OpenCV4Android开发实录(4):图像去噪与线性滤波(均值、方框、高斯)

本文详细介绍了OpenCV4Android中图像线性滤波的实现,包括点算子、邻域算子和线性滤波的原理,如方框滤波、均值滤波和高斯滤波。通过实例代码展示了如何使用OpenCV进行图像处理,包括C++和Android Studio的实现,帮助理解滤波在图像去噪和平滑中的应用。
摘要由CSDN通过智能技术生成

转载请声明出处:https://blog.csdn.net/AndrExpert/article/details/80183965

图像滤波(filtering),又称图像去噪或模糊(blur)或平滑(smooth),从某些程度上来说它们属于一个概念,其目的是在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,图像滤波处理效果的好坏直接影响到后续图像处理和分析的有效性和可靠性。常见的图像滤波有线性滤波、非线性滤波、形态学滤波等,本节将重点阐述线性滤波相关算法的核心原理以及OpenCV中API的使用。

1. 点算子与邻域算子

 在讲解点算子和邻域算子之前,我们先来了解下图像处理算子的概念,在上一篇博文中谈到,一副数字图像在计算机中实质就是一个数值矩阵,矩阵中的每个元素就是图像中的像素,所谓对图像的处理其实就是对图像中像素的处理,而处理的方法或称算法即为算子。一般的图像处理算子都是一个函数,它接受一个或多个输入图像,并产生输出图像,它的一般形式为:

 g(x) = h(f(x)) 或者 g(x) = h(f0(x)…fn(x))

1.1 点算子

 点算子,也称点操作,是图像处理变换中最为简单的一种,它的特点是输出的像素值只与输入的像素值有关,无输入像素相邻的像素无关。常见的点算子有图像的亮度调整、对比度调整、变换以及颜色校正等,这里以图像的亮度和对比度处理算子为例,函数表达式为:

 g(i,j) = a*f(i,j) + b;

 其中,i,j表示像素位于矩阵的第i行、第j列;f(i,j)表示源图像(i,j)位置像素;g(i,j)表示输出图像像素;参数a(a>0)称为增益,用于控制图像的对比度;参数b称为偏置,用于控制图像亮度。示例代码:

/**
* created by jiangdongguo on 20180503
* 调整图像亮度和对比度
*/
void resizeBrightnessAndContrast(int a,int b) {
    Mat src, dst;
    src = imread("yuwenwen.jpg");
    if (!src.data) {
        printf("加载源图像失败");
    }
    namedWindow("源图像");
    imshow("源图像", src);
    // dst矩阵尺寸、像素类型与源图像一致,并初始化置零
    dst = Mat::zeros(src.size(), src.type());
    // 遍历所有像素,使用点算子处理
    // g(i,j) = a*f(i,j) + b;
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            if (src.channels() == 1) {
                // 灰度图像
                dst.at<uchar>(i, j) = saturate_cast<uchar>(a*src.at<uchar>(i,j) + b);
            } else {
                // 彩色图像
                for (int channel = 0; channel < src.channels(); channel++) {
                    dst.at<Vec3b>(i, j)[channel] = saturate_cast<uchar>(a*src.at<Vec3b>(i,j)[channel]+b);
                }
            }
        }
    }
    imshow("a=2,b=2效果图", dst);
}

 说明:OpenCV中使用Mat::at<像素类型>(i,j)方法返回矩阵中(i,j)位置元素的引用,即访问图像矩阵中(i,j)位置像素,其中<..>尖括号提供的是一种模板方法,用于指定访问像素的类型。比如矩阵的类型为CV_8U,对应为Mat::at<uchar>(i,j); 矩阵类型为CV_32F对应为Mat::at<float>(i,j),当然,对于多通道而言,我们还可以使用Vec3b、Vec4b等向量类型,如CV_8UC3,对应为Mat::at<Vec3b>(i,j)。另外,在处理像素值时,需要注意计算后的像素值超过类型范围情况,比如对于灰度图像像素值或BRG/RGB彩色图像单通道分量取值范围为0-255之间,我们使用saturate_cast<uchar>函数来处理,其中尖括号指定数据类型,或称取值范围。

效果演示:
这里写图片描述

1.2 邻域算子

 邻域算子是图像处理中非常重要的一种算子,常用于图像滤波(平滑、锐化)、图像边缘增强以及局部色调调整等方面,它的特点是给定像素的最终输出值,不仅与自身有关,还与该像素周围像素的值有关。本文将要介绍的线性邻域滤波就是一种常用的领域算子,像素的输出值取决于输入像素的加权和。具体过程如下图所示:
