[转载+原创]Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化
局部自適應閾值二值化
相對全局閾值二值化,自然就有局部自適應閾值二值化,本文利用Emgu CV實現局部自適應閾值二值化算法,并通過調節block大小,實現圖像的邊緣檢測。
一、理論概述(轉載自《OpenCV_基于局部自適應閾值的圖像二值化》)
? ? 局部自適應閾值則是根據像素的鄰域塊的像素值分布來確定該像素位置上的二值化閾值。這樣做的好處在于每個像素位置處的二值化閾值不是固定不變的,而是由其周圍鄰域像素的分布來決定的。亮度較高的圖像區域的二值化閾值通常會較高,而亮度較低的圖像區域的二值化閾值則會相適應地變小。不同亮度、對比度、紋理的局部圖像區域將會擁有相對應的局部二值化閾值。常用的局部自適應閾值有:1)局部鄰域塊的均值;2)局部鄰域塊的高斯加權和。?
二、程序實現
1、關鍵函數
關鍵函數 CvInvoke.cvAdaptiveThreshold Method
函數功能:
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.
函數原型:
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枚舉類型
| 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。
?2、編程實現
采用均值法設定局部適應閾值,塊大小為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();?
與《OpenCV_基于局部自適應閾值的圖像二值化》比對
采用本文算法獲取的二值化圖像
第五個參數本文用的是Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY,剛好與原文相反,因此一個是白底,一個是黑底。
轉載請標明出處,原文地址:http://www.cnblogs.com/MobileBo/p/3923599.html?
三、結果分析
1、邊緣提取作用
有人提出cvAdaptiveThreshold的作用不是二值化而是提取對象邊緣的觀點
參考文獻:http://wuyiwangyi.blog.163.com/blog/static/3214949520093834537412/
?? ? ? ? ? ? 《關于cvAdaptiveThreshold的一點收獲》
關鍵是里面的block_size參數,該參數是決定局部閾值的block的大小,當block很小時,如block_size=3 or 5 or 7時,“自適應”的程度很高,即容易出現block里面的像素值都差不多,這樣便無法二值化,而只能在邊緣等梯度大的地方實現二值化,結果顯得它是邊緣提取函數。當把block_size設為比較大的值時,如block_size=21 or 31 or 41時,cvAdaptiveThreshold便是二值化函數啦~
2、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, ...)" );
個人感覺是圖像處理算法本身導致的,與編程無關。?
轉載于:https://www.cnblogs.com/MobileBo/p/3923599.html
總結
以上是生活随笔為你收集整理的[转载+原创]Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 纯c gSoap实现WebService
- 下一篇: Javascript数字前补零的功能