中值滤波

中值滤波

一、原理

(1)目的:去除图像上的尖锐噪声,平滑图像。

(2)原理:中值滤波属于非线性滤波,是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。其中,图1中mid表示矩阵中的中值,median表示获取中值的函数名,中括号的内容是待选取中值的参数。

 

                                                         

图1 核心步骤,求中值

 

 

 

二、步骤

(1)判断卷积核大小是否为奇数

(2)边界复制填充

(3)跳过边界,对中间区域滤波

(4)通过排序获得中值

(5)将中值写入目标图像

(6)显示图像

 

三、伪代码

输入:原图src,卷积核大小n(取中值的范围)

输出:结果图dst

Void MedianFilter(Mat src,Mat& dst, int n)

{

         If(卷积核n为偶数)

                   报异常,退出

 

         边缘处理

 

         for(循环处理像素点){

         if(判断图像通道数){

                   根据通道数,以n个像素为单位存入一个大小为n的数组

                   求数组的中值

                   将中值赋值到输出图片中    

    }

  }

}

 

 

三、特点

优点:中值滤波法对消除椒盐噪声非常有效;

缺点:条纹中心分析方法中作用不大,效率不如均值滤波;

 

 

四、源码

// 中值滤波

void MedianFilter(cv::Mat &srcImg, cv::Mat& dstImg, int n)

{

    // 判断原图像是否为空

    if (srcImg.empty()) {

        return;

    }

    // 判断核的大小是否为奇数

    CV_Assert(n % 2 == 1);

 

    // 清空目标图像,对原图像进行边界填充

    Mat tmp;

    dstImg = dstImg.zeros(srcImg.size(), srcImg.type());

    int *kernel = new int[n*n];

    copyMakeBorder(srcImg, tmp, n / 2, n / 2, n / 2, n / 2, BORDER_REPLICATE);

    for (int i = n / 2; i < srcImg.rows + n / 2; i++)       //对填充后的图像从有图像区域开始滤波

    {

        for (int j = n / 2; j < srcImg.cols + n / 2; j++)

        {

            for (int c = 0; c < 3; c++)      

            {

                // 将核大小的图像填入数组

                for (int m = 0; m < n*n; m++) {

                    if (tmp.channels() == 1) {

                        kernel[m] = tmp.ptr<uchar>(i - n / 2 + m / n, j - n / 2 + m % n)[c];

                    }

                    else if (tmp.channels() == 3) {

                        kernel[m] = tmp.ptr<Vec3b>(i - n / 2 + m / n, j - n / 2 + m % n)->val[c];

                    }

                    else

                    {

                        delete[]kernel;

                        return;

                    }

                }

                // 排序

                Sort(kernel, n*n);

                // 将中值写入目标图像

                if (tmp.channels() == 1) {

                    dstImg.ptr<uchar>(i - n / 2, j - n / 2)[c] = kernel[(n*n) / 2];

                }

                else if (tmp.channels() == 3) {

                    dstImg.ptr<Vec3b>(i - n / 2, j - n / 2)->val[c] = kernel[(n*n) / 2];

                }

 

            }

        }

    }

    delete[]kernel;

 

}

 

五、结果图

卷积核为3*3

 

 

 

 

卷积核为5*5 

 

 

posted @ 2021-04-28 10:36  will-z  阅读(8090)  评论(0编辑  收藏  举报