图像二值化

图像二值化

目录导航

简介

将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,首先,图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。其次,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像[1]

所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。

图像二值化图册图像二值化图册(3)

OpenCV

OpenCV中有两个函数可以实现图片的二值化:

(1)cvThreshold( dst, dst,230 , 255, CV_THRESH_BINARY_INV);

(2)cvAdaptiveThreshold( dst, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY, 9, -10);

方法(1)是手动指定一个阈值,以此阈值来进行二值化处理。其中的第四个参数决定了该方法的结果:

threshold_type=CV_THRESH_BINARY:

dst(x,y) = max_value, if src(x,y)>threshold 0, otherwise.

threshold_type=CV_THRESH_BINARY_INV:

dst(x,y) = 0, if src(x,y)>threshold; dst(x,y) = max_value, otherwise.

threshold_type=CV_THRESH_TRUNC:

dst(x,y) = threshold, if src(x,y)>threshold; dst(x,y) = src(x,y), otherwise.

threshold_type=CV_THRESH_TOZERO:

dst(x,y) = src(x,y), if (x,y)>threshold ; dst(x,y) = 0, otherwise.

threshold_type=CV_THRESH_TOZERO_INV:

dst(x,y) = 0, if src(x,y)>threshold ; dst(x,y) = src(x,y), otherwise.

值得一说的是threshold_type可以使用CV_THRESH_OTSU类型,这样该函数就会使用大律法OTSU得到的全局自适应阈值来进行二值化图片,而参数中的threshold不再起 作用。比如:cvThreshold( dst, dst,300 , 255, CV_THRESH_OTSU | CV_THRESH_BINARY_INV);这种方法对于灰度直方图呈现二峰特征的图片处理起来效果很好。

方法(2)是一个自适应阈值二值化方法,通过设定最后两个参数来调整效果。

原理

图像的二值化的基本原理

图像的二值化处理就是将图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阈值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阈值选取技术来分割该图像。动态调节阈值实现图像的二值化可动态观察其分割图像的具体结果。

程序实现

通过Delphi刻度控件调整阈值,实现动态控制,程序如下:

procedure TForm1.Button1Click(Sender: TObject);

var

p:PByteArray;

Gray,x,y:integer;

begin

TestBMP:=TBitmap.Create; changedbmp:=tbitmap.Create;

testbmp.Assign(image1.Picture);

for y:=0 to testbmp.Height-1 do

begin

p:=testbmp.ScanLine[y];

for x:=0 to testbmp.Width-1 do

begin

gray:=round(p[x*3+2]*0.3+p[x*3+1]*0.59+p[x*3]*0.11);

if gray> TrackBar1.Position then

begin

p[x*3]:=255; p[x*3+1]:=255; p[x*3+2]:=255;

end

else

begin

p[x*3]:=0;p[x*3+1]:=0;p[x*3+2]:=0;

end;

end;

end;

ChangedBmp.Assign(TestBMP);

PaintBox1.Canvas.CopyMode:=srccopy;

PaintBox1.Canvas.Draw(0,0,ChangedBmp);

end;[2]

算法比较

1:OTSU

OTSU的中心思想是阈值T应使目标与背景两类的类间方差最大。

//用类间方差最大思想计算阈值

int Threshold(int *hist) //compute the threshold

{

float u0, u1;

float w0, w1;

int count0;

int t, maxT;

float devi, maxDevi = 0; //方差及最大方差

int i;

int sum = 0;

for (i = 0; i < 256; i++)

{

sum = sum + hist[i];

}

for (t = 0; t < 255; t++)

{

u0 = 0; count0 = 0;

//阈值为t时,c0组的均值及产生的概率

for (i = 0; i <= t; i++)

{

u0 += i * hist[i]; count0 += hist[i];

}

u0 = u0 / count0; w0 = (float)count0/sum;

//阈值为t时,c1组的均值及产生的概率

u1 = 0;

for (i = t + 1; i < 256; i++)

{

u1 += i * hist[i];

}

u1 = u1 / (sum - count0); w1 = 1 - w0;

//两类间方差

devi = w0 * w1 * (u1 - u0) * (u1 - u0);

//记录最大的方差及最佳位置

if (devi > maxDevi)

{

maxDevi = devi;

maxT = t;

}

}

return maxT;

}

//二值化处理

void OTSU(IplImage *src, IplImage *dst)

{

int i = 0, j = 0;

int wide = src->widthStep;

int high = src->height;

int hist[256] = {0};

int t;

unsigned char *p, *q;

for (j = 0; j < high; j ++)

{

p = (unsigned char *)(src->imageData + j * wide);

for (i = 0; i < wide; i++)

{

hist[p[i]]++; //统计直方图

}

}

t = Threshold(hist);

for (j = 0; j < high; j ++)

{

q = (unsigned char *)(dst->imageData + j * wide);

p = (unsigned char *)(src->imageData + j * wide);

for (i = 0; i < wide; i++)

{

q[i] = p[i] >= t ? 255 : 0;

}

}

}

OTSU算法对不均匀光照的图片不能产生很好的效果。

2:Kittle

另外一个Kittler算法,是一种快速的全局阈值法。它的效果不比OTSU差多少,但速度快好多倍,如果可以应用在图像质量不错的环境。

它的中心思想是,计算整幅图像的梯度灰度的平均值,以此平均值做为阈值。

//kittler算法

for (i=1;i

{

plineadd=src->imageData+i*wide;

pNextLine=src->imageData+(i+1)*wide;

pPreLine=src->imageData+(i-1)*wide;

for(j=1;j

{

//求水平或垂直方向的最大梯度

Grads=MAX(abs((uchar)pPreLine[j]-(uchar)pNextLine[j]),abs((uchar)plineadd[j-1]-(uchar)plineadd[j+1])); //max(xGrads,yGrads)

sumGrads += Grads;

//梯度与当前点灰度的积

sumGrayGrads += Grads*((uchar)plineadd[j]);

}

}

threshold=sumGrayGrads/sumGrads;

// printf("%d\n",threshold);

for(i=0;i

{

plineadd=src->imageData+i*wide;

pTempLine=kittler->imageData+i*wide;

for(j=0;j

{

pTempLine[j]=(uchar)plineadd[j]>threshold?255:0;[3]

}

}

相关百科
返回顶部
产品求购 求购