圖像閾值化是圖像處理的重要基礎部分, 應用很廣泛, 可以根據灰度差異來分割圖像不同部分
閾值化處理的圖像一般爲單通道圖像(灰度圖)
閾值化參數的設置可以使用滑動條來debug
閾值化處理易光照影響, 處理時應注意
本節主要介紹的圖像閾值化函數方法:
固定閾值:threshold()
自適應閾值:adaptiveThreshold()
1、固定閾值---threshold()
給定閾值進行閾值操作得到二值圖(0, 1兩類值), 可以過濾灰度值過大或過小的點函數原型:
src: 單通道圖像(灰度圖或二值圖)
dst: 輸出圖像要求和src一樣的尺寸和類型
thresh: 給定的閾值
maxval: 第五個參數設置爲CV_THRESH_BINARY或 CV_THRESH_BINARY_INV 閾值類型的最大值
第五個參數閾值類型取值如下:
ex1:
例:
srcImg = imread("0.bmp", 0); //以灰度模式讀取
threshold(srcImg, dstImg, 100, 255, CV_THRESH_BINARY);
threshold(srcImg, dstImg, 100, 255, CV_THRESH_BINARY_INV);
threshold(srcImg, dstImg, 100, 255, CV_THRESH_TRUNC);
threshold(srcImg, dstImg, 100, 255, CV_THRESH_TOZERO);
threshold(srcImg, dstImg, 100, 255, CV_THRESH_TOZERO_INV);
效果:
srcImg:
BINARY:
BINARY_INV:
TRUNC:
TOZERO:
TOZERO_INV:
2、自適應閾值---adaptiveThreshold()
對矩陣採用自適應閾值操作, 自適應閾值是根據像素的鄰域塊的像素值分佈來確定該像素位置上的二值化閾值
函數原型:
src: 單通道圖像(灰度圖或二值圖)
dst: 輸出圖像要求和src一樣的尺寸和類型
maxValue:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的 最大值
adaptiveMethod: 指定自適應閾值算法, 可取值爲CV_ADAPTIVE_THRESH_MEAN_C 或CV_ADAPTIVE_THRESH_GAUSSIAN_C
thresholdType: 取閾值類型取值必須爲CV_THRESH_BINARY、CV_THRESH_BINARY_INV二者之一
blockSize: 用來計算閾值的鄰域大小3, 5, 7,…
C: 減去平均或加權平均後的常數值
函數 adaptiveThreshold 將灰度圖像變換到二值圖像,採用下面公式:
其中T(x, y)爲分別計算每個單獨像素的閾值, 取值如下:
對方法 CV_ADAPTIVE_THRESH_MEAN_C, 先求出塊中的均值,再減掉C
對方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C, 先求出塊中的加權和(gaussian), 再減掉C
效果:
原圖:
高斯閾值:
中值閾值取反:
可見,高斯閾值對輪廓的特徵截取比較好。
例:
srcImg = imread("0.bmp", 0); //以灰度模式讀取
adaptiveThreshold(srcImg, dstImg, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 11, 5);
adaptiveThreshold(srcImg, dstImg, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 11, 5);
#include "opencv2/opencv.hpp"
using namespace cv;
Mat srcImg, dstImg;
Mat dstImg2;
int thres_min = 20;
int block_size = 3;
int C0 = 3;
void OnThreshold(int, void* )
{
threshold(srcImg, dstImg, thres_min, 255, CV_THRESH_BINARY);
imshow("src", srcImg);
imshow("固定閾值", dstImg);
}
void OnAdaptiveThreshold(int, void* )
{
if(block_size % 2==0) //如果block_size是偶數
block_size++;
adaptiveThreshold(srcImg, dstImg2, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, block_size, C0);
imshow("自適應閾值", dstImg2);
}
void main()
{
srcImg = imread("0.bmp", 0); //以灰度模式讀取
medianBlur(srcImg, srcImg, 5);
namedWindow("固定閾值", CV_WINDOW_AUTOSIZE);
namedWindow("自適應閾值", CV_WINDOW_AUTOSIZE);
//cvtColor(srcImg, dstImg, CV_BGR2GRAY);
//threshold(srcImg, dstImg, 100, 255, CV_THRESH_BINARY);
//threshold(srcImg, dstImg, 100, 255, CV_THRESH_BINARY_INV);
//threshold(srcImg, dstImg, 100, 255, CV_THRESH_TRUNC);
//threshold(srcImg, dstImg, 100, 255, CV_THRESH_TOZERO);
//threshold(srcImg, dstImg, 100, 255, CV_THRESH_TOZERO_INV);
//adaptiveThreshold(srcImg, dstImg, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 11, 5);
//adaptiveThreshold(srcImg, dstImg, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 11, 5);
createTrackbar("Threshold", "固定閾值", &thres_min, 255, OnThreshold, 0);
createTrackbar("Block_Size", "自適應閾值", &block_size, 255,OnAdaptiveThreshold, 0);
createTrackbar("C", "自適應閾值", &C0, 255, OnAdaptiveThreshold, 0);
OnThreshold(thres_min, 0); //回調函數初始化
OnAdaptiveThreshold(block_size, 0);
OnAdaptiveThreshold(C0, 0);
//imshow("src", srcImg);
//imshow("dst", dstImg);
waitKey(0);
}