對影象應用閾值建立二值影象,是提取有意義元素的好方法。但有的時候單一閾值達不到目標提取的效果。
下面比較一下幾種方法的效果。例如,給定一幅圖如下,將「富貴白頭」四個字提取出來。
通過opencv閾值化函式cv::threshold(),純手工選擇引數,進行固定閾值二值化,發現當閾值設為80時效果最好。
//採用固定閾值
cv::threshold(image, binaryfixed, 80, 255, cv::thresh_binary);
固定閾值(取為80)的效果,其實還行了,只不過閾值還是得手工微調:
採用最大類間方差法怎麼樣?自動選擇最優閾值(其實還是單一閾值)。
//大津法
std::cout
<70,255,cv::thresh_otsu);//經測試cout輸出為143
可見大津法算出的閾值為143。但是閾值化效果是很差的:
下面採用opencv的自適應閾值化方法:
cv::adaptivethreshold(image,binaryadaptive,255,cv::adaptive_thresh_mean_c,cv::thresh_binary,7,-4);
效果如下,還不錯,同時花樹的輪廓也描繪出了:
自適應閾值是一種區域性方法。它的原理是根據每個畫素的鄰域計算閾值,包括上面語句採用的將每個畫素的值與鄰域的平均值進行比較。如果某畫素的值與它的區域性平均值差別很大,就會被當做異常值在閾值化過程中被分離。
**實現:
1、使用積分影象實現自適應閾值化
//自己實現自定義閾值
cv::mat iimage;
cv::integral(image,iimage,cv_32s);
cv::mat binary;
image.copyto(binary);
int blocksize = 7;
int threshold = -4;//畫素將與(mean-threshold)比較
int halfsize = blocksize / 2;
for (int j = halfsize; j < image.rows-halfsize-1;j++)
}cv::imshow("thresholdadaptive",binary);
為了簡化計算,計算畫素周圍方形鄰域畫素的和,採用了積分影象。假設鄰域塊的大小為blocksize*blocksize,不採用積分影象,每次需要計算blocksize*blocksize次加法運算;而採用積分影象,運算複雜度並不隨鄰域大小而改變,每次只需計算2次加法和2次減法。
2、使用盒子濾波實現自適應閾值化
cv::mat filtered;
cv::mat binaryfiltered;
cv::boxfilter(image,filtered,cv_8u,cv::size(7,7));//這個盒子濾波相當於平均的效果
filtered = filtered + 4;
binaryfiltered = image >= filtered;
imshow("thresholdbox",binaryfiltered);
自適應閾值
自適應閾值函式 void vcadaptivethreshold cvarr src,cvarr dst,double max val,int adaptive method cv adaptive thresh mean c,int threshold type cv thresh binary,...
自適應閾值二值化
二值化原理 把乙個灰度影象二值化,其實就是找到乙個閾值,使這個較低中,灰度大於這個閾值的,設定成255,灰度小於這個閾值的,設定為0。閾值自適應二值化 非自適應的二值化呢,有乙個問題,就是乙個閾值往往只對應一類影象,如果影象的光照變暗了,那個單閾值情況的二值化效果會大大的折扣。自適應二值化其實就是一...
全域性固定閾值化和區域性自適應閾值化
在影象處理應用中二值化操作是乙個很常用的處理方式,較為常用的影象二值化方法有 1 全域性固定閾值 2 區域性自適應閾值 3 otsu等。全域性固定閾值化 對整幅影象都是用乙個統一的閾值來進行二值化 區域性自適應閾值化 根據畫素的鄰域塊的畫素值分布來確定該畫素位置上的二值化閾值。這樣做的好處在於每個畫...