zoukankan      html  css  js  c++  java
  • 【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 }

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

  • 相关阅读:
    rocketmq 命令示例
    原 荐 使用Spring Boot Actuator、Jolokia和Grafana实现准实时监控
    业务系统中最核心的状态设计,异常 case. (系统设计)
    大数据架构分析
    开源 java 电商系统
    数据一致性对账平台架构
    管理中遇到的问题--人,组织上的问题
    腾讯后台开发面试题
    理解inode
    TCP序列号和确认号
  • 原文地址:https://www.cnblogs.com/liulijin/p/9038230.html
Copyright © 2011-2022 走看看