赞
踩
滤波是信号和图像处理中的一种基本操作,目的是选择性提取图像中某些方面的内容,例如,滤波可以去除图像中的噪声,提取有用的视觉特征,对图像进行重采样等。下面介绍几个有关滤波的重要概念:
一幅图像是由不同灰度级别(或者彩色)组成的图案,有些地方的图案灰度级变化很大(比如在大量细小的物体场景中),有些地方的灰度级强度几乎不变(比如大海、蓝天、草地等),因此产生了一种描述图像特性的方式,即观察上述变化的频率。这种特征称为频域 (frequency domain);而通过观察灰度分布来描述图像特征,称为空域(spatial domain)。
频域分析把图像分解成从低频到高频的频率成分,图像强度值变化慢的区域只包含低频率,强度值变化快的区域产生高频率。因为图像是二维的,因此频率分为两种,垂直频率(垂直方向的变化)和水平频率(水平方向的变化)。
低通滤波器的作用是消除图像中的高频部分,使图像变得更加平滑。
把图像中每个像素的值替换成它周围像素的平均值,从而使图像更加平滑。opencv中对应的均值滤波函数是:
- void blur( InputArray src, //输入的图像
- OutputArray dst, //输出的图像
- Size ksize, //滤波核的大小
- Point anchor=Point(-1,-1), //锚点,即被平滑的那个点,默认值是Point(-1,-1)
- int borderType=BORDER_DEFAULT );//图像外部像素的某种边界模式,默认值是BORDER_DEFAULT
对实验图像分别选择两种滤波核对比效果,一种是Size(5*5),一种是Size(10*10),下面是代码和结果图。
- cv::blur(image, result_55, cv::Size(5, 5));//滤波器尺寸5*5
- cv::blur(image, result_1010, cv::Size(10, 10));//滤波器尺寸10*10
原图
滤波核分别是5*5和10*10的结果,可以看出滤波核越大越模糊,体会到了近视的痛苦>_<
相关原理:
滤波核实际上是一个矩阵,矩阵中的值是权值,5*5,10*10就是对应的矩阵大小。对于一个3*3的均值滤波器,他对应的滤波核可能长这样:
以上面的滤波核为例,当这个滤波器移动到图像的每个像素上时,会将其邻域内的每个像素乘以1,然后累加再取平均(除以9),最后用这个平均值替换原像素的值。
当需要让邻域内较近的像素具有更高的重要度时,采用计算加权平均值,即距离较近的像素比较远的像素有更大的权重,依据高斯函数来制定加权策略。opencv中对应的高斯滤波函数是:
- void GaussianBlur( InputArray src, //输入图像
- OutputArray dst, //输出图像
- Size ksize, //滤波器尺寸
- double sigmaX, //控制高斯曲线形状的参数
- double sigmaY = 0, //x轴上的分量sigmaX,y轴上的分量sigmaY
- int borderType = BORDER_DEFAULT );
对小狗图像做高斯滤波
- cv::Mat image = cv::imread("puppy.bmp");
- cv::imshow("puppy", image);
- cv::GaussianBlur(image, result, cv::Size(5, 5), 1.5);
- cv::imshow("Gaussian filtered ", result);
相关原理:
对于高斯滤波器,像素对应的权重与它到中心像素之间的距离成正比。一维高斯公式为:
其中,A是归一化系数,为了确保高斯曲线下方的面积为1,符号sigma的值决定了高斯曲线的宽度,这个值越大,高斯曲线越扁平。下面是当sigma=0.5和sigma=1.5时的高斯曲线图:
高斯函数是一个对称钟形曲线,离中心点越远的像素权重越低,这使得像素之间的过渡更平滑,当曲线愈扁平时(接近均值滤波器),远处的像素会使得当前的平均值发生突变,从频率上看,均值滤波器没有消除全部高频的成分。
因为高斯滤波器是一种可分离滤波器,所以要在图像上应用二维高斯滤波器时,只需先在横向线条上应用一维高斯滤波器(过滤水平方向的频率),然后在纵向线条上应用另一个一维高斯滤波器(过滤垂直方向的频率)。
注意一点,在openCV中使用cv::GaussianBlur()函数对图像做高斯滤波的时候,除了提供前两个输入和输出图像,还要提供滤波器尺寸(第三个参数必须是奇数)和的值(第四个参数)。或者只提供的值,由openCV决定滤波器尺寸(输入滤波器尺寸的值为0),或者只输入滤波器尺寸,openCV决定自己判断合适的值。
- cv::GaussianBlur(image, result, cv::Size(9, 9), 1.5); //第三个参数应为奇数
- cv::GaussianBlur(image, result, cv::Size(10, 10), 1.5);//会报错
降低图像精度的过程称为缩减像素采样。当缩小一幅图像时,简单的删除图像中的一部分行和列会导致图像呈现更多锯齿状,视觉效果不佳,因此在删除部分行和列之前先对原始图像做低通滤波处理,这样得到的图像不会存在伪影。
直接去除一部分行和列
- cv::Mat image = cv::imread("boldt.jpg",0); //读取照片
- cv::Mat reduced(image.rows / 4, image.cols / 4, CV_8U);
- for (int i = 0; i < reduced.rows; i++)
- {
- for (int j = 0; j < reduced.cols; j++)
- {
- reduced.at<uchar>(i, j) = image.at<uchar>(i * 4, j * 4);
- }
- }
- cv::resize(reduced, reduced, cv::Size(), 4, 4, cv::INTER_NEAREST);//把每个像素按原大小的四倍显示
- cv::imshow("Reduced ", reduced);
直接去除一部分行和列结果
经过低通滤波后再缩减像素
- cv::GaussianBlur(image, image, cv::Size(11, 11), 1.75); //第三个参数应为奇数
- cv::Mat reduced2(image.rows / 4, image.cols / 4, CV_8U);//每四个像素保留一个
- for (int i = 0; i < reduced2.rows; i++)
- {
- for (int j = 0; j < reduced2.cols; j++)
- {
- reduced2.at<uchar>(i, j) = image.at<uchar>(i * 4, j * 4);
- }
- }
- cv::Mat newimage;
- cv::resize(reduced2, newimage, cv::Size(), 4, 4, cv::INTER_NEAREST);//把每个像素按原大小的四倍显示
- cv::imshow("Reduced2 ", newimage);
可以看出做高斯滤波后再缩减像素的视觉效果比直接删除像素的效果好得多。
按比例缩放后的图像必须进行像素的插值,常见的图像插值方法有:最邻近插值法,双线性内插法,双三次插值法。
最邻近插值法
把待生成图像的像素网格放在图像上方,每个新像素被赋予原图像中最邻近像素的值。例如要把上面的图像放大四倍。
cv::resize(reduced, newImage, cv::Size(), 3, 3, cv::INTER_NEAREST);
双线性内插法
先在新增像素左侧和右侧垂直的插入两个像素值,然后利用这两个插入的像素(灰色圆)在相应的位置插入像素值。
cv::resize(reduced2, newimage, cv::Size(), 4, 4, cv::INTER_LINEAR);
本篇文章是我学习opencv做的笔记,可能存在许多不足,欢迎大家批评指正!有问题可以随时和我交流。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。