模糊原理
- Smooth/Blur是图像处理中最简单和常用的操作之一
- 使用操作的原因之一就是为了给图像预处理时候减低噪声
- 图像噪声是指存在于图像数据中的不必要的或多余的干扰信息
- Smooth/Blur操作原理是数学的卷积运算,根据不同卷积运算公式,划分了多种图像滤波方式
- 图像滤波:指的是在尽量保留图像特征的条件下对目标图像得噪声进行抑制
均值滤波
均值方程
计算过程
在6x6像素表中,3x3的卷积算子从图一所示的红色像素开始卷积,依次从左至右,从上至下。取黄色像素值之和的平均值赋给红色像素,则红色像素为卷积之后的新像素。由此每次移动一个像素。显然,计算平均值时,取值范围越大,"模糊效果"越强烈。
均值模糊
void blur( InputArray src, OutputArray dst,Size ksize, Point anchor = Point(-1,-1),int borderType = BORDER_DEFAULT );
/*******************************************************************
* src: 输入图像
* dst: 输出图像
* ksize: 内核大小
* anchor: 锚点
* 默认Point(-1,-1):锚点在核中心
* borderType: 外部像素边界模式(一般不管)
*********************************************************************/
高斯滤波
一阶高斯函数
简单变换下:
a表示得到曲线的高度,b是指曲线在x轴的中心,c指width(与半峰全宽有关),图形如下:
二阶高斯函数
正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小,图形如下:
计算过程
均值模糊中我们采用的是简单平均,显然不是很合理,因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。
权重矩阵
假定中心点的坐标是(0,0),那么距离它最近的8个点的坐标如下:
高斯模糊中为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:
这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终的权重矩阵.
计算高斯模糊
有了权重矩阵,就可以计算高斯模糊的值了。假设现有9个像素点,灰度值(0-255)如下:
每个点乘以自己的权重值,等到如下颜色值:
将这9个值加起来,就是中心点的高斯模糊的值。
对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图片,可以对RGB三个通道分别做高斯模糊。
高斯模糊
void medianBlur( InputArray src, OutputArray dst, int ksize );
/*******************************************************************
* src: 输入图像
* dst: 输出图像
* ksize: 内核大小
* 大小必须是大于1而且必须是奇数
*********************************************************************/
中值滤波
计算过程
中值是统计排序的滤波嚣,对椒盐噪声有很好的抑制作用椒盐噪声是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)
中值模糊
void medianBlur( InputArray src, OutputArray dst, int ksize );
/*******************************************************************
* src: 输入图像
* dst: 输出图像
* ksize: 内核大小
* 大小必须是大于1而且必须是奇数
*********************************************************************/
双边滤波
计算过程
双边滤波就是经典的常用的能够保留图像边缘信息的滤波算法之一。双边滤波是一种综合考虑滤波器内图像空域信息和滤波器内图像像素灰度值相似性的滤波算法,可以实现在保留区域信息的基础上实现对噪声的去除、对局部边缘的平滑。双边滤波对高频率的波动信号起到平滑的作用,同时保留大幅值的信号波动,进而实现对保留图像中边缘信息的作用。双边滤波器是两个滤波器的结合,分别考虑空域信息和值域信息,使得滤波器对边缘附近的像素进行滤波时,距离边缘较远的像素值不会对边缘上的像素值影响太多,进而保留了边缘的清晰性。
空域核:在窗口内每个位置都有权重(即每个位置的像素都考虑)。
i,j 为模板窗口的其他系数的坐标;
k,l为模板窗口的中心坐标点;
σ为高斯函数的标准差。
w空间域核由像素位置欧式距离决定的模板权值
值域核:一定像素差范围进行局部模糊,像素值高的在高的部分模糊,低的在低的那部分模糊,保留了边缘区分
i,j为模板窗口的其他系数的坐标,
f(i,j)表示图像在点i,j处的像素值;
k,l为模板窗口的中心坐标点,对应的像素值为f(k,l)
σ为高斯函数的标准差。
w值域核是由像素值的差值决定的模板权值
双边滤波器的模板权值双边滤波器的数据公式
双边滤波器的数据公式
- 空域权重衡量的是 p,q两点之间的距离,距离越远权重越低
- 值域权重衡量的是 p,q两点之间的像素值相似程度,越相似权重越大
双边模糊
void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType = BORDER_DEFAULT );
/*******************************************************************
* src: 输入图像
* dst: 输出图像
* d: 滤波过程中每个像素邻域的直径
* sigmaColor: 颜色空间滤波器的标准差值
* 参数越大表明该像素领域内有越多的颜色被混合到一起
* sigmaSpace: 空间间坐标中滤波器的标准差值
* borderType: 外部像素边界模式(一般不管)
*********************************************************************/
综合代码
#include <iostream>
#include <string>
#include <map>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class Blur
{
public:
Blur() :img(imread("test.jpg"))
{
result["原图"] = img;
}
void BlurByblur()
{
blur(img, result["blur"], Size(9, 9));
}
void BlurByGaussianBlur()
{
GaussianBlur(img, result["GaussianBlur"], Size(9, 9), 9, 9);
}
void BlurBymedianBlur()
{
medianBlur(img, result["medianBlur"], 9);
}
void BlurBybilateralFilter()
{
bilateralFilter(img, result["bilateralFilter"], 9, 9, 9);
}
void Show()
{
for (auto& v : result)
{
imshow(v.first, v.second);
}
waitKey(0);
}
private:
Mat img;
map<string, Mat> result;
};
int main()
{
Blur* p = new Blur;
p->BlurByblur();
p->BlurByGaussianBlur();
p->BlurBymedianBlur();
p->BlurBybilateralFilter();
p->Show();
return 0;
}