1 #include <opencv2/imgproc/imgproc.hpp> 2 #include <opencv2/core/core.hpp> 3 #include <opencv2/highgui/highgui.hpp> 4 #include <iostream> 5 6 using namespace cv; 7 using namespace std; 8 9 //按给定的threshold,计算hist的背景熵和目标熵的总和 10 float caculateCurrentEntropy(Mat hist, int threshold) 11 { 12 float BackgroundSum = 0, targetSum = 0; 13 const float* pDataHist = (float*)hist.ptr<float>(0); 14 for (int i = 0; i < 256; i++) 15 { 16 //累计背景值 17 if (i < threshold) 18 { 19 BackgroundSum += pDataHist[i]; 20 } 21 //累计目标值 22 else 23 { 24 targetSum += pDataHist[i]; 25 } 26 } 27 cout << BackgroundSum << " " << targetSum << endl; 28 float BackgroundEntropy = 0, targetEntropy = 0; 29 for (int i = 0; i < 256; i++) 30 { 31 //计算背景熵 32 if (i < threshold) 33 { 34 if (pDataHist[i] == 0) 35 continue; 36 float ratio1 = pDataHist[i] / BackgroundSum; 37 //计算当前能量熵 38 BackgroundEntropy += -ratio1*logf(ratio1); 39 } 40 else //计算目标熵 41 { 42 if (pDataHist[i] == 0) 43 continue; 44 float ratio2 = pDataHist[i] / targetSum; 45 targetEntropy += -ratio2*logf(ratio2); 46 } 47 } 48 return (targetEntropy + BackgroundEntropy); 49 } 50 //寻找最大熵阈值并分割,根据该阈值进行二值化 51 Mat maxEntropySegMentation(Mat inputImage) 52 { 53 const int channels[1] = { 0 }; 54 const int histSize[1] = { 256 }; 55 float pranges[2] = { 0,256 }; 56 const float* ranges[1] = { pranges }; 57 MatND hist; 58 calcHist(&inputImage, 1, channels, Mat(), hist, 1, histSize, ranges); 59 float maxentropy = 0; 60 int max_index = 0; 61 Mat result; 62 for (int i = 0; i < 256; i++) 63 { 64 float cur_entropy = caculateCurrentEntropy(hist, i); 65 if (cur_entropy > maxentropy) 66 { 67 maxentropy = cur_entropy; 68 max_index = i; 69 } 70 } 71 threshold(inputImage, result, max_index, 255, CV_THRESH_BINARY); 72 return result; 73 } 74 int main() 75 { 76 Mat srcImage = imread("D:\hand.jpg"); 77 if (!srcImage.data) 78 return -1; 79 Mat grayImage; 80 cvtColor(srcImage, grayImage, CV_BGR2GRAY); 81 Mat result = maxEntropySegMentation(grayImage); 82 imshow("grayImage", grayImage); 83 imshow("result", result); 84 waitKey(0); 85 return 0; 86 }
运行效果: