图像处理——(源)最大熵阈值分割(Max_Entropy)函数编程实现
1 #include <iostream> 2 #include <opencv2/core.hpp> 3 #include <opencv2/highgui.hpp> 4 #include <opencv2/imgproc.hpp> 5 6 7 int Max_Entropy(cv::Mat& src, cv::Mat& dst, int thresh, int p){ 8 const int Grayscale = 256; 9 int Graynum[Grayscale] = { 0 }; 10 int r = src.rows; 11 int c = src.cols; 12 for (int i = 0; i < r; ++i){ 13 const uchar* ptr = src.ptr<uchar>(i); 14 for (int j = 0; j < c; ++j){ 15 if (ptr[j] == 0) //排除掉黑色的像素点 16 continue; 17 Graynum[ptr[j]]++; 18 } 19 } 20 21 float probability = 0.0; //概率 22 float max_Entropy = 0.0; //最大熵 23 int totalpix = r*c; 24 for (int i = 0; i < Grayscale; ++i){ 25 26 float HO = 0.0; //前景熵 27 float HB = 0.0; //背景熵 28 29 //计算前景像素数 30 int frontpix = 0; 31 for (int j = 0; j < i; ++j){ 32 frontpix += Graynum[j]; 33 } 34 //计算前景熵 35 for (int j = 0; j < i; ++j){ 36 if (Graynum[j] != 0){ 37 probability = (float)Graynum[j] / frontpix; 38 HO = HO + probability*log(1/probability); 39 } 40 } 41 42 //计算背景熵 43 for (int k = i; k < Grayscale; ++k){ 44 if (Graynum[k] != 0){ 45 probability = (float)Graynum[k] / (totalpix - frontpix); 46 HB = HB + probability*log(1/probability); 47 } 48 } 49 50 //计算最大熵 51 if(HO + HB > max_Entropy){ 52 max_Entropy = HO + HB; 53 thresh = i + p; 54 } 55 } 56 57 //阈值处理 58 src.copyTo(dst); 59 for (int i = 0; i < r; ++i){ 60 uchar* ptr = dst.ptr<uchar>(i); 61 for (int j = 0; j < c; ++j){ 62 if (ptr[j]> thresh) 63 ptr[j] = 255; 64 else 65 ptr[j] = 0; 66 } 67 } 68 return thresh; 69 } 70 71 72 int main(){ 73 cv::Mat src = cv::imread("E://lena.jpg"); 74 if (src.empty()){ 75 return -1; 76 } 77 if (src.channels() > 1) 78 cv::cvtColor(src, src, CV_RGB2GRAY); 79 80 cv::Mat dst, dst2; 81 int thresh = 0; 82 double t2 = (double)cv::getTickCount(); 83 thresh = Max_Entropy(src, dst, thresh,10); //Max_Entropy 84 std::cout << "Mythresh=" << thresh << std::endl; 85 t2 = (double)cv::getTickCount() - t2; 86 double time2 = (t2 *1000.) / ((double)cv::getTickFrequency()); 87 std::cout << "my_process=" << time2 << " ms. " << std::endl << std::endl; 88 89 double Otsu = 0; 90 Otsu = cv::threshold(src, dst2, Otsu, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); 91 std::cout << "Otsuthresh=" << Otsu << std::endl; 92 93 94 cv::namedWindow("src", CV_WINDOW_NORMAL); 95 cv::imshow("src", src); 96 cv::namedWindow("dst", CV_WINDOW_NORMAL); 97 cv::imshow("dst", dst); 98 cv::namedWindow("dst2", CV_WINDOW_NORMAL); 99 cv::imshow("dst2", dst2); 100 101 cv::waitKey(0); 102 }
萍水相逢逢萍水,浮萍之水水浮萍!