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. easyDialog弹窗+zTree部门选择

    写一个父页面方法,将name和id赋值 function show(name,id) { $("#deptnoID").val(name); $("#deptnoId&q ...

  2. Math 对象 识记

    Math 对象用于执行数学任务. 1.使用 Math 的属性和方法的语法: var pi_value=Math.PI; var sqrt_value=Math.sqrt(15); 注释:Math 对象 ...

  3. 图片的 base64 编码

    图片的 base64 编码就是将一幅图片编码成一串字符串,使用该字符串代替图像地址.我们所看到的网页上的图片,都是需要消耗一个 http 请求下载而来的:(所有才有了 csssprites 技术< ...

  4. php分类

    <?php /* * PHP分页类 * @package Page * @Created 2013-03-27 * @Modify 2013-03-27 * @link http://www.6 ...

  5. ExtJS从入门到后面肯定要抛弃

    一.ExtJs定义 ①基于JavaScript语言 ②基于JavaSwing的MVC架构 ③支持组件化.模块化设计 ④提供“本地数据源”的支持 ⑤完完善与服务端的交互机制 ⑥是最有可能拥有大规模可视化 ...

  6. ServiceContract,OperationContract

    代码如下 [ServiceContract] //服务协定定义 using System.ServiceModel; public interface IInterface1 { [Operation ...

  7. DOM对象和JQuery有什么不同的地方?

    jQuery对象和DOM对象使用说明,需要的朋友可以参考下.1.jQuery对象和DOM对象第一次学习jQuery,经常分辨不清哪些是jQuery对象,哪些是 DOM对象,因此需要重点了解jQuery ...

  8. java中的词汇

    java中的词汇: 空白符:空格,制表符,换行符.他们的存在使得代码变得很美观. 标识符:由大小写字母,数字,下划线,美元符号组成.且数字不能用于标识符第一个字符. 字面值:变量的值通常使用表示常量的 ...

  9. 统计C语言程序行数

    补充前一篇中统计C语言程序行数的程序 写得比较匆忙,可能有些失误,等弄明白GitHub的用法并完善程序后再补充完整代码链接 没有写成函数,但经过简单修改可以作为一个计算或判断函数使用 判断算法主要为以 ...

  10. magento数据查询

    一.查询出所有的数据: 1.以mysql查询语句在magento里执行,以此来查询你所需要的语句! $read = Mage::getSingleton('core/resource')->ge ...