均值滤波 附带简易code

1.概念介绍
 均值滤波是典型的 线性滤波算法,是指用当前像素点周围nxn个像素值的均值来代替当前像素值。使用该方法遍历处理图像内的每一个像素点,可完成整幅图像的均值滤波。

2.基本原理
 如图2-1,我们对第5行第5列的像素点进行均值滤波时,首先需要考虑需要对周围多少个像素点去取平均值。通常情况下,我们会以该当前像素为中心,对行数和列数相等的一块区域内的所有像素点的像素取平均值
 例如,我们可以以当前像素点的像素周围3x3区域内所有像素点的像素取平均值,也可以对周围5x5区域内所有像素点的像素值取平均值。

在这里插入图片描述

图2-1  一幅图像的像素值示例

 当前像素点的位置为第5行第5列时,我们对其周围5*5区域内的像素值取平均,计算方法如下:
像素点新值=
[(197+25+106+156+159)
(149+40+107+5+71)+
(163+198+226+223+156) +
(222+37+68+193+157)+
(42+72+250+41+75)]/25 = 126


计算得到新值以后,我们将新值作为当前像素点均值滤波后的像素值。我们针对图2-1的每一个像素点计算其周围5x5区域内的像素值均值,并将其作为当前像素点的新值,即可得到当前图像的均值滤波结果。


然而图像的边界并不存在5x5的领域区域。如图2-1的左上角第1行第1列上的像素点,其像素值为23。如果以其为中心点取周围5x5领域,则5x5领域的部分区域位于图像外部。但是图像外部是没有像素点和像素值的,显然是无法计算该点的领域均值的。


因此,针对边缘的像素点,可以只取图像内存在的周围领域点的像素值均值。如图2-2所示,计算左上角的均值滤波结果时,仅取图中灰色背景的33领域内的像素值的平均值。计算方法如下:
像素点新值=
[(23+158+140)+
(238+0+67)+
(199+197+25)]/9
=116

在这里插入图片描述

图2-2  边界点的处理

 除此之外,我们还可以扩展当前图像的周围像素点。例如,可以将当前97大小的图像扩展为13*11大小的图像,如图2-3所示。

在这里插入图片描述

图2-3  扩展边缘


 在完成图像边缘拓展后,我们可以在新增的行列内填充不同的像素值。在此基础上,再针对9x7的原始图像计算其5x5领域内像素点的像素值均值。OpenCV提供了多种边界处理方式,我们可以根据实际需要选用不同的边界处理模式。

 针对第5行第5列的像素点,其运算过程相当于一个额内部值是1/25的55矩阵进行相乘运算,从而得到均值滤波的结果为126。如图2-4所示。

在这里插入图片描述

图2-4  针对第 5 行第 5 列像素点均值滤波的运算示意图

根据上述运算,针对每一个像素点,都是与一个内部值均为1/25的55举证相乘,得到均值滤波的计算结果。示意图如图2-4所示

在这里插入图片描述

图1-4  针对每一个像素点均值滤波的运算示意图

将使用到的5x5矩阵一般化,可以得到如下图2-5的结果。

在这里插入图片描述

图2-5  将矩阵一般化

在Opencv中,将图1-5右侧的矩阵称为卷积核,其一般形式如下图2-6所示。其中M和N分别对应高度和宽度,一般情况下M和N的值是相等的,常用的3x3、5x5和7x7。如果M和N的值越大,参与运算的值就越大,参与运算的像素点的数量就越多,图像失真就越严重。

在这里插入图片描述

图2-6  卷积核

从使用不同大小的卷积核进行均值滤波处理图像可以发现:卷积核越大,图像的失真情况越明显。

卷积核越大,参与到均值运算中的像素就会越多,即当前计算的算的是更多点的像素值的平均值,去噪效果越好,当然花费的计算时间也会越长,同时让图像失真越严重。因此在实际处理中,要在失真和去噪效果之间取得平衡,选取合适大小的卷积核。
 

void MainWindow::on_averagefilter_clicked()
{
    cv::Mat FilterImg;
    QImage Qtemp1,Qtemp2;

    FilterImg = m_noiseimg.clone();

    for(int i = 1 ; i < m_noiseimg.rows - 1 ; i++)
        for(int j = 1 ; j < m_noiseimg.cols - 1 ; j++){
            for(int k = 0 ; k < 3 ; k++){
                FilterImg.at<cv::Vec3b>(i,j)[k] = cv::saturate_cast<uchar>((m_noiseimg.at<cv::Vec3b>(i - 1,j - 1)[k] + m_noiseimg.at<cv::Vec3b>(i - 1,j)[k] + m_noiseimg.at<cv::Vec3b>(i - 1,j + 1)[k]
                                                                        +m_noiseimg.at<cv::Vec3b>(i,j - 1)[k] + m_noiseimg.at<cv::Vec3b>(i,j)[k] + m_noiseimg.at<cv::Vec3b>(i,j + 1)[k]
                                                                        +m_noiseimg.at<cv::Vec3b>(i + 1,j - 1)[k] + m_noiseimg.at<cv::Vec3b>(i + 1,j)[k] + m_noiseimg.at<cv::Vec3b>(i + 1,j + 1)[k])/9);
            }
        }
    Qtemp2 = QImage((const unsigned char*)(FilterImg.data), FilterImg.cols, FilterImg.rows, FilterImg.step, QImage::Format_RGB888);
    ui->Label3->setPixmap(QPixmap::fromImage(Qtemp2));
    Qtemp2 = Qtemp2.scaled(250, 250, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    ui->Label3->setScaledContents(true);
    ui->Label3->resize(Qtemp2.size());
    ui->Label3->show();
}

猜你喜欢

转载自blog.csdn.net/cyy1104/article/details/130357891
今日推荐