區域性二值化adaptiveThreshold
影象閾值化的一般目的是從灰度影象中分享目標區域和背景區域,然而僅僅通過設定固定閾值(固定閾值的求解可點此檢視我寫的博文)很難達到理想的分割效果。在實際應用中,我們可以通過某個畫素的鄰域以某種方法確定這個畫素應該具有的閾值,進而保證影象中各個畫素的閾值會隨著週期圍鄰域塊的變化而變化。在灰度影象中,灰度值變化明顯的區域往往是物體的輪廓,所以將影象分成一小塊一小塊的去計算閾值往往會得出影象的輪廓,而固定閾值的方法就不行,可以把本文的結果和用固定閾值法進行二值化的結果作下對比,很容易發現這一點!(我下面作了對比哦)
OpenCV中提供了自適應閾值化函式adaptiveThreshold來實現自適應閾值處理、
函式adaptiveThreshold的原型如下:
C++: void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
點此檢視官方的說明!
這裡我對各引數作一箇中文說明!
InputArray src:源影象
OutputArray dst:輸出影象,與源影象大小一致
int adaptiveMethod:在一個鄰域內計算閾值所採用的演算法,有兩個取值,分別為 ADAPTIVE_THRESH_MEAN_C 和 ADAPTIVE_THRESH_GAUSSIAN_C 。
ADAPTIVE_THRESH_MEAN_C的計算方法是計算出領域的平均值再減去第七個引數double C的值
ADAPTIVE_THRESH_GAUSSIAN_C的計算方法是計算出領域的高斯均值再減去第七個引數double C的值
int thresholdType:這是閾值型別,只有兩個取值,分別為 THRESH_BINARY 和THRESH_BINARY_INV 具體的請看官方的說明,這裡不多做解釋
int blockSize:adaptiveThreshold的計算單位是畫素的鄰域塊,鄰域塊取多大,就由這個值作決定
double C:在對引數int adaptiveMethod的說明中,我已經說了這個引數的作用,從中可以看出,這個引數實際上是一個偏移值調整量
從上面的說明中可以看出,使用函式adaptiveThreshold的關鍵是確定blockSize和C的值,明白了這兩個值的意義之後,在實際專案中,應該可以根據試驗法選出較為合適的值吧!
下面是一個例項的原始碼(原始碼中用到的影象的下載連結為 http://pan.baidu.com/s/1dFhVUpF):
//OpenCV版本2.4.9
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
int main( )
{
// 影象讀取及判斷
cv::Mat srcImage = cv::imread("hand1.jpg");
if( !srcImage.data )
return 1;
// 灰度轉換
cv::Mat srcGray;
cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
cv::imshow("srcGray", srcGray);
cv::Mat dstImage;
// 初始化自適應閾值引數
int blockSize = 5;
int constValue = 10;
const int maxVal = 255;
/* 自適應閾值演算法
0:ADAPTIVE_THRESH_MEAN_C
1: ADAPTIVE_THRESH_GAUSSIAN_C
閾值型別
0: THRESH_BINARY
1: THRESH_BINARY_INV */
int adaptiveMethod = 0;
int thresholdType = 1;
// 影象自適應閾值操作
cv::adaptiveThreshold(srcGray, dstImage,
maxVal, adaptiveMethod,
thresholdType, blockSize,
constValue);
cv::imshow("dstImage", dstImage);
cv::waitKey(0);
return 0;
}