这里写图片描述
 上图演示了从原图像中取一个3x3的矩阵,使之与另一个3x3矩阵相乘,然后得到一个新的3x3的矩阵,再将新的3x3的矩阵的所有元素进行累加,最终得到235,即为原图像第(2,2)个像素的经过处理的值,而这一过程又称为邻域卷积

1.3 图像归一化

图像归一化是指对图像进行了一系列标准的处理变换,使之变换为一固定标准形式的过程,该标准图像称作归一化图像。它的基本原理:首先,利用图像中对仿射变换具有不变性的矩确定变换函数的参数,然后,利用此参数确定的变换函数把原始图像变换为一个标准形式的图像,且该标准形式图像对平移、旋转、缩放等仿射变换具有不变性。
 举个例子:在制作表情图像时,一般表情图像经过特征块切割后,切割生成的特征块大小不一,这就需要采取归一化操作来统一特征块图像的尺寸。OpenCV中实现图像归一化操作的函数为normalize,其函数原型为:

/** 归一化数组元素在一定的范围内
 *  src:输入数组
 *  dst:输出数组
 *  alpha: range normalization模式的最小值
 *  beta:range normalization模式的最大值,不用于norm normalization(范数归一化)模式。
 *  norm_type:归一化的类型,可以有以下的取值:
    - NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。
    - NORM_INF:此类型的定义没有查到,根据OpenCV 1的对应项,可能是归一化数组的C-范数(绝对值的最大值)
    - NORM_L1:归一化数组的L1-范数(绝对值的和)
    - NORM_L2:归一化数组的(欧几里德)L2-范数
 *  dtype:dtype为负数时,输出数组的type与输入数组的type相同;否则
        输出数组与输入数组只是通道数相同,而tpye=CV_MAT_DEPTH(dtype).
 *  mask:操作掩膜,用于指示函数是否仅仅对指定的元素进行操作。
 *
 */
void normalize(InputArray src,OutputArray dst, double alpha=1, 
        double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
2. 线性滤波

 滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施,以便将原始信号的有用信息通过各种组合来凸显出来。在图像处理中,对邻域中的像素的计算为线性运算时,如利用窗口函数进行平滑加权求和的运算,或者某种卷积运算,都可以称为线性滤波。常见的线性滤波有:均值滤波、高斯滤波、方框滤波、拉普拉斯滤波等,通常线性滤波器之间只是模版系数或称滤波器加权系数不同。
这里写图片描述
 上图是一个典型的图像线性滤波操作过程,它描述的是左边图像与中间图像的卷积产生右边图像,即中间的图像通过扫描方式不断地在输入图像上找到相同大小的矩阵进行加权后操作,直到计算出所有可计算的像素,最终得到卷积处理后的输出图像。如果用数学方式来表述,可为:
这里写图片描述这里写图片描述
 即线性滤波处理的输出像素值g(i,j) 是输入像素值f(i+k,j+I)h(k,I)的加权和;或称输出像素值g是输入像素值f与h的卷积。其中,h(k,I)被称为”核”或窗口函数,是滤波器的加权系数,是一个kxI大小的矩阵,它还有一个锚点的概念,锚点的作用就是基于“核”指定要处理的目标像素,这个接下来会讲到。

2.1 方框滤波

1. 基本理论
 方框滤波是最简单的线性滤波,每个输出像素都是其内核邻域像素的平均值(它们都贡献了相同的权重),它所用的核h(k,l)为:
这里写图片描述
其中,这里写图片描述,当normalize=true时,使用归一化把要处理的量都缩放到一个范围内,比如(0,1),以便统一处理和直观量化,此时方框滤波就变成了均值滤波;当normalize=false时,方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法(dense optical flow algorithms)中用到的图像倒数的协方差矩阵(covariance matrices of image derivatives)。
2. boxFilter函数源码解析
 (1) boxFilter函数原型

/**boxFilter函数 
    src:输入图像,即源图像,填Mat类对象;
    dst:输出图像,需要和源图像有一样的尺寸和深度;
    ddepth:输出图像的颜色深度,ddepth=-1表示使用输入图像的深度
    ksize:平滑处理内核的大小,通常为正奇数1、3、5...;
    anchor&#
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值