集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1200|回复: 0

中值滤波&均值滤波

[复制链接]
fpga_feixiang 发表于 2019-10-25 14:12:44 | 显示全部楼层 |阅读模式
一.均值滤波

          图片中一个方块区域(一般为3*3)内,中心点的像素为全部点像素值的平均值。均值滤波就是对于整张图片进行以上操作。

我们可以看下图的矩阵进行理解

                                                                     

                        

缺陷:均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声

实现代码:

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include<ctime>
using namespace cv;
using namespace std;

//均值滤波
void AverFiltering(const Mat &src,Mat &dst) {
        if (!src.data) return;
        //at访问像素点
        for (int i = 1; i<src.rows; ++i)
                for (int j = 1; j < src.cols; ++j) {
                        if ((i - 1 >= 0) && (j - 1) >= 0 && (i + 1)<src.rows && (j + 1)<src.cols) {//边缘不进行处理
                                dst.at<Vec3b>(i, j)[0] = (src.at<Vec3b>(i, j)[0] + src.at<Vec3b>(i - 1, j - 1)[0] + src.at<Vec3b>(i - 1, j)[0] + src.at<Vec3b>(i, j - 1)[0] +
                                        src.at<Vec3b>(i - 1, j + 1)[0] + src.at<Vec3b>(i + 1, j - 1)[0] + src.at<Vec3b>(i + 1, j + 1)[0] + src.at<Vec3b>(i, j + 1)[0] +
                                        src.at<Vec3b>(i + 1, j)[0]) / 9;
                                dst.at<Vec3b>(i, j)[1] = (src.at<Vec3b>(i, j)[1] + src.at<Vec3b>(i - 1, j - 1)[1] + src.at<Vec3b>(i - 1, j)[1] + src.at<Vec3b>(i, j - 1)[1] +
                                        src.at<Vec3b>(i - 1, j + 1)[1] + src.at<Vec3b>(i + 1, j - 1)[1] + src.at<Vec3b>(i + 1, j + 1)[1] + src.at<Vec3b>(i, j + 1)[1] +
                                        src.at<Vec3b>(i + 1, j)[1]) / 9;
                                dst.at<Vec3b>(i, j)[2] = (src.at<Vec3b>(i, j)[2] + src.at<Vec3b>(i - 1, j - 1)[2] + src.at<Vec3b>(i - 1, j)[2] + src.at<Vec3b>(i, j - 1)[2] +
                                        src.at<Vec3b>(i - 1, j + 1)[2] + src.at<Vec3b>(i + 1, j - 1)[2] + src.at<Vec3b>(i + 1, j + 1)[2] + src.at<Vec3b>(i, j + 1)[2] +
                                        src.at<Vec3b>(i + 1, j)[2]) / 9;
                        }
                        else {//边缘赋值
                                dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
                                dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
                                dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
                        }
                }
}
//图像椒盐化
void salt(Mat &image, int num) {
        if (!image.data) return;//防止传入空图
        int i, j;
        srand(time(NULL));
        for (int x = 0; x < num; ++x) {
                i = rand() % image.rows;
                j = rand() % image.cols;
                image.at<Vec3b>(i, j)[0] = 255;
                image.at<Vec3b>(i, j)[1] = 255;
                image.at<Vec3b>(i, j)[2] = 255;
        }
}
void main() {
        Mat image = imread("路飞.jpg");

        Mat Salt_Image;
        image.copyTo(Salt_Image);
        salt(Salt_Image, 3000);

        Mat image1(image.size(), image.type());
        Mat image2;
        AverFiltering(Salt_Image, image1);
        blur(Salt_Image, image2, Size(3, 3));//openCV库自带的均值滤波函数
        imshow("原图", image);
        imshow("自定义均值滤波", image1);
        imshow("openCV自带的均值滤波", image2);
        waitKey();
}

效果图:





可以看到图片变模糊而且噪声并没有很有效的去除,该算法只是模糊化了图片而已。

二.中值滤波

       首先,我们复习中值。在一连串数字{1,4,6,8,9}中,数字6就是这串数字的中值。由此我们可以应用到图像处理中。依然我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。



                                    

