sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。

原理

算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点

Gx方向的相关模板:

Gy方向的相关模板:

看了网上的很多资料,都把卷积和相关的概念给弄糊了,书上给的Sobel的模板不是卷积模板,而是相关模板,因为卷积的话要先将模板旋转180度以后再与图像做相关的操作。

所以Sobel的卷积模板是:

Gx=

1

0

-1

2

0

-2

1

0

-1

具体计算如下:

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

通常,为了提高效率使用不开平方的近似值:

然后可用以下公式计算梯度方向:

opencv还提供了一个scharr函数,比Sobel算子更为精准,也是3x3的模板。

下面放上源代码:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
bool sobelEdge(Mat&  srcImage, Mat& resultImageX, Mat& resultImageY, uchar threshold)
{CV_Assert(srcImage.channels() == 1);// 初始化水平核因子Mat sobelx = (Mat_<double>(3, 3) << -1, 0,1, -2, 0, 2, -1, 0, 1);// 初始化垂直核因子Mat sobely = (Mat_<double>(3, 3) << -1, -2, -1,0, 0, 0, 1, 2, 1);resultImageX = Mat::zeros(srcImage.rows - 2,srcImage.cols - 2, srcImage.type());resultImageY = Mat::zeros(srcImage.rows - 2,srcImage.cols - 2, srcImage.type());double edgeX = 0;double edgeY = 0;double graMagX = 0;// 垂直方向上的梯度模长double graMagY = 0;// 水平方向上的梯度模长for (int k = 1; k < srcImage.rows - 1; ++k) {for (int n = 1; n < srcImage.cols - 1; ++n) {edgeX = 0;edgeY = 0;// 遍历计算水平与垂直梯度for (int i = -1; i <= 1; ++i) {for (int j = -1; j <= 1; ++j){edgeX += srcImage.at<uchar>(k + i, n + j) *sobelx.at<double>(1 + i, 1 + j);edgeY += srcImage.at<uchar>(k + i, n + j) *sobely.at<double>(1 + i, 1 + j);}}// 计算垂直方向上的梯度模长graMagX = sqrt(pow(edgeX, 2));// 计算水平方向上的梯度模长graMagY = sqrt(pow(edgeY, 2));// 二值化resultImageX.at<uchar>(k - 1, n - 1) =((graMagX > threshold) ? 255 : 0);// 二值化resultImageY.at<uchar>(k - 1, n - 1) =((graMagY > threshold) ? 255 : 0);}}return true;
}int OTSU(Mat &srcImage)
{int nRows = srcImage.rows;int nCols = srcImage.cols;int threshold = 0;double max = 0.0;double AvePix[256];int nSumPix[256];double nProDis[256];double nSumProDis[256];for (int i = 0; i < 256; i++){AvePix[i] = 0.0;nSumPix[i] = 0;nProDis[i] = 0.0;nSumProDis[i] = 0.0;}for (int i = 0; i < nRows; i++){for (int j = 0; j < nCols; j++){nSumPix[(int)srcImage.at<uchar>(i, j)]++;}}for (int i = 0; i < 256; i++){nProDis[i] = (double)nSumPix[i] / (nRows*nCols);}AvePix[0] = 0;nSumProDis[0] = nProDis[0];for (int i = 1; i < 256; i++){nSumProDis[i] = nSumProDis[i - 1] + nProDis[i];AvePix[i] = AvePix[i - 1] + i*nProDis[i];}double mean = AvePix[255];for (int k = 1; k < 256; k++){double PA = nSumProDis[k];double PB = 1 - nSumProDis[k];double value = 0.0;if (fabs(PA) > 0.001 && fabs(PB) > 0.001){double MA = AvePix[k];//前一半的平均double MB = (mean - PA*MA) / PB;//后一半的平均value = value = (double)(PA * PB * pow((MA - MB), 2));//类间方差  //或者这样value = (double)(PA * PB * pow((MA-MB),2));//类间方差//pow(PA,1)* pow((MA - mean),2) + pow(PB,1)* pow((MB - mean),2)if (value > max){max = value;threshold = k;}}}return threshold;
}
int main()
{Mat srcImage = cv::imread("building.jpg");if (!srcImage.data)return -1;Mat srcGray;cvtColor(srcImage, srcGray, CV_BGR2GRAY);imshow("srcGray", srcGray);//调用二值化函数得到最佳阈值int otsuThreshold = OTSU(srcGray);cout << otsuThreshold << endl;Mat XresultImage;Mat YresultImage;sobelEdge(srcGray, XresultImage, YresultImage, otsuThreshold);Mat resultImage;//水平垂直边缘叠加addWeighted(XresultImage, 0.5, YresultImage, 0.5, 0.0, resultImage);imshow("resx", XresultImage);imshow("resy", YresultImage);imshow("res", resultImage);waitKey(0);return 0;
}

原图灰度图:

垂直边缘图像:

水平边缘图像:

水平垂直合一起:

从上图可以看出 边缘图还有很多不是边缘点的也被取出来了,下一步就是做非极大值抑制

Sobel算子的理解相关推荐

  1. 梯度,sobel算子的理解

    本文转于:https://blog.csdn.net/u014020344/article/details/50196635 若用侵权 请联系删除 ? 在这一讲中我们来学习一下opencv中最基本的边 ...

  2. 学习sobel算子对图像求导自我理解

    sobel算子,其实也就是近似把对函数进行偏导数计算,转化为适合图像计算的矩阵, 把整个图像当做为二元函数,然后分别对二元(x和y)求偏导数. 偏导数其实高数考试里面的形象解释不多,个人就当导数理解, ...

  3. Sobel算子及cvSobel

    转自:http://blog.sina.com.cn/s/blog_4bdbec750100mufo.html 由于项目里要用到边缘检测,所以今天研究了一下最简单的梯度的方法. 首先,我们来开一下计算 ...

  4. 【OpenCV 4开发详解】Sobel算子

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  5. 灰度图像--图像增强 Robert算子、Sobel算子

    灰度图像--图像增强 Robert算子.Sobel算子         目录(?)[+] 开篇废话 图像梯度介绍 Robert算子 Sobel算子 代码 结果 总结 学习DIP第36天 转载请标明本文 ...

  6. OpenCV-Python教程(6)(7)(8): Sobel算子 Laplacian算子 Canny边缘检测

    OpenCV-Python教程(6.Sobel算子) 本篇文章介绍如何用OpenCV-Python来使用Sobel算子. 提示: 转载请详细注明原作者及出处,谢谢! 本文介绍使用OpenCV-Pyth ...

  7. python高斯滤波和降噪_python添加高斯噪声和椒盐噪声,实现中值滤波和均值滤波,实现Roberts算子和Sobel算子...

    写在前面 HIT大三上学期视听觉信号处理课程中视觉部分的实验一,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验一. 由于时间紧张,代码没有进行任何优化, ...

  8. 【Pytorch神经网络理论篇】 11 卷积网络模型+Sobel算子原理

    1 视觉角度理解卷积神经网络 1.1 卷积神经网络与生物视觉系统的关系 卷积神经网络的工作流程与生物大脑的处理视觉信号的流程相似,即:将图像从基础像素到局部信息再到整体信息的转化.大脑在对图像进行分级 ...

  9. OpenCV中的Sobel算子

    OpenCV中的Sobel算子 刚开始第一次接触这个东西的时候也是感觉一脸懵逼,这是什么鬼.完全看不懂.今天再次接触到,感觉理解的透彻了一点. 首先来看一下Sobel算子是个什么东西: -1 0 1 ...

最新文章

  1. mysql 查看运行级别_Linux的运行级别和chkconfig用法
  2. C#学员信息管理试题
  3. 看新排美国话剧《哗变》
  4. TPL 和传统 .NET Framework 异步编程
  5. Mybatis一二级缓存的理解
  6. ubuntu sudo apt-get update 失败 解决方法
  7. Mybatis_day2_Mybatis的CRUD操作
  8. 【CVPR 2019】Strong-Weak Distribution Alignment for Adaptive Object Detection
  9. 关于CVE-2020-14882,你需要知道的都在这里
  10. 基于Python-Pygame:200行代码实现完整的俄罗斯方块
  11. 北京互联网人寒冬求职记
  12. susmote个人网站博客论坛(TexTec | 关注互联网技术,传播极客精神)
  13. 如何使用Spring Bean Configuration File调用构造方法并给参数赋值
  14. AES加密算法|密码学|网络空间安全
  15. 文件同步工具BT Sync介绍和使用说明
  16. T检验和F检验\自由度
  17. git diff的简单使用
  18. 多媒体集中控制系统 (4600版)
  19. 【问题解决】win服务器磁盘初始化
  20. 使用十六进制设置颜色

热门文章

  1. python真假判断
  2. HBase如何快速查询
  3. 天气预报实时显示系统设计
  4. 深度资讯|美团王兴带头承诺廉洁自律,互联网公司也需要“人民的名义”
  5. 全新二开PHP自适应极简多引擎搜索单页网站源码
  6. 自动生成实体类、Mapper、Mapper.xml文件
  7. 5G的关键技术与所面临的挑战
  8. 远期、期货和互换(三)
  9. TOEFL口语——TASK4的答题方法(学术场景Academic Lecture)
  10. gitflow概念及上传本地文件到github