模糊原理
- Smooth/Blur 是图像处理中最简单和常用的操作之一
- 使用该操作的原因之一就为了给图像预处理时候减低噪声
- 使用Smooth/Blur操作其背后是数学的卷积计算
其中:f()表示一副图像,i、j表示图像的行和列,h(k,l)表示卷积算子(和)(也可以叫掩膜),k l又可以叫窗口大小(掩膜的大小,比如3*3),g()表示输出的像素值; - 通常这些卷积算子计算都是线性操作,所以又叫线性滤波
假设有6x6的图像像素点矩阵。
卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个像素点值之和取平均值赋给中心红色像素作为它卷积处理之后新的像素值。每次移动一个像素格。
1. 归一化盒子滤波(均值滤波)
blur(Mat src, Mat dst, Size(xradius, yradius), Point(-1,-1));
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main(int argc,char** argv){
Mat src=imread("E:/Experiment/OpenCV/Pictures/dog2.jpg");
if(!src.data){
printf("could not load image ...");
return -1;
}
char windows_name[]="input Image";
namedWindow(windows_name,CV_WINDOW_AUTOSIZE);
imshow(windows_name,src);
//均值模糊
Mat dst1, dst2, dst3;
//Size()的参数必须是正数
blur(src, dst1, Size(15, 15), Point(-1, -1));//均值模糊,Size(15, 15)表示卷积算子(掩膜)大小(不一定要正方形)为15*15, Point(-1, -1) 表示取掩膜中心点为计算结果
blur(src, dst2, Size(29, 1), Point(-1, -1));//x方向模糊看起来像是瞬间移动一样
blur(src, dst3, Size(1, 15), Point(-1, -1));//y方向模糊看起来会把图像拉高一点点
imshow("blur1", dst1);
imshow("blur2", dst2);
imshow("blur3", dst3);
waitKey(0);
return 0;
}
2. 高斯滤波
GaussianBlur(Mat src, Mat dst, Size(11, 11), sigmax, sigmay);
其中Size(x, y), x, y 必须是正数而且是奇数
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main(int argc,char** argv){
Mat src=imread("E:/Experiment/OpenCV/Pictures/dog2.jpg");
if(!src.data){
printf("could not load image ...");
return -1;
}
char windows_name[]="input Image";
namedWindow(windows_name,CV_WINDOW_AUTOSIZE);
imshow(windows_name,src);
//高斯模糊
Mat dst1, dst2, dst3;
//同样的卷积因子,均值模糊会比高斯模糊更模糊些
//Size()的参数必须是正数而且是奇数,否则会报错
//参数sigma x 11, sigma y 11 是控制x,y方向高斯权重分布的,似乎是值越大,图像越模糊,但不是线性关系
GaussianBlur(src, dst1, Size(15, 15), 11, 11);//高斯模糊,Size(15, 15)表示卷积算子(掩膜)大小(不一定要正方形)为15*15
GaussianBlur(src, dst2, Size(15, 1), 11, 11);//x方向模糊看起来像是瞬间移动一样
GaussianBlur(src, dst3, Size(1, 15), 11, 11);//y方向模糊看起来会把图像拉高一点点
imshow("gaussian blur1", dst1);
imshow("gaussian blur2", dst2);
imshow("gaussian blur3", dst3);
waitKey(0);
return 0;
}
说明1
模糊原理: 同样的卷积因子,均值模糊会比高斯模糊更模糊些。 不管对于哪种模糊,卷积和(比如3*3)的大小最好是奇数
1. 归一化盒子滤波(均值滤波): 就是上面的卷积计算,卷积算子(掩膜)中的格子权重都是1,所以卷积和之后还要除以卷积因子的大小取均值
2. 高斯滤波: 相比于均值滤波,权重是不一样,但是权重和为1,所以计算卷积和之后不用取均值了
说明2
在模糊处理方面,filter2D() 也可以自己定义卷积核;
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
int main(int argc,char** argv){
Mat src,dst1,dst2;
src=imread("E:/Experiment/OpenCV/Pictures/dog2.jpg");
if(!src.data){
printf("could not load image ...");
return -1;
}
imshow("input",src);
//模糊处理一
Mat kernel=(Mat_<float>(3,3)<< 1.0/9, 1.0/9, 1.0/9, 1.0/9, 1.0/9, 1.0/9 , 1.0/9, 1.0/9, 1.0/9);
filter2D(src,dst1,src.depth(),kernel);
//filter2D(src,dst,-1,kernel);
imshow("filter2D",dst1);
//模糊处理二
blur(src, dst2, Size(3,3), Point(-1, -1));
imshow("Blur",dst2);
waitKey(0);
return 0;
}
效果:
整体程序代码:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main(int argc,char** argv){
Mat src=imread("E:/Experiment/OpenCV/Pictures/test.jpg");
if(src.empty()){
printf("Could not load Image ...");
return -1;
}
char input_windows[]="Input Image";
char blur_windows[]="blur Image";
char gblur_windows[]="GBlur Image";
namedWindow(input_windows,CV_WINDOW_AUTOSIZE);
namedWindow(blur_windows,CV_WINDOW_AUTOSIZE);
namedWindow(gblur_windows,CV_WINDOW_AUTOSIZE);
imshow(input_windows,src);
//模糊处理
Mat blur_dst,gblur_dst;
//均值模糊
blur(src, blur_dst, Size(5, 5), Point(-1, -1));
imshow(blur_windows,blur_dst);
//高斯模糊
GaussianBlur(src, gblur_dst, Size(5, 5), 11, 11);
imshow(gblur_windows,gblur_dst);
waitKey(0);
return 0;
}
运行结果
推荐参考博客
https://blog.csdn.net/huanghuangjin/article/details/80917986