NiBlack二值化演算法和區域性均值法

無臉男發表於2017-04-06
Niblack二值化演算法是比較簡單的區域性閾值方法,閾值的計算公式是T = m + k*v,其中m為以該畫素點為中心的區域的平均灰度值,v是該區域的標準差,k是一個修正係數  

這幾天在研究靜脈的影像二值化,然後百度了幾次無果,要不然就是效果差,達不到心中的期待值。所以打算自己動手造一下輪子。

首先我用了區域性均值法,效果挺棒的。廢話不多說,看程式碼;  


void Mean_method(BYTE *image_in, BYTE *image_out, int xsize, int ysize)
{
/*////////////////////////////////////////////////////////////////////
// 作者:楊魁
//引數列表:
//image_in            輸入影像的指標
//image_out        輸出影像的指標
//xsize                影像的寬
//ysize                影像的高
////////////////////////////////////////////////////////////////////*/
int sum = 0;
int i, j, h, k;;//用於迴圈
int T = 0;//閾值
int num = 0;//用於自加
int w_size = 7;//視窗大小為2*w_size+1
int Area = (2 * w_size + 1)*(2 * w_size + 1);
int *d = (int *)malloc(sizeof(int)*Area);//陣列空間

for (j = w_size; j < ysize - w_size; j++)
{
    for (i = w_size; i < xsize - w_size; i++)
    {
        sum = 0;
        num = 0;
        for (h = 0; h < 2 * w_size + 1; h++)
        {
            for (k = 0; k < 2 * w_size + 1; k++)
            {
                d[num++] = GetGray(image_in, xsize, i + w_size - k, j + w_size - h);
            }
        }
        for (h = 0; h < Area; h++)
        {
            sum += d[h];
        }
        T = sum / Area;
        *(image_out + j *xsize + i) = *(image_in + j *xsize + i) > T ? 255 : 0;
    }
}
free(d);
}  

我寫的比較簡單。例如邊緣我直接沒有處理。待我慢慢改進。處理的影像效果如下。 enter image description here 效果不錯吧。

然後我又換了一種被叫做Niblack的演算法。程式碼如下:
void NiBlack(BYTE *image_in, BYTE *image_out, int xsize, int ysize)
{
/*////////////////////////////////////////////////////////////////////
// 作者:楊魁
//引數列表:
//image_in            輸入影像的指標
//image_out        輸出影像的指標
//xsize                影像的寬
//ysize                影像的高
////////////////////////////////////////////////////////////////////*/

int sum = 0;
int i, j, h, k;;//用於迴圈
int Average = 0;//平均值
int num = 0;//用於自加
int w_size = 7;//視窗大小為2*w_size+1
int Area = (2 * w_size + 1)*(2 * w_size + 1);
int *d = (int *)malloc(sizeof(int)*Area);//陣列空間
int T = 0;//閾值
int S = 0;//標準差

for (j = w_size; j < ysize - w_size; j++)
{
    for (i = w_size; i < xsize - w_size; i++)
    {
        sum = 0;
        num = 0;
        for (h = 0; h < 2 * w_size + 1; h++)
        {
            for (k = 0; k < 2 * w_size + 1; k++)
            {
                d[num++] = GetGray(image_in, xsize, i + w_size - k, j + w_size - h);        //求area領域內的畫素值
            }
        }
        for (h = 0; h <Area; h++)
        {
            sum += d[h];//求總和
        }
        Average = sum / Area;
        sum = 0;
        for (h = 0; h < Area; h++)
        {
            sum += (d[h] * d[h]);
        }
        S = sqrt((float)sum);
        S = S / Area;
         T = Average + 0.05*S;//確定閾值
        *(image_out + j *xsize + i) = *(image_in + j *xsize + i) > T ? 255 : 0;
    }
}
free(d);

}

效果如下: enter image description here

感覺並沒有變化,可能是我修正係數設定的不好。好了,就寫這麼多。我封裝了一個MyDib類,和一些常用的影像處理的演算法。如果感興趣可以一起來完善。
** 簡單的bmp圖片操作類和常用的影像處理函式**

相關文章