標籤:des style blog http color 使用 os io
局部自適應閾值二值化
相對全域閾值二值化,自然就有局部自適應閾值二值化,本文利用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枚舉類型
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。
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, ...)" );
個人感覺是影像處理演算法本身導致的,與編程無關。