OpenCV成长之路(7):图像滤波
滤波实际上是信号处理里的一个概念,而图像本身也可以看成是一个二维的信号。其中像素点灰度值的高低代表信号的强弱。
高频:图像中灰度变化剧烈的点。
低频:图像中平坦的,灰度变化不大的点。
根据图像的高频与低频的特征,我们可以设计相应的高通与低通滤波器,高通滤波可以检测图像中尖锐、变化明显的地方;低通滤波可以让图像变得光滑,滤除图像中的噪声。
下面我们来看一下OpenCV中的一些滤波函数:
一、低通滤波
1,blur函数
这个函数是一个平滑图像的函数,它用一个点邻域内像素的平均灰度值来代替该点的灰度。
cv::blur(image,result,cv::Size(,));
2,高斯模糊
上面的blur的平滑原理是用邻域内的平均值来代替当前的灰度值,但是我们往往希望越靠近该像素的点提供越高的权重,这样就产生了高斯模糊滤波。它的滤波器或者叫遮罩是一个高斯分布的二维矩阵。
cv::GaussianBlur(image,result,cv::Size(,),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。中值滤波也是在实际中应用最多的平滑滤波,它可以有效的去除比如椒盐噪声一类的干扰。
下面我们对比一下上面三种滤波器的效果:
#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(,));
GaussianBlur(image,gaussianResult,Size(,),1.5);
medianBlur(image,medianResult,); namedWindow("blur");imshow("blur",blurResult);
namedWindow("Gaussianblur");imshow("Gaussianblur",gaussianResult);
namedWindow("medianBlur");imshow("medianBlur",medianResult); waitKey();
return ;
}
二、高通滤波:边缘检测
高通滤波器最好的一个应用就是边缘检测,由文章开头分析可知高频是图像中变化剧烈的地方,所以图像的边缘区域恰好符合这一特性,我们可以利用高通滤波让图像的边缘显露出来,进一步计算图像的一些特征。
边缘检测本来打算作为一个单独的主题来写一篇文章,但是由于Canny边缘检测算法比较复杂,篇幅也较大,所以先把Sobel边缘检测在高通滤波这里作为一个实例,以后Canny边缘检测作为单独的一篇文章来写。
实际上OpenCV有提供了Sobel边缘检测的函数,但是一方面阈值好像取的不太好,另一方面没有对最后边缘作细化处理,所以效果并不太让人满意,本文是模仿Matlab中算法来写的,相关的理论可以参考我原来写过的一篇文章《视觉算法:Sobel边缘检测》。
下面是Sobel实现的C++代码:
bool Sobel(const Mat& image,Mat& result,int TYPE)
{
if(image.channels()!=)
return false;
// 系数设置
int kx();
int ky();
if( TYPE==SOBEL_HORZ ){
kx=;ky=;
}
else if( TYPE==SOBEL_VERT ){
kx=;ky=;
}
else if( TYPE==SOBEL_BOTH ){
kx=;ky=;
}
else
return false; // 设置mask
float mask[][]={{,,},{,,},{-,-,-}};
Mat y_mask=Mat(,,CV_32F,mask)/;
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=;
double cutoff=scale*mean(gradient)[]; result.create(image.size(),image.type());
result.setTo();
for(int i=;i<image.rows-;i++)
{
float* sbxPtr=sobelX.ptr<float>(i);
float* sbyPtr=sobelY.ptr<float>(i);
float* prePtr=gradient.ptr<float>(i-);
float* curPtr=gradient.ptr<float>(i);
float* lstPtr=gradient.ptr<float>(i+);
uchar* rstPtr=result.ptr<uchar>(i);
// 阈值化和极大值抑制
for(int j=;j<image.cols-;j++)
{
if( curPtr[j]>cutoff && (
(sbxPtr[j]>kx*sbyPtr[j] && curPtr[j]>curPtr[j-] && curPtr[j]>curPtr[j+]) ||
(sbyPtr[j]>ky*sbxPtr[j] && curPtr[j]>prePtr[j] && curPtr[j]>lstPtr[j]) ))
rstPtr[j]=;
}
} return true;
}
OpenCV成长之路(7):图像滤波的更多相关文章
- OpenCV成长之路:图像滤波
http://ronny.blog.51cto.com/8801997/1394138 OpenCV成长之路:图像滤波 2014-04-11 14:28:44 标签:opencv 边缘检测 sobel ...
- OpenCV成长之路:图像直方图的应用
OpenCV成长之路:图像直方图的应用 2014-04-11 13:57:03 标签:opencv 图像 直方图 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否 ...
- OpenCV成长之路:图像直方图
http://ronny.blog.51cto.com/8801997/1394115 2014-04-11 13:47:27 标签:opencv 直方图 统计表 原创作品,允许转载,转载时请务必以超 ...
- OpenCV成长之路:直线、轮廓的提取与描述
http://ronny.blog.51cto.com/8801997/1394139 OpenCV成长之路:直线.轮廓的提取与描述 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...
- OpenCV成长之路(2):图像的遍历
我们在实际应用中对图像进行的操作,往往并不是将图像作为一个整体进行操作,而是对图像中的所有点或特殊点进行运算,所以遍历图像就显得很重要,如何高效的遍历图像是一个很值得探讨的问题. 一.遍历图像的4种方 ...
- opencv第三课,图像滤波
1.介绍 OpenCV图像处理技术中比较热门的图像滤波操作主要被分为了两大类:线性邻域滤波和非线性滤波.线性邻域滤波常见的有“方框滤波“,”均值滤波“和”高斯滤波“三种,二常见的非线性滤波主要是中值滤 ...
- OpenCV成长之路(5):图像直方图的应用
正如第4篇文章所说的图像直方图在特征提取方面有着很重要的作用,本文将举两个实际工程中非常实用的例子来说明图像直方图的应用. 一.直方图的反向映射. 我们以人脸检测举例,在人脸检测中,我们第一步往往需要 ...
- OpenCV成长之路(4):图像直方图
一.图像直方图的概念 图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的.纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比. 图 ...
- OpenCV成长之路 01、图像的读写与显示
一.工具篇 工欲善其事,必先利其器.学习OpenCV,肯定少不于基本的编程工具与OpenCV库.在Windows平台下你可以选择Visual Studio.CodeBlock等,当然你也可以选择在Li ...
随机推荐
- spark 读取 elasticsearch数据
–master spark://10.8.2.100:7077 –jars /usr/local/spark-1.5.2/lib/elasticsearch-hadoop-2.1.1.jar
- git-tag
标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ git tag # 在控制台打印出当前仓库的所有标签 $ git tag -l 'v0.1.*' # 搜索符合模式的标签 打标签 g ...
- select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
http://hi.baidu.com/%B1%D5%C4%BF%B3%C9%B7%F0/blog/item/e7284ef16bcec3c70a46e05e.html select函数用于在非阻塞中 ...
- linux 相关快捷键
linux 相关快捷键 http://linux.chinaunix.net/begin/2004-10-05/34.shtml#_Toc41417098 1.使用虚拟控制台登录后按“Alt+F2”键 ...
- 深入浅出MyBatis
参考文献:深入浅出MyBatis MyBatis功能架构图: MyBatis内部原理流程图: 详情见:深入浅出MyBatis
- Winsock 入门 判读主机字节序 示例
#include <stdio.h> union endian_u { /*最大成员的长度就是联合成员的长度.联合可以在定义时直接进行初始化,但这个初始化必须是联合第一个成员的类型,所以把 ...
- 集成EaseUI报错 环信3.1.5,托入EaseUI后,系统文件报错
一托入EaseUI的文件夹,就各种系统报错,NSObject文件也错了,不能编译UIKit头文件…………………… 解决方案以及参考文档 http://www.jianshu.com/p/291ac34 ...
- iTunes访问自己应用的沙盒
- jQuery checkbox 所有 全选、全不选、是否选中等
下面是网络收集: jquery判断checked的三种方法:.attr('checked): //看版本1.6+返回:”checked”或”undefined” ;1.5-返回:true或fals ...
- [C#]集合已修改;可能无法执行枚举操作
摘要 我相信很多人对这个再熟悉不过了.对已经修改的集合进行操作就会出现这个错. 解决办法 比如有下面的一段代码,我们创建一个集合,并向集合中添加10个数,然后,我们循环再将这些数移除了. static ...