1 #include2 #include 3 #include 4 #include 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 (0);14 for (int i = 0; i < 256; i++)15 {16 //累计背景值17 if (i < threshold)18 {19 BackgroundSum += pDataHist[i];20 }21 //累计目标值22 else23 {24 targetSum += pDataHist[i];25 }26 }27 cout << BackgroundSum << "\t" << 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 }
运行效果: