使用sobel算子进行边缘检测的步骤如下:

  • 1、高斯模糊,降噪。因为sobel算子对噪声比较敏感,因此要先对原图像进行高斯模糊,降噪
  • 2、将图像转换成灰度图像
  • 3、使用sobel函数,求x和y方向上的导数。
  • 4、将x方向的导数(边缘)和y方向的导数进行叠加。

(1)高斯模糊

 //首先进行高斯模糊,降噪Mat gauImage;GaussianBlur(srcImage, gauImage, Size(3, 3), 0, 0, 4);

原图如下:

(2)转换成灰度图

 //将图片转换成灰度图Mat grayImage;cvtColor(gauImage, grayImage, COLOR_BGR2GRAY);

(3)使用sobel函数

 //进行x和y方向的soble算子Mat xGrand, yGrand;Sobel(grayImage, xGrand, CV_16S, 1, 0, 3);convertScaleAbs(xGrand, xGrand);Sobel(grayImage, yGrand, CV_16S, 0, 1, 3);convertScaleAbs(yGrand, yGrand);

下面详细讲述一下x和y方向导数怎么求解。

对于一元连续函数的导数,我们直接通过公式求导就可以;对于多元连续函数的导数,我们需要求各个方向的偏导。但是对于存储在计算机中的图像来说,计算机只能够处理离散的像素值,不能够使用公式求解导数,因此只能够使用导数的定义来求解x和y方向的导数。比如求解x方向的导数:dx = I(i + 1) - I(i);求解y方向的导数:dx = I(j + 1) - I(j),某点的导数 = 该点x(y)方向的下一个像素值 - 该点的像素值,就可以得到该点x或者y方向的导数。

值得注意的是,因为sobel函数在求x或者y方向的导数时,使用的核是不一样的,得到的导数可能小于0,或者大于255,因此为了保护细节,最好选用16位(CV_16S)的输出图像的深度,并且调用convertScaleAbs(输出图像为8位),将所得结果尽可能的保护下来。

(4)将x和y方向的导数进行叠加

方法一:使用线性混合的方法进行叠加

 //进行线性混合叠加Mat dst;addWeighted(xGrand, 0.5, yGrand, 0.5, 0, dst, -1);

调用函数所需要的瞬间很短,得到的效果也很一般。最终的图片如下:

方法二:使用近似的方法,将x和y方向的导数进行相加

 Mat dst = Mat :: zeros( xGrand.size(), yGrand.type());//将x和y的梯度直接相加int colsImage = srcImage.cols;int rowsImage = srcImage.rows;for (int row = 0; row < rowsImage; row++) {for (int col = 0; col < colsImage; col++) {int xValue = xGrand.at<uchar>(row, col);int yValue = yGrand.at<uchar>(row, col);dst.at<uchar>(row, col) = saturate_cast<uchar>(xValue + yValue);}}

这个方法消耗的时间较长,消耗了0.1s左右的时间,但是运行结果显而易见,获得了更多的细节和边缘。

方法三:根据勾股定理求出近似梯度

根据向量的加法,如果要求得图像整体的梯度,就要求x和y向量加法的模,也就是x和y构成的直角三角形的斜边。

具体代码如下:

 //使用勾股定理获得更多的细节int colsImage = srcImage.cols;int rowsImage = srcImage.rows;for (int row = 0; row < rowsImage; row++) {for (int col = 0; col < colsImage; col++) {uchar xValue = xGrand.at<uchar>(row, col);uchar yValue = yGrand.at<uchar>(row, col);dst.at<uchar>(row, col) = saturate_cast<uchar>(sqrt(xValue * xValue + yValue * yValue));}}

这个方法消耗的时间比方法二消耗的时间略长一些,但是效果和方法二相差不多。因此,从时间方面考虑,完全可以使用第二种方法代替第三种方法。

最终所有代码如下:

#include <opencv2/opencv.hpp>
#include <math.h>
#include <iostream>using namespace cv;int main(int argc, char ** argv) {Mat srcImage = imread("1.jpg");if (srcImage.empty()) {printf("could not load this picture\n");return -1;}imshow("原图像", srcImage);//首先进行高斯模糊,降噪Mat gauImage;GaussianBlur(srcImage, gauImage, Size(3, 3), 0, 0, 4);//将图片转换成灰度图Mat grayImage;cvtColor(gauImage, grayImage, COLOR_BGR2GRAY);imshow("灰度图", grayImage);//进行x和y方向的soble算子Mat xGrand, yGrand;Sobel(grayImage, xGrand, CV_16S, 1, 0, 3);convertScaleAbs(xGrand, xGrand);Sobel(grayImage, yGrand, CV_16S, 0, 1, 3);convertScaleAbs(yGrand, yGrand);//进行叠加float t1 = getTickCount();Mat dst = Mat :: zeros( xGrand.size(), yGrand.type());//使用线性混合的方法//addWeighted(xGrand, 0.5, yGrand, 0.5, 0, dst, -1);将x和y的梯度直接相加//int colsImage = srcImage.cols;//int rowsImage = srcImage.rows;//for (int row = 0; row < rowsImage; row++) {//    for (int col = 0; col < colsImage; col++) {//     uchar xValue = xGrand.at<uchar>(row, col);//     uchar yValue = yGrand.at<uchar>(row, col);//     dst.at<uchar>(row, col) = saturate_cast<uchar>(xValue + yValue);//    }//}//使用勾股定理获得更多的细节int colsImage = srcImage.cols;int rowsImage = srcImage.rows;for (int row = 0; row < rowsImage; row++) {for (int col = 0; col < colsImage; col++) {uchar xValue = xGrand.at<uchar>(row, col);uchar yValue = yGrand.at<uchar>(row, col);dst.at<uchar>(row, col) = saturate_cast<uchar>(sqrt(xValue * xValue + yValue * yValue));}}float timeConsume = (getTickCount() - t1) / getTickFrequency();printf("线性混合叠加消耗的时间是:%f\n", timeConsume);imshow("最终图像", dst);imwrite("finalImage.jpg", dst);waitKey(0);return 0;
}

sobel算子进行边缘检测相关推荐

  1. Sobel算子的边缘检测实现

    1. Sobel算子的边缘检测实现 1.1. 边缘检测概念 所谓边缘是指其周围像素灰度急剧变化的那些象素的集合,它是图像最基本的特征.边缘存在于目标.背景和区域之间,所以,它是图像分割所依赖的最重要的 ...

  2. matlab实现sobel边缘检测图像,基于Sobel算子图像边缘检测的MATLAB实现

    <基于Sobel算子图像边缘检测的MATLAB实现>由会员分享,可在线阅读,更多相关<基于Sobel算子图像边缘检测的MATLAB实现(3页珍藏版)>请在人人文库网上搜索. 1 ...

  3. 在CIELab颜色空间下使用八方向Sobel算子实现边缘检测

    参考河北师范大学硕士学位论文--基于八方向Sobel算子的边缘检测算法研究. 由于自己实现滤波器运算,计算速度很慢,以后有能力再进行改进. 算子定义如下: 算法思路: 1.将RGB图像转化为CIELa ...

  4. Opencv python基础入门(4)---sobel算子及边缘检测

    本文主要介绍sobel算子及边缘检测: 代码如下: #sobel,ddepth如果设置为-1的话,水平处理只能取出左边界,右边界为负值丢失了,所以需要先用64F扩展然后用convertScaleAbs ...

  5. 屏幕后期处理之:Sobel算子实现边缘检测

    版权声明 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商 ...

  6. sobel算子_OpenCV图像处理专栏十八 | 手动构造Sobel算子完成边缘检测

    1. 前言 众所周知,在传统的图像边缘检测算法中,最常用的一种算法是利用Sobel算子完成的.Sobel算子一共有 个,一个是检测水平边缘的算子,另一个是检测垂直边缘的算子. 2. Sobel算子优缺 ...

  7. sobel算子实现边缘检测及其c++实现及与matlab效果对比

    这里增加了对边缘像素的补齐.sobel梯度分割抗噪性好,但是无法做到自动阈值,是其一大遗憾,matlab却解决的很好. //默认对8位位图进行处理 void Sobel(unsigned char * ...

  8. sobel算子_边缘检测算法4.-教你动手实现kirsch和robinson算子

    还有很多 边缘检测算子,在OpenCV中没有实现代码. 所以,我们得掌握看懂算法,然后扩展 算法得能力. 比如,我已知的一些 边缘检测核心: Kirsch 8方向算子 Robinson 8方向算子 这 ...

  9. CUDA精进之路(四):图像处理——Sobel算子边缘检测

    引言 关于图像边缘检测,记得刚开始接触图像处理时,第一个自己实现的程序是通过笔记本摄像头采集图像,利用OpenCV自带的算法库进行Canny算子边缘检测,那时候当看到程序运行后,视频窗口实时显示经Ca ...

  10. 图像处理学习2,边缘检测1(sobel算子,kirsch算子)

    图像边缘的种类 图像中的边缘是像素灰度值发生加速变化而不连续的结果,边缘检测是常见的图像基元检测的基础,也是所有基于边界的图像分割方法的第一步. 图片来源:章毓晋.计算机视觉教程[M].北京:人民邮电 ...

最新文章

  1. js实现数据结构及算法之图和图算法(Graphs)
  2. Python介绍以及Python 优缺点
  3. Linux下中文man帮助安装。
  4. Python一切皆对象
  5. 玻璃体混浊研究中需要解决的问题(持续更新中)
  6. SAP Spartacus Page Layout学习笔记
  7. [react] React的触摸事件有哪几种?
  8. 随想录(程序员和收入)
  9. “javax.servlet.http.HttpServlet“ 错误
  10. CentOS配置ssh无密码登录
  11. 2017.9.21 所驼门王的宝藏 思考记录
  12. C++如何生成随机数
  13. java任务监控进度控制
  14. ThinkPad机型BIOS开启VT虚拟化技术
  15. iphone 计算机找不到了,电脑找不到苹果手机热点
  16. QTP10破解方法及mgn-mqt82.exe下载
  17. am335x USB 驱动框架记录
  18. 交换机VLAN划分的三种方法
  19. 计算机网络要点归纳(一文带你快速掌握网络知识)
  20. autobahn-python的使用——sendMessage()和断线自动重连

热门文章

  1. 华硕B85M-D台式机主板音响没反应,更新驱动还是找不到realtek高清晰音频管理器原因及解决方案
  2. Android 腾讯信鸽集成
  3. 扫二维码登录的实现原理
  4. 《web课程设计》期末网页制作 基于HTML+CSS+JavaScript制作公司官网页面精美
  5. 征途私服mysql启动不了_征途win版服务端1.1蛋白质修改版
  6. 鸿蒙系统摩尔纹怎么去,PS摩尔纹如何消除?摩尔纹消除方法图文分享
  7. Mikrotik ROS软路由设置上网方式(一)
  8. 神舟IV号开发板STM32F107VCT6资料包(已购买)\STM32神舟IV号视频教程\第9集 串口实验 电脑超级终端连接串口1
  9. DSP SRIO接口认识
  10. 基于Java毕业设计/疫情展示平台源码+系统+mysql+lw文档+部署软件