新浪博客

OTSU 算法(大津法)代码

2014-07-13 13:41阅读:
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。
[cpp] view plaincopy
  1. #include
  2. #include
  3. 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
  • {
  • pixelCount[data[i * image->widthStep + j]]++;
  • }
  • }
  • //计算每个像素在整幅图像中的比例
  • for(i = 0; i < 256; i++)
  • {
  • pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
  • }
  • //经典ostu算法,得到前景和背景的分割
  • //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
  • 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) //背景部分
  • {
  • //以i为阈值分类,第一类总的概率
  • w0 += pixelPro[j];
  • u0tmp += j * pixelPro[j];
  • }
  • else //前景部分
  • {
  • //以i为阈值分类,第二类总的概率
  • 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算法进行二值化后的图像。

我的更多文章

下载客户端阅读体验更佳

APP专享