1. OpenCV C++(四)----對比度增強
對比度增強或者稱為對比度拉伸就是圖像增強技術的一種,它主要解決由於圖像的灰度級范圍較小造成的對比度較低的問題,目的就是將輸出圖像的灰度級放大到指定的程度,使得圖像中的細節看起來更加清晰。對比 度增強有幾種常用的方法,如線性變換、分段線性變換、伽馬變換、直方圖正規化、直方圖均衡化、局部自適應直方圖均衡化等。
灰度直方圖是圖像灰度級的函數, 用來描述每個灰度級在圖像矩陣中的像素個數或者佔有率(概率)。
OpenCV提供了函數 calcHist 來實現直方圖的構建,但是在計算8點陣圖的灰度直方圖 時,它使用起來略顯復雜。下面是OpenCV源碼
可以定義函數 calcGrayHist 來計算灰度直方圖,其中輸入參數為8點陣圖,將返回的灰度直方圖存儲為一個1行256列的 Mat 類型。
圖像對比度是通過灰度級范圍來度量的,而灰度級范圍可通過觀察灰度直方圖得到,灰度級范圍越大代表對比度越高;反之,對比度越低,低對比度的圖像在視覺上給人的感覺是看起來不夠清晰,所以通過演算法調整圖像的灰度值,從而調整圖像的對比度是有必要的。最簡單的一種對比度增強方法是通過灰度值的線性變換來實現的。
當a=1,b=0時,O為I的一個副本;如果a>1,則輸出圖像O的對 比度比I 有所增大;如果0<a< 1,則O的對比度比I有所減小。而b值的改變,影響的是輸出圖像的亮度,當b> 0時,亮度增加;當b<0時,亮度減小。
在OpenCV中實現一個常數與矩陣相乘有多種方式。
1、convertTo
註:當輸出矩陣的數據類型是 CV_8U 時, 大於255的值會自動截斷為255
2、矩陣乘法運算
使用乘法運算符「*」, 無論常數是什麼數據類型, 輸出矩陣的數據類型總是和輸入矩陣的數據類型相同,當數據類型是 CV_8U 時,在返回值中將大於255的值自動截斷為255。
3、convertScaleAbs
直方圖正規化是一種自動選取a和b的值的線性變換方法。
利用 minMaxLoc 函數不僅可以計算出矩陣中的最大值和最小值, 而且可以求出最大 值的位置和最小值的位置。 當然,
在使用過程中如果只想得到最大值和最小值, 則將其 他的變數值設為 NULL 即可。
OpenCV提供的函數: normalize()
使用函數 normalize 對圖像進行對比度增強時, 經常令參數 norm_type=NORM_MINMAX , 和直方圖正規化原理詳解中提到的計算方法是相同的, 參數 alpha 相當於 Omax , 參數 beta 相當於 Omin 。 注意, 使用 normalize 可以處理多通道矩陣, 分別對每一個通道進行正規化操作。
非線性變換 。
假設輸入圖像為I,寬為W、 高為H,首先將其灰度值歸一化到[0,1]范圍,對於8位 圖來說,除以255即可。 I (r, c) 代表歸一化後的第r行第c列的灰度值, 輸出圖像記為 O, 伽馬變換就是令 O(r, c) =I(r, c) γ , 0≤r<H, 0≤c< W,
當γ=1時, 圖像不變。 如果圖像整體或者感興趣區域較暗, 則令0< γ< 1可以 增加圖像對比度; 相反, 如果圖像整體或者感興趣區域較亮, 則令γ>1可以降低圖像對比度。
伽馬變換在提升對比度上有比較好的效果, 但是需要手動調節γ值。
全局直方圖均衡化操作是對圖像I進行改變, 使得輸出圖像O的灰度直方圖 hist O 是「平」的, 即每一個灰度級的像素點個數是「相等」的。 注意,其實這里的「相等」不是嚴格意義上的等於, 而是約等於,
上述分別為I和O的累加直方圖
總結,對於直方圖均衡化的實現主要分四個步驟:
OpenCV實現的直方圖均衡化函數 equalize-Hist , 其使用方法很簡單, 只支持對 8點陣圖 的處理。
雖然全局直方圖均衡化方法對提高對比度很有效,但是均衡化處理以後暗區域的雜訊可能會被放大,變得清晰可 見,而亮區域可能會損失信息。為了解決該問題, 提出了自適應直方圖均衡化(Aptive Histogram Equalization) 方法。
自適應直方圖均衡化首先將圖像劃分為不重疊的區域塊(tiles) ,然後對每一個塊分別進行直方圖均衡化。 顯然, 在沒有雜訊影響的情況下, 每一個小區域的灰度直方圖會被限制在一個小的灰度級范圍內; 但是如果有雜訊, 每一個分割的區域塊執行直方圖均衡化後, 雜訊會被放大。為了避免出現雜訊這種情況, 提出了「限制對比度」(Contrast Limiting) [3],如果直方圖的bin超過了提前預設好的「限制對比度」, 那麼會被裁減, 然 後將裁剪的部分均勻分布到其他的bin, 這樣就重構了直方圖。
OpenCV提供的函數 createCLAHE 構建指向 CLAHE 對象的指針, 其中默認設置「限制 對比度」為40,塊的大小為8×8。
2. 你好,請問您怎麼用opencv檢測一幅圖片的邊緣,主要是怎麼進行圖片平滑還有怎麼應用Prewitt運算元、sobel!
說說我的做法~
在提取邊緣時,前處理工作很重要!且,噪音全都去掉是比較困難的是
1.可以先做平滑cvSmooth,去除噪音
2.可以用正規化或者直方圖均衡化來處理圖像像素~
3.用CLAHE演算法,增加對比度
4.prewitt,sobel,運算元都不是很精確,canny運算元雖比較好但是不能提取封閉輪廓。你可以用snake,或者GVFsnake來動態提取邊緣,但是之前得提取初始邊緣。
以上,如果你想用prewitt,sobel的話可以到opencv論壇去搜索,答案有很多。
http://www.opencv.org.cn/index.php/%E9%A6%96%E9%A1%B5這是論壇
http://www.opencv.org.cn/index.php/Canny%E8%BE%B9%E7%BC%98%E6%A3%80%E6%B5%8B這是canny檢測的例子
http://fsa.ia.ac.cn/opencv-doc-cn/opencv-doc-cn-0.9.7/ref/opencvref_cv.cn.htm這是函數的用法
祝你成功