您的位置:首页 > 运维架构

基于opencv的一种局部自适应快速二值化方法(积分法)

2015-07-20 17:16 645 查看
由于用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

实现的代码如下:

void AdaptiveThereshold(Mat src,Mat dst)
{
cvtColor(src,dst,CV_BGR2GRAY);
int x1, y1, x2, y2;
int count=0;
long long sum=0;
int S=src.rows>>3;  //划分区域的大小S*S
int T=15;         /*百分比,用来最后与阈值的比较。原文:If the value of the current pixel is t percent less than this average
then it is set to black, otherwise it is set to white.*/
int W=dst.cols;
int H=dst.rows;
long long **Argv;
Argv=new long long*[dst.rows];
for(int ii=0;ii<dst.rows;ii++)
{
Argv[ii]=new long long[dst.cols];
}

for(int i=0;i<W;i++)
{
sum=0;
for(int j=0;j<H;j++)
{
sum+=dst.at<uchar>(j,i);
if(i==0)
Argv[j][i]=sum;
else
Argv[j][i]=Argv[j][i-1]+sum;
}
}

for(int i=0;i<W;i++)
{
for(int j=0;j<H;j++)
{
x1=i-S/2;
x2=i+S/2;
y1=j-S/2;
y2=j+S/2;
if(x1<0)
x1=0;
if(x2>=W)
x2=W-1;
if(y1<0)
y1=0;
if(y2>=H)
y2=H-1;
count=(x2-x1)*(y2-y1);
sum=Argv[y2][x2]-Argv[y1][x2]-Argv[y2][x1]+Argv[y1][x1];

if((long long)(dst.at<uchar>(j,i)*count)<(long long)sum*(100-T)/100)
dst.at<uchar>(j,i)=0;
else
dst.at<uchar>(j,i)=255;
}
}
for (int i = 0 ; i < dst.rows; ++i)
{
delete [] Argv[i];
}
delete [] Argv;
}
效果如图所示:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: