1、参考博客:https://www.cnblogs.com/riddick/p/7989871.html
2、但是博客代码的i和j的下标表示有些问题
3、修改code-1之后,可以成功运行的代码
1 #include <opencv2\opencv.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 }
结果示例,中值滤波后的图片