图像二值化算法是图像处理的基础。一般来说,二值化算法可以分为两个类别:全局二值化和局部二值化。全局二值化是指通过某种算法找到一个全局的阈值T,对图像中坐标为(x,y)的像素值做如下处理:
Ostu就是这样一种全局二值化算法,又叫最大类间方差。因为该算法会遍历图像中任意一个像素值i,计算当其为阈值时,图像的前景和背景图像(并不一定是真正的前景和背景,只是我们把当前小于i的记做背景,大于i的记做前景)的方差值。当方差值达到最大时,我们认为此时的i是该图像的全局阈值。
符号说明:
前景点数占图像比例:w0;平均灰度:u0
背景点数占图像比例:w1,平局灰度:u1
图像平均灰度:
前景和背景图像方差:
C++代码:
int ostu(Mat image) { cvtColor(image.clone(),image,CV_RGB2GRAY); int width = image.cols; int height = image.rows; int x=0,y=0; float ip1,ip2,is1,is2,w0,w1,mean1,mean2,mean,deltaTmp,deltaMax; int pixelCount[256]; int i, j, pixelSum = width * height, thres = 0; for(i = 0; i < 256; i++) { pixelCount[i] = 0; } int pixel=0; for(i = 0; i < height; i++) { for(j = 0;j <width;j++) { pixel=image.at<uchar>(i,j); pixelCount[pixel]++; } } //经典ostu算法,得到前景和背景的分割 //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值 deltaMax=0; for(i = 0; i < 256; i++) { ip1=ip2=is1=is2=w0=w1=mean1=mean2=mean=deltaTmp=0; for(j = 0; j < 256; j++) { if(j <= i) //背景部分 { ip1+=pixelCount[j]*j; is1+=pixelCount[j]; } else { ip2+=pixelCount[j]*j; is2+=pixelCount[j]; } } mean1=ip1/is1; //第一类像素平均灰度值 w0=(float)is1/(float)pixelSum;//第一类像素占整个图像比例 mean2=ip2/is2; w1=1-w0; mean=w0*mean1+w1*mean2; deltaTmp=w0*w1*(mean1-mean2)*(mean1-mean2);//灰度值为i的阈值的类间方差 if (deltaTmp>deltaMax) { deltaMax=deltaTmp; thres=i; } } return thres; }