opencv学习笔记之cvSobel 函数解析
首先,我们来开一下计算机是如何检测边缘的。以灰度图像为例,它的理论基础是这样的,如果出现一个边缘,那么图像的灰度就会有一定的变化,为了方便假设由黑渐变为白代表一个边界,那么对其灰度分析,在边缘的灰度函数就是一个一次函数y=kx,对其求一阶导数就是其斜率k,就是说边缘的一阶导数是一个常数,而由于非边缘的一阶导数为零,这样通过求一阶导数就能初步判断图像的边缘了。通常是X方向和Y方向的导数,也就是梯度。理论上计算机就是通过这种方式来获得图像的边缘。
但是,具体应用到图像中你会发现这个导数是求不了的,因为没一个准确的函数让你去求导,而且计算机在求解析解要比求数值解麻烦得多,所以就想到了一种替代的方式来求导数。就是用一个3×3的窗口来对图像进行近似求导。拿对X方向求导为例,某一点的导数为第三列的元素之和减去第一列元素之和,这样就求得了某一点的近似导数。其实也很好理解为什么它就近似代表导数,导数就代表一个变化率,从第一列变为第三列,灰度值相减,当然就是一个变化率了。这就是所谓的Prewitt算子。这样近似X方向导数就求出来了。Y方向导数与X方向导数求法相似,只不过是用第三行元素之和减去第一行元素之和。X方向和Y方向导数有了,那么梯度也就出来了。这样就可以找出一幅图中的边缘了。
还有一个问题,由于求的是3×3中心点的导数,所以给第二列加了一个权重,它的权重为2,第一列和第三列的权重为1,好了,这就是Sobel算子了。相比Prewitt算子,Sobel的抗噪能力更强。如图所示:
这样,中心点的Y方向导数就求出来了。
举个例子吧。X点以Sobel方式求导数ΔX=1×50+2×30+1×50-(1×50+2×30+1×50)=0。这样可以看出这个点不是边界。
好了,了解了基本理论之后,我们看看OpenCv下的Sobel函数吧,void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );src:输入图像;dst:输出图像;xorder:x 方向上的差分阶数;yorder:y 方向上的差分阶数;aperture_size 扩展 Sobel 核的大小(既窗口阶数),必须是 1(注意这是一个3×1或1×3向量而不是一个方阵), 3, 5 或 7。
其实,这里是问题的,因为以Sobel方式求完导数后会有负值,还有会大于255的值而你建的Sobel的图像是 IPL_DEPTH_8U,也就是8位无符号数,所以Sobel建立的图像位数不够,要16位有符号的,也就是 IPL_DEPTH_16S。把建立图像这句改为
sobel=cvCreateImage(cvGetSize(frame),IPL_DEPTH_16S,1);运行,发现不报错了,但是Sobel图像显示不出来,这是什么原因呢?原来图像显示是以8位无符号显示的,现在是16位有符号,当然显示会出问题了。所以还要将Sobel转为8位无符号。OpenCv里提供了一个函数,就是cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );src:源图像;dst:目标图像;scale:转化前乘的系数;shift转化前加的系数。这样新建一个无符号图像再转换就可以实现了。
IplImage *sobel8u=cvCreateImage(cvGetSize(sobel),IPL_DEPTH_8U,1);
再在显示图像前加上cvConvertScaleAbs(sobel,sobel8u,1,0);这样就可以看到cvSobel的效果了。可以看X方向或Y方向求导是什么效果。
代码如下
//Sobel边缘检测的程序
#include "cv.h"
#include "highgui.h"
int main( int argc , char** argv)
{
//以灰度图格式加载图像或者用函数cvCvtColor(frame,gray,CV_BGR2GRAY);转为灰度
IplImage* src = cvLoadImage(argv[],CV_LOAD_IMAGE_GRAYSCALE);
//以sobel方式求完导之后会有负数,会有大于255的值,故建立图像的数据格式
//要为IPL_DEPTH_16S
IplImage* dst1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_16S,);
IplImage* dst2 = cvCreateImage(cvGetSize(src),IPL_DEPTH_16S,);
IplImage* dst18u = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,);
IplImage* dst28u = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,);
//逼近x方向上一阶微分的Sobel算子的效果
cvSobel(
src,
dst1,
,
,
);
//逼近y方向上一阶微分的Sobel算子的效果
cvSobel(
src,
dst2,
,
,
);
//图像是以8位无符号显示的,故要把输出图像的数据格式转化为IPL_DEPTH_8U
cvConvertScaleAbs(dst1,dst18u,,);
cvConvertScaleAbs(dst2,dst28u,,);
cvNamedWindow("src",);
cvNamedWindow("dst1",);
cvNamedWindow("dst2",);
cvShowImage("src",src);
cvShowImage("dst1",dst18u);
cvShowImage("dst2",dst28u);
cvWaitKey();
cvReleaseImage(&src);
cvReleaseImage(&dst1);
cvReleaseImage(&dst2);
cvReleaseImage(&dst18u);
cvReleaseImage(&dst28u);
cvDestroyWindow("src");
cvDestroyWindow("dst1");
cvDestroyWindow("dst2");
return ;
}
opencv学习笔记之cvSobel 函数解析的更多相关文章
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...
- OpenCV 学习笔记03 threshold函数
opencv-python 4.0.1 简介:该函数是对数组中的每一个元素(each array element)应用固定级别阈值(Applies a fixed-level threshold) ...
- opencv学习笔记——cv::CommandLineParser函数详解
命令行解析类CommandLineParser 该类的作用主要用于命令行的解析,也就是分解命令行的作用.以前版本没这个类时,如果要运行带参数的.exe,必须在命令行中输入文件路径以及各种参数,并且输入 ...
- opencv学习笔记——cv::mean()函数详解
opencv中封装了一个专门用于求解cv::Mat均值的函数,即cv::mean(&cv::Mat),该函数会得到Mat中各个通道的均值,若要获取指定通道的均值,做进一步解析即可. 具体使用方 ...
- 【opencv学习笔记】SetImageROI函数设置ROI区域的作用及用法
虽然先前知道ROI区域是感兴趣区域,但是真正看到调用了OpenCV的cvSetImageROI函数时,并不知道它的作用,所以还是单独写了一段代码对这个函数进行探究. OpenCVchm文档中对cv ...
- OpenCV学习笔记:resize函数改变图像的大小
OpenCV提供了resize函数来改变图像的大小,函数原型如下: , , int interpolation=INTER_LINEAR ); 参数解释: src:输入,原图像,即待改变大小的图像: ...
- OpenCV 学习笔记03 drawContours函数
opencv-python 4.0.1 轮廓的绘制或填充. cv2.drawContours(image, contours, contourIdx, color[, thickness[, li ...
- opencv学习笔记——图像缩放函数resize
opencv提供了一种图像缩放函数 功能:实现对输入图像缩放到指定大小 函数原型: void cv::resize ( InputArray src, OutputArray dst, Size ds ...
- opencv学习笔记——时间计算函数getTickCount()和getTickFrequency()
cv::getTickCount()可以用来测量一段代码的运行时间,这个函数返回从上次开机算起的时钟周期数. 由于我们需要的是某个代码段运行的毫秒数,因此还需要另一个函数cv::getTickFreq ...
随机推荐
- 关于error:Cannot assign to 'self' outside of a method in the init family
有时候我们重写父类的init方法时不注意将init后面的第一个字母写成了小写,在这个方法里面又调用父类的初始化方法(self = [super init];)时会报错,错误信息如下:error:Can ...
- 【GIS】WGS84与Web墨卡托理解(转)
坐标系 · WGS84,地理坐标系,单位度,在三维上可以很好的展示全球的数据,但在二维上显示时在高纬度地区变形较大,另由于WGS84坐标系与CGCS2000坐标系差异很小,所以WGS84坐标系在Web ...
- str.split()与re.split()的区别
str.split(): >>>'hello, world'.split() >>>['hello,','world'] >>>'hello, w ...
- 转载mysql数据库配置优化
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...
- 【代码审计】ThinkSNS_V4 任意文件下载漏洞分析
0x00 环境准备 ThinkSNS官网:http://www.thinksns.com 网站源码版本:ThinkSNS V4 更新时间:2017-09-13 程序源码下载:http://www ...
- MongoDB(三)-- 执行JS、界面工具
一.执行Js脚本 1.开启mongod服务 2.连接mongodb客户端,./mongo --host 192.168.80.128 --port 27017 3.创建数据库:use testdb1 ...
- [Command] alias - 别名
alias 命令可以让用户使用预置的字符串来执行系统命令. 命令是指用户输入指令指示电脑完成工作.命令一般在命令行输入,以回车键完成输入.命令被传递给shell.shell是类Unix操作系统提供的纯 ...
- C语言中打印返回值
demo: ----return :返回值------------------ int mosquitto_username_pw_set(struct mosquitto *mosq, const ...
- iOS10个实用小技巧(总有你不知道的和你会用到的)
本文转载至 http://www.jianshu.com/p/a3156826c27c 在开发过程中我们总会遇到各种各样的小问题,有些小问题并不是十分容易解决.在此我就总结一下,我在开发中遇到的各种小 ...
- css !important用法以及CSS样式使用优先级判断
之前一直看到很多css中都有!important这个样式,一直不知道有什么作用的,今天在网上详细了解了一下,看了别人的博客,顺便转载收藏一下 css !important用法CSS样式使用优先级判断 ...