http://ronny.blog.51cto.com/8801997/1394138

OpenCV成长之路:图像滤波

2014-04-11 14:28:44

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ronny.blog.51cto.com/8801997/1394138

滤波实际上是信号处理里的一个概念,而图像本身也可以看成是一个二维的信号。其中像素点灰度值的高低代表信号的强弱。

高频:图像中灰度变化剧烈的点。

低频:图像中平坦的,灰度变化不大的点。

根据图像的高频与低频的特征,我们可以设计相应的高通与低通滤波器,高通滤波可以检测图像中尖锐、变化明显的地方;低通滤波可以让图像变得光滑,滤除图像中的噪声。

下面我们来看一下OpenCV中的一些滤波函数:

一、低通滤波

1,blur函数

这个函数是一个平滑图像的函数,它用一个点邻域内像素的平均灰度值来代替该点的灰度。

cv::blur(image,result,cv::Size(5,5));

2,高斯模糊

上面的blur的平滑原理是用邻域内的平均值来代替当前的灰度值,但是我们往往希望越靠近该像素的点提供越高的权重,这样就产生了高斯模糊滤波。它的滤波器或者叫遮罩是一个高斯分布的二维矩阵。

cv::GaussianBlur(image,result,cv::Size(5,5),1.5);

参数image为输入图像,result为输出图像,Size(5,5)定义了核的大小,最后一个参数说明了高斯核的方差。

3,中值滤波

上面讲到的2个滤波器,都是邻域内的像素按照一个权重相加最后设置为当前点的灰度值,这种操作又称为卷积,这样的滤波器叫线性滤波器,另外还有一种非线性的滤波器,比如中值滤波器,它是取邻域内所有像素的中值作为当前点的灰度值。

中值即排序后中间的那个值:median({1,2,3,3,7,5,1,8})=3。

cv::medianBlur(image,result,5);

其中最后一个参数指定了邻域的大小为5*5。中值滤波也是在实际中应用最多的平滑滤波,它可以有效的去除比如椒盐噪声一类的干扰。

下面我们对比一下上面三种滤波器的效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
    using namespace cv;
    Mat image=imread("../cat.png");
    cvtColor(image,image,CV_BGR2GRAY);
    Mat blurResult;
    Mat gaussianResult;
    Mat medianResult;
    blur(image,blurResult,Size(5,5));
    GaussianBlur(image,gaussianResult,Size(5,5),1.5);
    medianBlur(image,medianResult,5);
    namedWindow("blur");imshow("blur",blurResult);
    namedWindow("Gaussianblur");imshow("Gaussianblur",gaussianResult);
    namedWindow("medianBlur");imshow("medianBlur",medianResult);
    waitKey();
    return 0;
}

二、高通滤波:边缘检测

高通滤波器最好的一个应用就是边缘检测,由文章开头分析可知高频是图像中变化剧烈的地方,所以图像的边缘区域恰好符合这一特性,我们可以利用高通滤波让图像的边缘显露出来,进一步计算图像的一些特征。

边缘检测本来打算作为一个单独的主题来写一篇文章,但是由于Canny边缘检测算法比较复杂,篇幅也较大,所以先把Sobel边缘检测在高通滤波这里作为一个实例,以后Canny边缘检测作为单独的一篇文章来写。

实际上OpenCV有提供了Sobel边缘检测的函数,但是一方面阈值好像取的不太好,另一方面没有对最后边缘作细化处理,所以效果并不太让人满意,本文是模仿Matlab中算法来写的,相关的理论可以参考我原来写过的一篇文章《视觉算法:Sobel边缘检测》。

下面是Sobel实现的C++代码:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
bool Sobel(const Mat& image,Mat& result,int TYPE)
{
    if(image.channels()!=1)
        return false;
    // 系数设置
    int kx(0);
    int ky(0);
    if( TYPE==SOBEL_HORZ ){
        kx=0;ky=1;
    }
    else if( TYPE==SOBEL_VERT ){
        kx=1;ky=0;
    }
    else if( TYPE==SOBEL_BOTH ){
        kx=1;ky=1;
    }
    else
        return false;
    // 设置mask
    float mask[3][3]={{1,2,1},{0,0,0},{-1,-2,-1}};
    Mat y_mask=Mat(3,3,CV_32F,mask)/8;
    Mat x_mask=y_mask.t(); // 转置
    // 计算x方向和y方向上的滤波
    Mat sobelX,sobelY;
    filter2D(image,sobelX,CV_32F,x_mask);
    filter2D(image,sobelY,CV_32F,y_mask);
    sobelX=abs(sobelX);
    sobelY=abs(sobelY);
    // 梯度图
    Mat gradient=kx*sobelX.mul(sobelX)+ky*sobelY.mul(sobelY);
    // 计算阈值
    int scale=4;
    double cutoff=scale*mean(gradient)[0];
    result.create(image.size(),image.type());
    result.setTo(0);
    for(int i=1;i<image.rows-1;i++)
    {
        float* sbxPtr=sobelX.ptr<float>(i);
        float* sbyPtr=sobelY.ptr<float>(i);
        float* prePtr=gradient.ptr<float>(i-1);
        float* curPtr=gradient.ptr<float>(i);
        float* lstPtr=gradient.ptr<float>(i+1);
        uchar* rstPtr=result.ptr<uchar>(i);
        // 阈值化和极大值抑制
        for(int j=1;j<image.cols-1;j++)
        {
            if( curPtr[j]>cutoff && (
                (sbxPtr[j]>kx*sbyPtr[j] && curPtr[j]>curPtr[j-1] && curPtr[j]>curPtr[j+1]) ||
                (sbyPtr[j]>ky*sbxPtr[j] && curPtr[j]>prePtr[j] && curPtr[j]>lstPtr[j]) ))
                rstPtr[j]=255;
        }
    }
    return true;
}

