【C++】如何利用直方图实现快速中值滤波

1、参考博客:https://www.cnblogs.com/riddick/p/7989871.html

2、但是博客代码的i和j的下标表示有些问题

3、修改code-1之后,可以成功运行的代码

  1 #include <opencv2opencv.hpp>
  2 #include <iostream>
  3 #include <string>
  4 
  5 using namespace cv;
  6 using namespace std;
  7 
  8 //计算亮度中值和灰度<=中值的像素点个数
  9 int calMediaValue(const int histogram[], int thresh)
 10 {
 11     int sum = 0;
 12     for (int i = 0; i < 256; ++i)
 13     {
 14         sum += histogram[i];
 15         if (sum >= thresh)
 16         {
 17             return i;
 18         }
 19     }
 20     return 255;
 21 }
 22 
 23 void fastMedianBlur(const Mat &srcImg, Mat &dstImg, int diameter)
 24 {
 25     int radius = (diameter - 1) / 2;
 26     int imgW = srcImg.cols;   // 1920    宽
 27     int imgH = srcImg.rows;   // 1200    高
 28     int channels = srcImg.channels();  // 1
 29     dstImg = Mat::zeros(imgH, imgW, CV_8UC1);
 30     int windowSize = diameter*diameter;  // 25
 31 
 32     //直方图
 33     int Hist[256] = { 0 };
 34     int histogramSize = 256;//灰度等级
 35     int thresholdValue = windowSize / 2 + 1;   // 13
 36 
 37     uchar *pSrcData = srcImg.data;
 38     uchar *pDstData = dstImg.data;
 39 
 40     int right = imgW - radius;   // 1918
 41     int bot = imgH - radius;     // 1198
 42     for (int j = radius; j < bot; j++)   //
 43     {
 44         
 45         for (int i = radius; i < right; i++)   //
 46         {
 47             //每一行第一个待滤波像素建立直方图
 48             if (i == radius)
 49             {
 50                 memset(Hist, 0, histogramSize*sizeof(int));
 51                 for (int y = j - radius; y <= min(j + radius, imgH); y++)
 52                 {
 53                     for (int x = i - radius; x <= min(i + radius,imgW); x++)
 54                     {
 55                         uchar value = pSrcData[y*imgW + x];
 56                         Hist[value]++;
 57                     }
 58                 }
 59             }
 60             else//更新直方图
 61             {
 62                 int left = i - radius - 1;
 63                 int right = i + radius;
 64                 for (int y = j - radius; y <= min(j + radius, imgH); y++)
 65                 {
 66                     //减去左边一列
 67                     int leftIdx = y*imgW + left;
 68                     uchar leftValue = pSrcData[leftIdx];
 69                     Hist[leftValue]--;
 70 
 71                     //加上右边一列
 72                     int rightIdx = y*imgW + right;
 73                     uchar rightValue = pSrcData[rightIdx];
 74                     Hist[rightValue]++;
 75                 }
 76             }
 77 
 78             //直方图求中值
 79             uchar filterValue = calMediaValue(Hist, thresholdValue);
 80             pDstData[j*imgW + i] = filterValue;
 81         }
 82     }
 83 
 84     //边界直接赋原始值,不做滤波处理
 85     pSrcData = srcImg.data;
 86     pDstData = dstImg.data;
 87     //上下边界
 88     for (int i = 0; i < imgW; i++)
 89     {
 90         for (int j = 0; j < radius; j++)
 91         {
 92             int idxTop = j*imgW + i;
 93             pDstData[idxTop] = pSrcData[idxTop];
 94             int idxBot = (imgH - j - 1)*imgW + i;
 95             pDstData[idxBot] = pSrcData[idxBot];
 96         }
 97     }
 98     //左右边界
 99     for (int j = radius; j < imgH - radius - 1; j++)
100     {
101         for (int i = 0; i < radius; i++)
102         {
103             int idxLeft = j*imgW + i;
104             pDstData[idxLeft] = pSrcData[idxLeft];
105             int idxRight = j*imgW + imgW - i - 1;
106             pDstData[idxRight] = pSrcData[idxRight];
107         }
108     }
109 }
110 
111 
112 int main()
113 {
114     string imgPath = "D:\Images\漂亮的图片\";
115     Mat srcImg = imread(imgPath + "2.jpg", 0);
116     Mat dstImg;
117 
118     double t0 = cv::getTickCount();
119     fastMedianBlur(srcImg, dstImg, 5);
120     double t1 = cv::getTickCount();
121 
122     cout << "time=" << (t1 - t0) / cv::getTickFrequency() << "  seconds" << endl;
123 
124     imwrite("srcImg.jpg", srcImg);
125     imwrite("myFilter.jpg", dstImg);
126 
127     return 0;
128 }

结果示例,中值滤波后的图片

原文地址:https://www.cnblogs.com/liulijin/p/9038230.html