# 二维

### 二、熵（这里实在看不懂，请大神赐教）

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
//计算当前位置的能量熵
float caculateCurrentEntropy(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];
}
}
//输出
//cout << BackgroundSum << " " << targetSum << endl;
float BackgroundEntropy = 0, targetEntropy = 0;
for (int i = 0; i < 256; i++){
//计算背景熵
if (i < threshold){
if (pDataHist[i] == 0)
continue;
float ratiol = pDataHist[i] / BackgroundSum;
//计算当前背景熵
BackgroundEntropy += (-ratiol)*logf(ratiol);
}
else{//计算前景目标熵
if (pDataHist[i] == 0)
continue;
float ratio2 = pDataHist[i] / targetSum;
targetEntropy += (-ratio2)*logf(ratio2);
}
}
return (targetEntropy + BackgroundEntropy);
}
//寻找最大熵值并分割
Mat maxEntropySegMentation(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 = caculateCurrentEntropy(hist, i);
//取最大熵下的分割阈值
if (cur_entropy > maxentropy) {
maxentropy = cur_entropy;
max_index = i;
}
}
//二值化分割
threshold(inputImage, result, max_index, 255,
CV_THRESH_BINARY);
return result;
}
int main()
{
if (!srcImage.data){
cout << "failed to read" << endl;
system("pause");
return -1;
}
Mat srcGray;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);
//最大熵阈值分割
Mat result = maxEntropySegMentation(srcGray);
imshow("srcImage", srcImage);
imshow("result", result);
waitKey(0);
return 0;
}