OTSU算法对图像二值化

    xiaoxiao2021-03-25  61

    版权声明:本文为博主原创文章,未经博主允许不得转载。  转载请注明出处: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。 [cpp] view plain copy #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);      }        //经典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算法进行二值化后的图像。
    转载请注明原文地址: https://ju.6miu.com/read-39723.html

    最新回复(0)