代码:

//求九个数的中值
uchar Median(uchar n1, uchar n2, uchar n3, uchar n4, uchar n5,
        uchar n6, uchar n7, uchar n8, uchar n9) {
        uchar arr[9];
        arr[0] = n1;
        arr[1] = n2;
        arr[2] = n3;
        arr[3] = n4;
        arr[4] = n5;
        arr[5] = n6;
        arr[6] = n7;
        arr[7] = n8;
        arr[8] = n9;
        for (int gap = 9 / 2; gap > 0; gap /= 2)//希尔排序
                for (int i = gap; i < 9; ++i)
                        for (int j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap)
                                swap(arr[j], arr[j + gap]);
        return arr[4];//返回中值
}

//图像椒盐化
void salt(Mat &image, int num) {
        if (!image.data) return;//防止传入空图
        int i, j;
        srand(time(NULL));
        for (int x = 0; x < num; ++x) {
                i = rand() % image.rows;
                j = rand() % image.cols;
                image.at<Vec3b>(i, j)[0] = 255;
                image.at<Vec3b>(i, j)[1] = 255;
                image.at<Vec3b>(i, j)[2] = 255;
        }
}

//中值滤波函数
void MedianFlitering(const Mat &src, Mat &dst) {
        if (!src.data)return;
        Mat _dst(src.size(), src.type());
        for(int i=0;i<src.rows;++i)
                for (int j=0; j < src.cols; ++j) {
                        if ((i - 1) > 0 && (i + 1) < src.rows && (j - 1) > 0 && (j + 1) < src.cols) {
                                _dst.at<Vec3b>(i, j)[0] = Median(src.at<Vec3b>(i, j)[0], src.at<Vec3b>(i + 1, j + 1)[0],
                                        src.at<Vec3b>(i + 1, j)[0], src.at<Vec3b>(i, j + 1)[0], src.at<Vec3b>(i + 1, j - 1)[0],
                                        src.at<Vec3b>(i - 1, j + 1)[0], src.at<Vec3b>(i - 1, j)[0], src.at<Vec3b>(i, j - 1)[0],
                                        src.at<Vec3b>(i - 1, j - 1)[0]);
                                _dst.at<Vec3b>(i, j)[1] = Median(src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i + 1, j + 1)[1],
                                        src.at<Vec3b>(i + 1, j)[1], src.at<Vec3b>(i, j + 1)[1], src.at<Vec3b>(i + 1, j - 1)[1],
                                        src.at<Vec3b>(i - 1, j + 1)[1], src.at<Vec3b>(i - 1, j)[1], src.at<Vec3b>(i, j - 1)[1],
                                        src.at<Vec3b>(i - 1, j - 1)[1]);
                                _dst.at<Vec3b>(i, j)[2] = Median(src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i + 1, j + 1)[2],
                                        src.at<Vec3b>(i + 1, j)[2], src.at<Vec3b>(i, j + 1)[2], src.at<Vec3b>(i + 1, j - 1)[2],
                                        src.at<Vec3b>(i - 1, j + 1)[2], src.at<Vec3b>(i - 1, j)[2], src.at<Vec3b>(i, j - 1)[2],
                                        src.at<Vec3b>(i - 1, j - 1)[2]);
                        }
                        else
                                _dst.at<Vec3b>(i, j) = src.at<Vec3b>(i, j);
                }
        _dst.copyTo(dst);//拷贝
}


void main() {
        Mat image = imread("路飞.jpg");

        Mat Salt_Image;
        image.copyTo(Salt_Image);
        salt(Salt_Image, 3000);

        Mat image3, image4;
        MedianFlitering(Salt_Image, image3);
        medianBlur(Salt_Image, image4, 3);
        imshow("自定义中值滤波处理后", image3);
        imshow("openCV自带的中值滤波", image4);
        waitKey();
}


效果图:



可以看到,椒盐噪声很好的被平滑了,而且也没均值那样模糊化太过于严重。
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-4-30 12:38 , Processed in 0.054782 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表