一、原理:

首先介绍背景知识:

1)边缘:灰度或结构等信息的突变处,边缘是一个区域的结束,也是另一个区域的开始,利用该特征可以分割图像。

2)边缘点:图像中具有坐标[x,y],且处在强度显著变化的位置上的点。

3)边缘段:对应于边缘点坐标[x,y]及其方位 ,边缘的方位可能是梯度角。

索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量。

为了节省时间,我就直接截图了,原理都这样。

套用公式就如下,

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

如果求整体x和y方向的So被浏览梯度,只需要将Gx和Gy想家即可。

二、C++代码实现

我查过很多资料,都没有发现这个Sobel在C++上到底 是怎么实现的,以为就是没有代码,思索良久,在同学的提示下,终于写出来了,不过可能有不少瑕疵。

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{Mat m_img = imread("D://vvoo/lena.jpg");Mat src(m_img.rows, m_img.cols, CV_8UC1, Scalar(0));cvtColor(m_img, src, CV_RGB2GRAY);Mat dstImage(src.rows, src.cols, CV_8UC1, Scalar(0));for (int i = 1; i < src.rows - 1; i++){for (int j = 1; j < src.cols - 1; j++){dstImage.data[i*dstImage.step + j] = sqrt((src.data[(i - 1)*src.step + j + 1]+ 2 * src.data[i*src.step + j + 1]+ src.data[(i + 1)*src.step + j + 1]- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]- src.data[(i + 1)*src.step + j - 1])*(src.data[(i - 1)*src.step + j + 1]+ 2 * src.data[i*src.step + j + 1] + src.data[(i + 1)*src.step + j + 1]- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]- src.data[(i + 1)*src.step + j - 1]) + (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]- 2 * src.data[(i + 1)*src.step + j]- src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]- 2 * src.data[(i + 1)*src.step + j]- src.data[(i + 1)*src.step + j + 1]));}}Mat grad_y(src.rows, src.cols, CV_8UC1, Scalar(0));{for (int i = 1; i < src.rows - 1; i++){for (int j = 1; j < src.cols - 1; j++){grad_y.data[i*grad_y.step + j] = abs((src.data[(i - 1)*src.step + j + 1]+ 2 * src.data[i*src.step + j + 1]+ src.data[(i + 1)*src.step + j + 1]- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]- src.data[(i + 1)*src.step + j - 1]));}}}Mat grad_x(src.rows, src.cols, CV_8UC1, Scalar(0));{for (int i = 1; i < src.rows - 1; i++){for (int j = 1; j < src.cols - 1; j++){grad_x.data[i*grad_x.step + j] = sqrt((src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]- 2 * src.data[(i + 1)*src.step + j]- src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]- 2 * src.data[(i + 1)*src.step + j]- src.data[(i + 1)*src.step + j + 1]));}}}imshow("原图", src);imshow("gradient", dstImage);imshow("Vertical gradient", grad_y);imshow("Horizontal gradient", grad_x);waitKey(0);return 0;
}

截图:

为了作对比,再讲一下opencv的Sobel函数实现:

<pre name="code" class="cpp">C++: void Sobel (
InputArray src,//输入图OutputArray dst,//输出图int ddepth,//输出图像的深度int dx,int dy,int ksize=3,double scale=1,double delta=0,int borderType=BORDER_DEFAULT );
  • 第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
  • 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
  • 第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
    • 若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
    • 若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
    • 若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
    • 若src.depth() = CV_64F, 取ddepth = -1/CV_64F
  • 第四个参数,int类型dx,x 方向上的差分阶数。
  • 第五个参数,int类型dy,y方向上的差分阶数。
  • 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
  • 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
  • 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
  • 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。

有点啰嗦了

#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{Mat dstIamge, grad_x, grad_y, abs_grad_x, abs_grad_y;Mat srcIamge = imread("D:\\vvoo\\lena.jpg");imshow("原始图", srcIamge);cvtColor(srcIamge, srcIamge, COLOR_RGB2GRAY);//求 X方向梯度Sobel(srcIamge, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(grad_x, abs_grad_x);//使用线性变换转换输入数组元素成8位无符号整型imshow("X方向Sobel", abs_grad_x);//求Y方向梯度Sobel(srcIamge, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);convertScaleAbs(grad_y, abs_grad_y);imshow("Y方向Sobel", abs_grad_y);//合并梯度(近似)addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0,dstIamge);imshow("整体方向Sobel", dstIamge);waitKey(0);return 0;
}

