zoukankan      html  css  js  c++  java
  • 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 }

    效果对比:

  • 相关阅读:
    python基础知识0-5(单双向队列)
    python基础知识0-4
    python函数篇0-1
    面试题17:合并两个排序的链表
    面试题16:反转链表
    面试题15:链表中倒数第k个结点
    面试题14:调整数组顺序使奇数位于偶数前面
    面试题13:在O(1)时间删除链表结点
    面试题12:打印1到最大的n位数
    面试题11:数值的整数次方
  • 原文地址:https://www.cnblogs.com/zmm1996/p/10664401.html
Copyright © 2011-2022 走看看