1. 程式人生 > >Opencv Canny邊緣提取,閾值自適應基於一維熵最大值

Opencv Canny邊緣提取,閾值自適應基於一維熵最大值

Canny 邊緣提取的最大最小值設定很麻煩,合理的高低閾值選擇是一個很重要的問題,一般做法對不同影象採取相同的預設值,但會導致對某一類影象的處理效果好,對另一些影象處理效果不好。

一維最大熵的程式碼來自連線11,感謝博主的分享。 幫助理解下面是一維最大熵公式: 在這裡插入圖片描述 公式來自連線22,我一開始用的是連線2的程式碼但不知道為什麼得到的最大熵值為0。

int main()
{
	Mat src = imread("photo.bmp");
	int MaxThreshold;
	MaxThreshold = MaxEntropy(src);
	Canny(src , src , MaxThreshold /
3, MaxThreshold); imshow("canny自適應閾值", src ); printf("max:%d\n", MaxThreshold); } //計算當前熵 float CalEntropy(Mat hist, int threshold) { float BackgroundSum = 0, targetSum = 0; const float* pDataHist = (float*)hist.ptr<float>(0); for (int i = 0; i < 256; i++) { //累計背景值 if (i < threshold)
{ BackgroundSum += pDataHist[i]; } //累計目標值 else { targetSum += pDataHist[i]; } } float BackgroundEntropy = 0, targetEntropy = 0; for (int i = 0; i < 256; i++) { //計算背景熵 if (i < threshold) { if (pDataHist[i] == 0) continue; float ratio1 = pDataHist[i] / BackgroundSum;
//p[i] //計算當前能量熵 BackgroundEntropy += -ratio1 * logf(ratio1); } else //計算目標熵 { if (pDataHist[i] == 0) continue; float ratio2 = pDataHist[i] / targetSum; targetEntropy += -ratio2 * logf(ratio2); } } return (targetEntropy + BackgroundEntropy); } //尋找最大熵閾值並分割 int MaxEntropy(Mat inputImage) { const int channels[1] = { 0 }; const int histSize[1] = { 256 }; float pranges[2] = { 0,256 }; const float* ranges[1] = { pranges }; MatND hist; calcHist(&inputImage, 1, channels, Mat(), hist, 1, histSize, ranges); float maxentropy = 0; int max_index = 0; Mat result; for (int i = 0; i < 256; i++) { float cur_entropy = CalEntropy(hist, i); if (cur_entropy > maxentropy) { maxentropy = cur_entropy; max_index = i; } } return max_index; }