有時候由於拍照時光線不均,所以影像每個區域的灰階值基準不同,這時很難找到一個閾值能適用整張影像,然後得到良好的二值化結果,這時我們可以將影像分成幾個區域,每個區域有各自的閾值,再分別將各個區域進行二值化,OpenCV用adaptiveThreshold()函式來進行此作法。
void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
src:輸入圖,只能輸入8位元單通道圖。dst:輸出圖,尺寸大小、深度會和輸入圖相同。maxValue:最大值,adaptiveThreshold會將像素分成0和maxValue。adaptiveMethod:區域閾值方法:可以選擇ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C,兩者決定閾值的方式不同。thresholdType:二值化型態:有THRESH_BINARY和THRESH_BINARY_INV兩種型態可選。blockSize:區域尺寸,用幾個像素來決定閾值,只能選擇奇數像3、5、7……等。C:常數,計算閾值時,要從平均或加權平均減去的數。adaptiveMethod:
ADAPTIVE_THRESH_MEAN_C:閾值為blockSize*blockSize像素內的平均減去C。ADAPTIVE_THRESH_GAUSSIAN_C:閾值為blockSize*blockSize像素內的高斯加權平均減去C。thresholdType:
THRESH_BINARY:超過閾值的像素設為maxvalue,小於閾值的設為0。THRESH_BINARY_INV:超過閾值的像素設為0,小於閾值的設為maxvalue。以下示範adaptiveThreshold的使用,並和otsu的結果做比較:
#include <cstdio> #include <opencv2/opencv.hpp> using namespace cv; int main(){ Mat src = imread("test.jpg",CV_LOAD_IMAGE_GRAYSCALE); Mat dst1; Mat dst2; threshold(src, dst1, 150, 255, THRESH_BINARY|THRESH_OTSU); adaptiveThreshold(src, dst2, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 65, 0); imshow("origin", src); imshow("threshold1", dst1); imshow("threshold2", dst2); waitKey(0); return 0; }转自:http://monkeycoding.com/?p=603