void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C);
函數功能
對一幅灰度圖像進行二值化,該函數支持就地操作,該函數用下面的公式對一幅灰度圖像進行二值化:
(1)正向二值化,THRESH_BINARY

(2)反向二值化,THRESH_BINARY_INV

參數詳解
-
第一個參數,InputArray src,原圖,即輸入圖像,是一個8位單通道的圖像;
-
第二個參數,OutputArray dst,目標圖像,與原圖像具有同樣的尺寸與類型;
-
第三個參數,double maxValue,分配給滿足條件的像素的非零值;
-
第四個參數,int adaptiveMethod,自適應閾值的方法,通常有以下幾種方法;
- ADAPTIVE_THRESH_MEAN_C,閾值T(x,y)是(x,y)減去C的Blocksize×Blocksize鄰域的平均值。
- ADAPTIVE_THRESH_GAUSSIAN_C ,閾值T(x,y)是(x,y)減去C的Blocksize×Blocksize鄰域的加權和(與高斯相關),默認sigma(標准差)用於指定的Blocksize;具體的情況可以參見getGaussianKernel函數;
- 第五個參數,int thresholdType,閾值的類型必須是以下兩種類型,
- THRESH_BINARY,正向二值化
- THRESH_BINARY_INV ,反向二值化
-
第六個參數,int blockSize,計算blocksize x blocksize大小的領域內的閾值,必須為奇數,例如,3,5,7等等,一般二值化使用21,31,41;
-
第七個參數,double C,從平均數或加權平均數減去常量。通常,它是正的,但也可能是零或負數。,二值化時使用的7。
閾值類型詳解

(1)THRESH_BINARY
正向二值化,如果當前的像素值大於設置的閾值(thresh),則將該點的像素值設置為maxval;否則,將該點的像素值設置為0;具體的公式如下

(2)THRESH_BINARY_INV
反向二值化,如果當前的像素值大於設置的閾值(thresh),則將該點的像素值設置為0;否則,將該點的像素值設置為maxval,具體的公式如下

(3)THRESH_TRUNC
如果當前的像素值大於設置的閾值(thresh),則將該點的像素值設置為threshold;否則,將該點的像素值不變,具體的公式如下

(4)THRESH_TOZERO
如果當前的像素值大於設置的閾值(thresh),則將該點的像素值不變;否則,將該點的像素值設置為0,具體的公式如下

(5)THRESH_TOZERO_INV
如果當前的像素值大於設置的閾值(thresh),則將該點的像素值設置為0;否則,將該點的像素值不變,具體的公式如下

(6)THRESH_MASK
(7)THRESH_OTSU,使用Otsu算法選擇最佳閾值。
(8)THRESH_TRIANGLE,使用三角算法選擇最佳閾值。
補充
1、函數cvAdaptiveThreshold的確可以將灰度圖像二值化,但它的主要功能應該是邊緣提取,並且參數param1主要是用來控制邊緣的類型和粗細的1
關鍵是里面的block_size參數,該參數是決定局部閾值的block的大小,
1)當block很小時,如block_size=3 or 5 or 7時,“自適應”的程度很高,即容易出現block里面的像素值都差不多,這樣便無法二值化,而只能在邊緣等梯度大的地方實現二值化,結果顯得它是邊緣提取函數。
2)當把block_size設為比較大的值時,如block_size=21 or 31 or 41時,cvAdaptiveThreshold便是二值化函數了
3)src與dst 這兩個都要是單通道的圖像。
分析參數blockSize。這個參數相當重要,
1.要取奇數,如果取偶數運行后就會報錯!!原因看源碼,發現要做一個掩模,所以參數必須是奇數。OpenCV也做了一個檢測,在函數adaptiveThreshold一開始就有CV_Assert( blockSize % 2 == 1 && blockSize > 1 )。
2.cvAdaptiveThreshold既可以做邊緣提取,也可以實現二值化,是由你所選擇的鄰域所確定的,如果你所選擇的鄰域非常小(比如3×3),那么很顯然閾值的“自適應程度”就非常高,這在結果圖像中就表現為邊緣檢測的效果。如果鄰域選擇的比較大(比如31×31),那么閾值的“自適應程度”就比較低,這在結果圖像中就表現為二值化的效果。
3.一般情況下,濾波器寬度應該大於被識別物體的寬度。block_size太小,無法代表背景,太大的話會影響到臨近物體。
選定合適的block_size后,我們就可以選定一個更大的閾值param1,更好的抑制噪聲