结果为:

参考资料:

1.OpenCV入门教程

2.Sobel边缘检测算法

sobel算子原理与实现相关推荐

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

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

  2. sobel算子原理与实践

           索贝尔算子(Sobeloperator)主要用于获得数字图像的一阶梯度,是一种离散性差分算子.它是prewitt算子的改进形式,改进之处在于sobel算子认为,邻域的像素对当前像素产生的 ...

  3. sobel算子原理_「学术论文」基于Sobel算法图像边缘检测的FPGA实现

    摘要: 针对嵌入式软件无法满足数字图像实时处理速度问题,提出用硬件加速器的思想,通过FPGA实现Sobel边缘检测算法.通过乒乓操作.并行处理数据和流水线设计,大大提高算法的处理速度.采用模块的硬件设 ...

  4. sobel算子原理以及运用

    Sobel边缘检测算法: 主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值.在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量 Sobel卷积因子为: ...

  5. Sobel算子原理及matlab实现代码

    一.基本原理 Sobel算子使用梯度进行边缘增强,它考虑图像3×3邻域的处理. 对于图像f(x,y),取该图像的3×3的区域,如下图 x方向的偏微分定义为: y方向的偏微分定义为: 则梯度幅值为: S ...

  6. java求sobel算子代码_sobel算子原理及opencv源码实现

    sobel算子原理及opencv源码实现 简要描述 sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测. 原理 算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去 ...

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

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

  8. opencv——Sobel算子与Scharr算子

    目录 算子 边缘提取与梯度 边缘提取 Sobel算子 原理 API 代码展示 结果 优化代码 结果 Scharr算子 代码 结果 算子 狭义的算子实际上是指从一个函数空间到另一个函数空间(或它自身)的 ...

  9. 【CV】Sobel算子简介

    引言 Sobel算子是一种常用的边缘检测算法,是一种离散性差分算子,用差分近似代替梯度.对x求1阶差分用来检测竖直边缘,同样的对y求1阶差分用来检测水平边缘. sobel算子对垂直和水平方向上的排列表 ...

最新文章

  1. EdgeGallery — AIO 离线部署 v1.5 版本
  2. 【转】使用genstring和NSLocalizedString实现App文本的本地化
  3. PowerDesigner 小工具窗
  4. jQuery 基础学习笔记
  5. Python进阶:并发编程之Asyncio
  6. iptables防火墙基础
  7. 计算机处理器(CPU)基础
  8. 吉大网络教育护理学专升本病例分析
  9. STL之字符串类模板 string(一)、C++ string类库简介
  10. 银行卡所属银行的查询接口--阿里提供
  11. Kaggle入门项目,泰坦尼克号幸存者
  12. DSHOT600电调协议Verilog
  13. android studio计时器怎么用,android - Android Studio:启动倒数计时器时应用崩溃
  14. matlab中读文件的行数_【Matlab】 读取文件各种方法
  15. 【记录】Mac 预览(Preview)丢失PDF标注恢复
  16. 一文彻底搞懂go mod使用
  17. Qt编译通过,运行时出现the process was ended forcefully的crashed问题
  18. unity www 加载url 读微信头像
  19. not Chrome binary file---没有谷歌二进制文件 Windows10出现的问题
  20. 如何让Excel表使用一次后即自我销毁?

热门文章

  1. RPC是什么?RPC与REST、Socket的区别?php中流行的rpc框架有哪些?
  2. 最新综述:自动驾驶的协同感知技术
  3. mysql 简单练习题
  4. Abstract Expressionist
  5. 高速场景下自动驾驶车辆定位方法综述
  6. 毕设系列 - java web 项目获取方式说明
  7. 【瑞萨RA系列FSP库开发】RASC+Keil的环境搭建
  8. 穿越雷区(Python)
  9. 电脑桌面上的东西从计算机进去,如果有东西卡在电脑屏幕上怎么解决
  10. STM8S103F---Nokia5110液晶显示