图像滤波是指去除图像中不重要的内容而使关心的内容表现得更加清晰的方法,例如去除图像中的噪声、提取某些信息等.根据图像滤波目的的不同,可以将图像滤波分为消除图像噪声的滤波和提取图像中部分特征信息的滤波.图像滤波需要保证图像中关注的信息不在滤波过程中被破坏,因
此,图
像去除噪声应最大程度不损坏图像的轮廓和边缘信息,同时图像去除噪声后应使图像视觉效果更加清晰.
去除图像中的噪声称作图像的平滑或者图像去噪.由于
噪声信号在图像中主要集中在高频 ,因此图像去噪可以看作去除图像中高频段信号的同时保留图像的低频段和中频段信号的滤波操作.图像滤波使用的滤波器允许通过的信号频段,决定了滤波操作是去除噪声还是提取特征信息.噪声信号主要集中在高额段,因此,如果滤波过程中使用的滤被器是允许低频和中频信号通过的低通或者高阻滤波器,那么滤波的效果就是去除图像中的噪声.图像中绞理变化越明显的区域信号频率也就越高,因此使用高通滤波器对图像信号处理可以起到对图像边缘信息提取、增强和图像锐化的作用.
在部分图像处理书籍中,常用图像模糊来代替图像的低通滤波,因为图像的低通滤波在去除图
像噪声的同时会将图像的边缘信息弱化,使得整幅图像看起来变得模糊"图像模糊"因此而得名.
在低通滤液中,模糊可以与滤波等价,例如图像高斯模糊和图像高斯低通滤波是个概念.
均值滤波:
均值滤波的优点是
在像素值变换趋势一致的情况下,可以将受噪声影响而突然变化的像索值修正为周围邻近像素值的平均值,去除噪声影响.但是这种滤波方式会缩小像素值之间的差距 使得细节信息变得更加模糊,滤波器范围越大
,变模糊的效果越明显.
代码:
void visionagin::BlurOperate(Mat& img)
{
Mat gauss = imread("C:\\Users\\86176\\Downloads\\visionimage\\Gauss.jpeg");
Mat salt = imread("C:\\Users\\86176\\Downloads\\visionimage\\salt.jpeg");
Mat gauss_res, salt_res, res;
blur(img, res, Size(3, 3), Point(-1, -1), BORDER_CONSTANT);
blur(gauss, gauss_res,Size(3,3), Point(-1, -1), BORDER_CONSTANT);
blur(salt, salt_res, Size(3, 3), Point(-1, -1), BORDER_CONSTANT);
imshow("res", res);
imshow("gauss_res", gauss_res);
imshow("salt_res", salt_res);
}
2:方框滤波:
方框滤波也是求滤波器内所有像索值的和
,但
是方框滤
波可以选择不进行归一化,
是将所有像素值的和作为滤波结果,而不是所有像素值的平均值.
该函数是在
bo
xF
ilter()
函数功能基础上进行的功能扩展 ,
CV_
8U
数据类型的图像
像索值为
255
,计算平
方后数
据会变得更大 ,即使归一化操作也不能保证像素值不会超过最大值 。CV_32F
数据类型的图像像素 值是 0到1
的小数,
计算平方会变得更小,但结果始终保持在
0- 1.
因此,该函数在
处理图像滤波的任务时主要针对的是
CV
32F
数据类型的图像
,而且根
据计算关系可知
在归一化
后,图像在变模糊的同时亮度也会变暗.
代码:
void visionagin::BoxblurOperate(Mat& img)
{
Mat gauss = imread("C:\\Users\\86176\\Downloads\\visionimage\\Gauss.jpeg");
Mat salt = imread("C:\\Users\\86176\\Downloads\\visionimage\\salt.jpeg");
Mat gauss_res, salt_res, res,res1;
Mat img32f;
boxFilter(img, res, -1, Size(3, 3), Point(-1, -1), true, BORDER_CONSTANT);
img.convertTo(img32f, CV_32F, 1.0 / 255);//现将原图像数据类型转换成32f,再sqrboxfilter,保证值在0到1;
sqrBoxFilter(img32f, res1, -1, Size(3, 3), Point(-1, -1), true, BORDER_CONSTANT);//一般处理CV_32F数据
boxFilter(gauss, gauss_res,-1, Size(3, 3), Point(-1, -1),true,BORDER_CONSTANT);
boxFilter(salt, salt_res, -1, Size(3, 3), Point(-1, -1), true,BORDER_CONSTANT);
imshow("res1", res1);
imshow("res", res);
imshow("gauss_res", gauss_res);
imshow("salt_res", salt_res);
}
3:高斯滤波
代码:
void visionagin::Gaussblur(Mat& img)
{
Mat gauss = imread("C:\\Users\\86176\\Downloads\\visionimage\\Gauss.jpeg");
Mat salt = imread("C:\\Users\\86176\\Downloads\\visionimage\\salt.jpeg");
Mat gauss_res, salt_res, res1;
GaussianBlur(gauss, gauss_res, Size(3, 3), 10, 20, BORDER_CONSTANT);
GaussianBlur(salt , salt_res, Size(3, 3), 10, 20, BORDER_CONSTANT);
GaussianBlur(img, res1, Size(3, 3), 10, 20, BORDER_CONSTANT);
imshow("gauss", gauss);
imshow("res1", res1);
imshow("gauss_res", gauss_res);
imshow("salt_res", salt_res);
}
4:可分离滤波
前面介绍的滤波函数使用的滤波器都是
固定形式的滤波器,
有时需要根据实际需求调整滤波模板。
例如,
在滤波计算过程中 ,
滤波器中心位置
像素值不参与计算、滤波
器中
参与计算的像索值不
是一个矩形区域等.
OpenCV
无法根据每种需求单独编写滤波函数,因此
Open
CV
提供了根据自
定义滤波器实现图像滤波的函数
即本章最开始
介绍的
卷积函数
filter
2D().
图像滤波是一个并行的算法,在可以提供并行运算的处理器中可以极大地加快图像滤波的处理速度.除此之外
,图像
滤波还具有可分离性,
这个性质我们在高斯滤波中有简单的接触.可分离性指的是先对x方向滤波
再对y
滤波的结果与将两个方向的滤波器联合后整体滤波的结果相同。两个方向的滤波器的联合就是将两个方向的滤波器相乘,得到一个矩形的滤波器.
因此
在高斯滤波中,
我们利用
getGaussia
nK
ernel
函数分别得x
方向和y
方向的滤波器之后通过生成联合滤波器或者分别用两个方向的滤波器进行滤波,
计算结果相同.两个方向联合滤
波需要在使用
filter2D()
函数滤波之前计算联和
滤波器,而两个方向分
别滤波
需要调用两次
fil
ter
2D()
函数,增加了通过代码实现的复杂性 因此
OpenCV
提供了可以输入两个
方向滤波器实现滤波的滤波函数 s
epFilter2D().
代码:
void visionagin:: Myfilter()
{
uchar num[] = {
1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15,
16,17,18,19,20,
21,22,23,24,25,
};
Mat temp{ Size(5,5),CV_32FC1,num };
//x,y方向和联合滤波器构建
Mat a = (Mat_<float>(3, 1) << -1, 3, -1);//y方向滤波器
Mat b = a.reshape(1, 1);//x方向滤波器
Mat ab = a * b;
Mat gauss = getGaussianKernel(3, 1);
Mat gauss_num, sep_xy;
GaussianBlur(temp, gauss_num, Size(3, 3), 1, 1, BORDER_CONSTANT);
sepFilter2D(temp, sep_xy, -1, gauss, gauss, Point(-1, -1), 0, BORDER_CONSTANT);//两个方向的滤波器都是gauss
cout << gauss_num << endl;
cout << sep_xy << endl;
Mat temp_x, temp_y, temp_xy1,temp_xy2;
filter2D(temp, temp_x, -1, b, Point(-1, -1));
filter2D(temp_x, temp_xy1,-1, a, Point(-1, -1));//先x方向后y方向
filter2D(temp, temp_xy2, -1, ab, Point(-1, -1));//直接与联合滤波器进行滤波
cout << temp_xy1 << endl;
cout << temp_xy2 << endl;
}