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