OpenCV基础(六)---图像滤波

图像滤波

对图像进行单个像素操作,主要是进行对比度和阈值处理

而图像滤波在像素邻域间进行,一来达到我们希望的效果,二来进一步进行图像特征提取

 滤波分为空间域和频域滤波,空间域滤波又分线性、非线性滤波

常用的线性滤波有,均值滤波,高斯滤波;非线性滤波有中值滤波,双边滤波

线性滤波

均值模糊:blur()

void blur( InputArray src, OutputArray dst,
                        Size ksize, Point anchor = Point(-1,-1),
                        int borderType = BORDER_DEFAULT );
  • src 源图像
  • dst 输出图像
  • ksize 卷积核
  • anchor 锚点在核中心
  • borderType 图像边界处理方式

卷积核如下图所示

高斯模糊:GaussianBlur()

void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                                double sigmaX, double sigmaY = 0,
                                int borderType = BORDER_DEFAULT );
  • src 源图像
  • dst 目的图像
  • ksize 高斯核,ksize.width与ksize.height可以不同,但必须为正的奇数.可以为0,通过simga计算得到
  • sigmaX  高斯核在x方向的标准差
  • sigmaY  高斯核在y方向的标准差
  • borderType 边界像素处理方式

均值与高斯模糊代码:

 1 #include <opencv2/opencv.hpp>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 int main() {
 8 
 9     Mat srcImage = imread("D:/lena.png");
10     if (!srcImage.data) {
11         cout << "could not load image" << endl;
12         return -1;
13     }
14     imshow("src Image", srcImage);
15 
16     Mat bImage, gImage;
17     blur(srcImage, bImage, Size(3, 3));
18     GaussianBlur(srcImage, gImage, Size(3, 3), 11, 11);
19 
20     imshow("blur", bImage);
21     imshow("Gaussblur", bImage);
22     waitKey(0);
23     return 0;
24 }

效果图:

 

非线性滤波

统计排序滤波器是一种非线性滤波器,最知名的便是中值滤波。它将滤波器所包含的图像区域进行排序,选取中间值代替该点像素值,

其对椒盐噪声处理十分有效

 中值滤波

void medianBlur( InputArray src, OutputArray dst, int ksize );
  • src 源图像
  • dst 目的图像
  • ksize 孔径尺寸,必须为大于1的奇数
 1 #include <opencv2/opencv.hpp>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 
 8 //加入椒盐噪声
 9 void salt(Mat image, int n)
10 {
11     int i, j;
12     for (int k = 0; k<n; k++)
13     {
14         // rand()是随机数生成器
15         i = rand() % image.cols;
16         j = rand() % image.rows;
17         if (image.type() == CV_8UC1)
18         { // 灰度图像
19             if(rand()% 2 == 0)
20             image.at<uchar>(j, i) = 255;
21             else
22                 image.at<uchar>(j, i) = 0;
23         }
24         else if (image.type() == CV_8UC3)
25         { // 彩色图像
26             if (rand()%2==0) {
27                 image.at<cv::Vec3b>(j, i)[0] = 255;
28                 image.at<cv::Vec3b>(j, i)[1] = 255;
29                 image.at<cv::Vec3b>(j, i)[2] = 255;
30             }
31             else{
32                 image.at<cv::Vec3b>(j, i)[0] = 0;
33                 image.at<cv::Vec3b>(j, i)[1] = 0;
34                 image.at<cv::Vec3b>(j, i)[2] = 0;
35             }
36         }
37     }
38 }
39 
40 int main() {
41 
42     Mat srcImage = imread("D:/lena.png");
43     if (!srcImage.data) {
44         cout << "could not load image" << endl;
45         return -1;
46     }
47     salt(srcImage, 1500);   //加入椒盐噪声
48     imshow("src Image", srcImage);   
49     
50     Mat mImage;
51     medianBlur(srcImage, mImage, 3); //中值滤波
52     imshow("medianblur", mImage);
53  
54     waitKey(0);
55     return 0;
56 

效果图:

双边滤波

1.介绍    双边滤波(Bilateral Filtering)是一种简单,非迭代的保边去噪算法。

在最广泛的意义上“滤波”这一词,滤波图像在给定位置的值是输入图像在相同位置小邻域中的函数。

例如,高斯低通滤波(Gaussian low-pass fitering)计算像素邻域中得加权平均值,权重随着远离邻域中心减少。

虽然可以给出这种权重下降的正式和定量解释,但直觉是图像通常在空间上缓慢变化,

因此邻近像素可能具有相似的值,因此将它们平均在一起是合适的。

破坏这些邻近像素的噪声值与信号值相互关联较少,因此,当信号被保留时,噪声平均消失。

然而在边缘处,假设的缓慢空间变化失效了,因此会被线性低通滤波器模糊。

如何在平滑图像的同时,防止边缘被平均呢?下面介绍双边滤波的基本思路。

2.思路

双边滤波的基本思想是在传统空域滤波中引入值域滤波。两个像素可以彼此接近,即占据附近的空间位置,或者它们可以彼此相似,即具有邻近的值。

考虑应用于图像的平移不变低通域滤波器:

归一化常数

类似的定义值滤波器:

在这种情况下归一化常数:

解决方案是结合空域和值滤波,组合滤波可以描述如下:

归一化常数是,

结合空域与值域滤波被定义为双边滤波。在光滑的区域,邻域中像素的值差异不大,双边滤波的效果与标准空间滤波等同,

平均的消除噪声引起的像素值之间的小的、弱相关的差异。

在边缘处,滤波器用其附近的明亮像素的平均值代替中心处的明亮像素,并且基本上忽略了暗像素,

反之,当滤波器以暗像素为中心时,则忽略了明亮像素。

至此,由于滤波器的空域成分,边界得以保存;由于滤波器的值域成分,清晰的边缘也得以保存

 void bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT );
  • src 单通道,浮点类型,源图像
  • dst 输出图像,与src类型一致
  • d  用于滤波的每个像素邻域的直径。如果它是非正的,

        它是从sigmaSpace计算出来的

  • sigmaColor  较大的参数值意味着像素邻域内的较远颜色(参见sigmaSpace)将混合在一起
  • sigmaSpace  坐标空间中的sigmaSpace滤波器。参数值越大意味着越远处的像素(若像素足够接近)会影响该点像素
 1 #include <opencv2/opencv.hpp>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 int main() {
 8     Mat src, dst;
 9     src = imread("D:/kitten-orig.png");
10     if (src.empty()) {
11         cout << "could not load image..." << endl;
12         return -1;
13     }
14     bilateralFilter(src, dst, 9, 75, 75); 
15     namedWindow("input", CV_WINDOW_AUTOSIZE);
16     imshow("input", src);
17     namedWindow("output", CV_WINDOW_AUTOSIZE);
18     imshow("output", dst);
19     imwrite("kitten-outp.png", dst); 
20     waitKey(0);
21 }

效果对比:

猜你喜欢

转载自www.cnblogs.com/zmm1996/p/10664401.html