转载请注明出处:http://blog.csdn.net/WuHaibing_CVer
OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。
1. OTSU算法原理简介
对于一幅图像,设当前景与背景的分割阈值为t时,前景点占图像比例为w0,均值为u0,背景点占图像比例为w1,均值为u1。则整个图像的均值为u = w0*u0+w1*u1。建立目标函数g(t)=w0*(u0-u)^2+w1*(u1-u)^2,g(t)就是当分割阈值为t时的类间方差表达式。OTSU算法使得g(t)取得全局最大值,当g(t)为最大时所对应的t称为最佳阈值。OTSU算法又称为最大类间方差法。
2.OTSU算法例程
下面是OSTU算法的C语言代码及其测试,代码基于opencv。
- #include <cv.h>
- #include <highgui.h>
-
- int otsu(IplImage *image)
- {
- assert(NULL != image);
-
- int width = image->width;
- int height = image->height;
- int x=0,y=0;
- int pixelCount[256];
- float pixelPro[256];
- int i, j, pixelSum = width * height, threshold = 0;
-
- uchar* data = (uchar*)image->imageData;
-
-
- for(i = 0; i < 256; i++)
- {
- pixelCount[i] = 0;
- pixelPro[i] = 0;
- }
-
-
- for(i = y; i < height; i++)
- {
- for(j = x;j <width;j++)
- {
- pixelCount[data[i * image->widthStep + j]]++;
- }
- }
-
-
-
- for(i = 0; i < 256; i++)
- {
- pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
- }
-
-
-
- float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;
- for(i = 0; i < 256; i++)
- {
- w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
-
- for(j = 0; j < 256; j++)
- {
- if(j <= i)
- {
-
- w0 += pixelPro[j];
- u0tmp += j * pixelPro[j];
- }
- else
- {
-
- w1 += pixelPro[j];
- u1tmp += j * pixelPro[j];
- }
- }
-
- u0 = u0tmp / w0;
- u1 = u1tmp / w1;
- u = u0tmp + u1tmp;
-
- deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
-
- if(deltaTmp > deltaMax)
- {
- deltaMax = deltaTmp;
- threshold = i;
- }
- }
-
- return threshold;
- }
-
- int main(int argc, char* argv[])
- {
- IplImage* srcImage = cvLoadImage("D:\\technology\\CV\\Database\\image\\rice.png",0);
- assert(NULL != srcImage);
-
- cvNamedWindow("src");
- cvShowImage("src",srcImage);
-
- IplImage* biImage = cvCreateImage(cvGetSize(srcImage),8,1);
-
-
- int threshold = otsu(srcImage);
-
- cvThreshold(srcImage,biImage,threshold,255,CV_THRESH_BINARY);
-
- cvNamedWindow("binary");
- cvShowImage("binary",biImage);
-
- cvWaitKey(0);
-
- cvReleaseImage(&srcImage);
- cvReleaseImage(&biImage);
- cvDestroyWindow("src");
- cvDestroyWindow("binary");
-
- return 0;
- }
下面是上述代码的运行结果图片。其中左边为原图像,右边为使用OTSU算法进行二值化后的图像。