基于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
实现的代码如下:
各处的像素值(图像为单通道),如图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; }效果如图所示:
相关文章推荐
- hadoop学习笔记
- 配置nginx、mysql、php-fpm的方法
- LINUx 信号摘要
- <转>Openstack Ceilometer监控项扩展
- #!/bin/sh与#!/bin/bash的区别
- 源码编译openssl(Linux/Win)
- 学习ios的网站
- 01 Linux档案与目录管理
- Shell反弹不出来怎么办呢? -- Metasploit-tunna
- 查看linux启动的线程信息
- CentOS7.1下生产环境Keepalived+Nginx配置
- Linux进程间通信——使用信号
- Linux下调整根目录的空间大小
- 【转】windows下nginx+mono+fastCGI部署asp.net网站
- 拓扑排序(topological-sort)
- 史上最全的Linux常用命令
- linux文件基本操作(2)
- 【转】玩玩负载均衡---在window与linux下配置nginx
- centos在root用户下不能使用ibus和mount的中文乱码
- shell与if相关参数