局部自适应阈值二值化html
相对全局阈值二值化,天然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并经过调节block大小,实现图像的边缘检测。算法
1、理论概述(转载自《OpenCV_基于局部自适应阈值的图像二值化》)编程
局部自适应阈值则是根据像素的邻域块的像素值分布来肯定该像素位置上的二值化阈值。这样作的好处在于每一个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。亮度较高的图像区域的二值化阈值一般会较高,而亮度较低的图像区域的二值化阈值则会相适应地变小。不一样亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。经常使用的局部自适应阈值有:1)局部邻域块的均值;2)局部邻域块的高斯加权和。 函数
2、程序实现spa
一、关键函数.net
关键函数 CvInvoke.cvAdaptiveThreshold Method3d
函数功能:code
Transforms grayscale image to binary image. Threshold calculated individually for each pixel. For the method CV_ADAPTIVE_THRESH_MEAN_C it is a mean of blockSize x blockSize pixel neighborhood, subtracted by param1. For the method CV_ADAPTIVE_THRESH_GAUSSIAN_C it is a weighted sum (gaussian) of blockSize x blockSize pixel neighborhood, subtracted by param1.orm
函数原型:htm
public static void cvAdaptiveThreshold(
IntPtr src,
IntPtr dst,
double maxValue,
ADAPTIVE_THRESHOLD_TYPE adaptiveType,
THRESH thresholdType,
int blockSize,
double param1
)
第一个参数src表示输入图像,必须为单通道灰度图。
第二个参数dst表示输出的边缘图像,为单通道黑白图。
第三个参数maxValue表示采用CV_THRESH_BINARY 和CV_THRESH_BINARY_INV门限类型的最大值。
第四个参数adaptiveType表示局部二值化阈值的取值方法,自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C
或 CV_ADAPTIVE_THRESH_GAUSSIAN_C,
ADAPTIVE_THRESHOLD_TYPE枚举类型
Member name | Value | Description |
---|---|---|
CV_ADAPTIVE_THRESH_MEAN_C | 0 | indicates that "Mean minus C" should be used for adaptive threshold. |
CV_ADAPTIVE_THRESH_GAUSSIAN_C | 1 | indicates that "Gaussian minus C" should be used for adaptive threshold. |
第五个参数thresholdType表示取阈值类型:必须是下者之一
CV_THRESH_BINARY,
CV_THRESH_BINARY_INV
第六个参数block_size表明用来计算阈值的象素邻域大小,例如:3,5,7…
第七个参数表示均值或高斯加权平均值所须要减去的一个常数,相似一我的工干预的阈值调整。
对方法 CV_ADAPTIVE_THRESH_MEAN_C,先求出块中的均值,再减掉param1。
对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C ,先求出块中的加权和(gaussian), 再减掉param1。
二、编程实现
采用均值法设定局部适应阈值,块大小为25,参数取值为5.
//局部二值化 Image<Gray, Byte> adaptivethreshimg = new Image<Gray, Byte>(graymi.width, graymi.height); CvInvoke.cvAdaptiveThreshold(grayimg, adaptivethreshimg, 255, Emgu.CV.CvEnum.ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_MEAN_C, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY, 25, 5); pictureBox4.Image = adaptivethreshimg.ToBitmap();
采用本文算法获取的二值化图像
第五个参数本文用的是Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY,恰好与原文相反,所以一个是白底,一个是黑底。
转载请标明出处,原文地址:http://www.cnblogs.com/MobileBo/p/3923599.html
3、结果分析
一、边缘提取做用
有人提出cvAdaptiveThreshold的做用不是二值化而是提取对象边缘的观点
参考文献:http://wuyiwangyi.blog.163.com/blog/static/3214949520093834537412/
关键是里面的block_size参数,该参数是决定局部阈值的block的大小,当block很小时,如block_size=3 or 5 or 7时,“自适应”的程度很高,即容易出现block里面的像素值都差很少,这样便没法二值化,而只能在边缘等梯度大的地方实现二值化,结果显得它是边缘提取函数。当把block_size设为比较大的值时,如block_size=21 or 31 or 41时,cvAdaptiveThreshold即是二值化函数啦~
二、block_size取值问题
编程过程当中,发现block_size通常取奇数,若是取偶数会报错,错误内容是"blockSize % 2 == 1 && blockSize > 1"。固然,编程文档说明提示是3,5,7,...,并无要求是奇数,是这种算法在原理上就要这么要求吗?仍是编程须要?我没法解答。
网上说源代码要求就是 if( size <= 1 || (size&1) == 0 )
CV_ERROR( CV_StsOutOfRange, "Neighborhood size must be >=3 and odd (3, 5, 7, ...)" );
我的感受是图像处理算法自己致使的,与编程无关。 原文:http://www.cnblogs.com/MobileBo/p/3923599.html