本文出自 “Ronny的成长之路” 博客,请务必保留此出处http://ronny.blog.51cto.com/8801997/1394138

OpenCV成长之路:图像滤波的更多相关文章

  1. OpenCV成长之路:图像直方图的应用

    OpenCV成长之路:图像直方图的应用 2014-04-11 13:57:03 标签:opencv 图像 直方图 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否 ...

  2. OpenCV成长之路:直线、轮廓的提取与描述

    http://ronny.blog.51cto.com/8801997/1394139 OpenCV成长之路:直线.轮廓的提取与描述 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...

  3. OpenCV成长之路(2):图像的遍历

    我们在实际应用中对图像进行的操作,往往并不是将图像作为一个整体进行操作,而是对图像中的所有点或特殊点进行运算,所以遍历图像就显得很重要,如何高效的遍历图像是一个很值得探讨的问题. 一.遍历图像的4种方 ...

  4. OpenCV成长之路(9):特征点检测与图像匹配

    特征点又称兴趣点.关键点,它是在图像中突出且具有代表意义的一些点,通过这些点我们可以用来识别图像.进行图像配准.进行3D重建等.本文主要介绍OpenCV中几种定位与表示关键点的函数. 一.Harris ...

  5. OpenCV成长之路(7):图像滤波

    滤波实际上是信号处理里的一个概念,而图像本身也可以看成是一个二维的信号.其中像素点灰度值的高低代表信号的强弱. 高频:图像中灰度变化剧烈的点. 低频:图像中平坦的,灰度变化不大的点. 根据图像的高频与 ...

  6. OpenCV成长之路(5):图像直方图的应用

    正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射. 我们以人脸检测举例,在人脸检测中,我们第一步往往需要 ...

  7. OpenCV成长之路(4):图像直方图

    一.图像直方图的概念 图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的.纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比. 图 ...

  8. OpenCV成长之路 01、图像的读写与显示

    一.工具篇 工欲善其事,必先利其器.学习OpenCV,肯定少不于基本的编程工具与OpenCV库.在Windows平台下你可以选择Visual Studio.CodeBlock等,当然你也可以选择在Li ...

  9. OpenCV成长之路:图像直方图

    http://ronny.blog.51cto.com/8801997/1394115 2014-04-11 13:47:27 标签:opencv 直方图 统计表 原创作品,允许转载,转载时请务必以超 ...

随机推荐

  1. C 语言学习准备

    摘要:用 C#语言学习了一些数据结构,突然想学习 C 语言,为了学习C,本文准备好资料. C 语言学习准备 作者:乌龙哈里 时间:2015-11-17 平台:Window7 64bit,Visual ...

  2. django urls.py更改遇到问题

    Q:TypeError: view must be a callable or a list/tuple in the case of include() A:django 1.10版本改了写法了.首 ...

  3. 二十七、oracle 例外

    一.例外分类oracle将例外分为预定义例外.非预定义例外和自定义例外三种.1).预定义例外用于处理常见的oracle错误.2).非预定义例外用于处理预定义例外不能处理的例外.3).自定义例外用于处理 ...

  4. js变量,语句

  5. oracle导入dmp数据库文件

    要用sys账户登录数据库,创建和dmp文件一样的表空间名称 1. 创建表空间 例如: create tablespace test(表空间名称) datafile 'F:\oracle\oradata ...

  6. gitlab自动备份

    1.周期性计划任务: $crontab -e 0 0 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create $service crond res ...

  7. [妙味JS基础]第十课:日期对象、时钟倒计时

    知识点总结 时间.年.月.日.时.分.秒 new Date() ->当前系统的时间对象 数字类型: getFullYear().getYear().getUTCFullYear() getYea ...

  8. 【LeetCode】24. Swap Nodes in Pairs

    Given a linked list, swap every two adjacent nodes and return its head. For example,Given 1->2-&g ...

  9. C#数组和元组

    声明数组 int[] myArray; 初始化数组 myArray = new int[4]; 数组是引用类型当初始化完毕后,将在托管堆上分配内存空间,其结构图如下

  10. agnentX学习存在疑问?

    在RFC2741中这样定义: 4.3中有如下段落: A general architectural division of labor between master agent and  subage ...