千家信息网

C++如何实现中值滤波

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,这篇文章主要介绍了C++如何实现中值滤波的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++如何实现中值滤波文章都会有所收获,下面我们一起来看看吧。中值滤波器是一种非线性
千家信息网最后更新 2025年01月16日C++如何实现中值滤波

这篇文章主要介绍了C++如何实现中值滤波的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++如何实现中值滤波文章都会有所收获,下面我们一起来看看吧。

中值滤波器是一种非线性滤波器,或者叫统计排序滤波器。

适用对象:带椒盐噪声的图像

由于椒盐噪声像素值与原图像素值没有关联,随机性较大,因此使用中值滤波可有效滤掉噪声。

中值滤波需要对像素值进行排序,因此首先写一个冒泡排序算法。

冒泡排序实现:

为提高效率加入标志位flag,当第i次寻找最大值时,如果相邻两个数均未发生互换,此时flag位为false,即说明此时数组已经按照递增排列,可提前终止。此处应该注意flag=false所在位置,因为需要保证第i次寻找最大值过程中,遍历到所有未参与排列的数据,所以flag=false应该放在循环条件for(int j=0; j

void bubble(std::vector &arr, int len){    bool flag = true;    for (int i = 0; i < len-1; i++)    {        while (flag)        {            flag = false;            for (int j = 0; j < len - i - 1; j++)            {                                if (arr[j + 1] < arr[j])                {                    flag = true;  //只要发生一次交换就继续判断                    int temp = arr[j + 1];                    arr[j + 1] = arr[j];                    arr[j] = temp;                }            }        }    }    }

中值滤波的实现:

需要注意的主要问题:

为了能够遍历到原图的边界,需要对原图进行边界扩充,扩充长度为(窗口的长度-1)/ 2。
注意利用窗口对扩充后的图像遍历时,起始的位置不是0,而是扩充的长度,因为这时对应的才是原图的第一个像素点,同理结束的位置也是原图的最后一个像素点。
另外为了方便将窗口内对应的像素存到容器中,可以写两个循环,循环长度为窗口的长度与宽度,依次将像素值存入容器中。
最后对容器内的像素按照递增排列后,取中值赋给目标矩阵相应的位置,而此时的位置也应该用i-h,对应扩充前的位置。
经实践证明我写的这两个算法可有效使用。

void medianFilter(cv::Mat& src, cv::Mat& dst, cv::Size width){    //判断窗口是否为奇数    if (width.width % 2 == 0 || width.height % 2 == 0)    {        std::cout << "输入窗口大小应该为奇数,请重新输入" << endl;        exit(-1);    }    else    {        //计算边界扩充长度        int h = (width.height - 1) / 2;        int w = (width.width - 1) / 2;         //对原图边界扩充        cv::Mat src_border;        cv::copyMakeBorder(src, src_border, h, h, w, w, cv::BORDER_REFLECT_101);        for (int i = h; i < src.rows + h; i++)        {             for (int j = w; j < src.cols + w; j++)            {                //定义容器存放窗口对应的像素                std::vector  v;                for (int ii = i - h; ii <= i + h; ii++)                {                    for (int jj = j - w; jj <= j + w; jj++)                    {                         v.push_back(src_border.at(ii, jj));                    }                }                //对容器内存放的像素排序                int len = width.area();                bubble(v, len);                //将中值赋给目标图像对应位置                dst.at(i-h, j-w) = v[(len - 1) / 2];                            }        }            } }

关于"C++如何实现中值滤波"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"C++如何实现中值滤波"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

0