一种改进的OPenCV局部 自适应快速二值化

来源:互联网 发布:mysql 最近10条记录 编辑:程序博客网 时间:2024/05/19 03:20

由于用opencv自带的函数adaptiveThreshold()在光照不均匀的图像中进行二值化时,效果不佳,之后看了Derek Bradley和Gerhard Roth于2007年写的《Adaptive Thresholding Using the Integral Image》,方法简单实现简便且速度较快,本文基于opencv用程序实现了它。其核心思想可以由下面两张图概括,先得到图像中

各处的像素值(图像为单通道),如图1左。之后得到每个点的左上方所有点的像素值之和(包括该点)并可用一个二维数组暂时存储,如图一右所示,例如,第二行第二列中9=4+0+4+1,第二行第三列中12=4+1+2+4+1。一般地,所谓二值化就是给定一个阈值,当图像中某一点的像素值大于阈值时令它的像素为255(0),像素值小于阈值时为0(255)。而所谓区域二值化,就是把图片划分为若干的区域,每个区域有各自的阈值,再分别判定。



                                                             图1  

如图2所示,我们要判定区域D时,就可以利用图1右的表,设P(x,y)为点(x,y)的像素值(已转换为图一右的值),对于区域D有,P(D)=P(x2,y2)-P(x2,y1)-P(x1,y2)+P(x1,y1),得到区域D的总阈值,再除以区域D的像素点个数得到平均阈值P=P(D)/N,对于区域中心点(i,j)若P(i,j)>P,则重写点(i,j)的像素为255(0),反之为0(255)。


                                                     图2

实现的代码如下:

[cpp] view plain copy
print?
  1. void AdaptiveThereshold(Mat src,Mat dst)  
  2. {  
  3.     cvtColor(src,dst,CV_BGR2GRAY);  
  4.     int x1, y1, x2, y2;  
  5.     int count=0;  
  6.     long long sum=0;  
  7.     int S=src.rows>>3;  //划分区域的大小S*S  
  8.     int T=15;         /*百分比,用来最后与阈值的比较。原文:If the value of the current pixel is t percent less than this average  
  9.                             then it is set to black, otherwise it is set to white.*/  
  10.     int W=dst.cols;  
  11.     int H=dst.rows;  
  12.     long long **Argv;  
  13.     Argv=new long long*[dst.rows];  
  14.     for(int ii=0;ii<dst.rows;ii++)  
  15.     {  
  16.         Argv[ii]=new long long[dst.cols];  
  17.     }  
  18.   
  19.     for(int i=0;i<W;i++)  
  20.     {  
  21.         sum=0;  
  22.         for(int j=0;j<H;j++)  
  23.         {             
  24.             sum+=dst.at<uchar>(j,i);  
  25.             if(i==0)      
  26.                 Argv[j][i]=sum;  
  27.             else  
  28.                 Argv[j][i]=Argv[j][i-1]+sum;  
  29.         }  
  30.     }  
  31.       
  32.     for(int i=0;i<W;i++)  
  33.     {  
  34.         for(int j=0;j<H;j++)  
  35.         {  
  36.             x1=i-S/2;  
  37.             x2=i+S/2;  
  38.             y1=j-S/2;  
  39.             y2=j+S/2;  
  40.             if(x1<0)  
  41.                 x1=0;  
  42.             if(x2>=W)  
  43.                 x2=W-1;  
  44.             if(y1<0)  
  45.                 y1=0;  
  46.             if(y2>=H)  
  47.                 y2=H-1;  
  48.             count=(x2-x1)*(y2-y1);  
  49.             sum=Argv[y2][x2]-Argv[y1][x2]-Argv[y2][x1]+Argv[y1][x1];  
  50.               
  51.   
  52.             if((long long)(dst.at<uchar>(j,i)*count)<(long long)sum*(100-T)/100)  
  53.                 dst.at<uchar>(j,i)=0;  
  54.             else  
  55.                 dst.at<uchar>(j,i)=255;  
  56.         }  
  57.     }  
  58.             for (int i = 0 ; i < dst.rows; ++i)  
  59.        {  
  60.          delete [] Argv[i];   
  61.        }  
  62.          delete [] Argv;  
  63. }  
效果如图所示:


阅读全文
0 0
原创粉丝点击