sobel算子原理与实现
一、原理:
首先介绍背景知识:
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算子原理与实现相关推荐
- 【Pytorch神经网络理论篇】 11 卷积网络模型+Sobel算子原理
1 视觉角度理解卷积神经网络 1.1 卷积神经网络与生物视觉系统的关系 卷积神经网络的工作流程与生物大脑的处理视觉信号的流程相似,即:将图像从基础像素到局部信息再到整体信息的转化.大脑在对图像进行分级 ...
- sobel算子原理与实践
索贝尔算子(Sobeloperator)主要用于获得数字图像的一阶梯度,是一种离散性差分算子.它是prewitt算子的改进形式,改进之处在于sobel算子认为,邻域的像素对当前像素产生的 ...
- sobel算子原理_「学术论文」基于Sobel算法图像边缘检测的FPGA实现
摘要: 针对嵌入式软件无法满足数字图像实时处理速度问题,提出用硬件加速器的思想,通过FPGA实现Sobel边缘检测算法.通过乒乓操作.并行处理数据和流水线设计,大大提高算法的处理速度.采用模块的硬件设 ...
- sobel算子原理以及运用
Sobel边缘检测算法: 主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值.在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量 Sobel卷积因子为: ...
- Sobel算子原理及matlab实现代码
一.基本原理 Sobel算子使用梯度进行边缘增强,它考虑图像3×3邻域的处理. 对于图像f(x,y),取该图像的3×3的区域,如下图 x方向的偏微分定义为: y方向的偏微分定义为: 则梯度幅值为: S ...
- java求sobel算子代码_sobel算子原理及opencv源码实现
sobel算子原理及opencv源码实现 简要描述 sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测. 原理 算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去 ...
- 灰度图像--图像增强 Robert算子、Sobel算子
灰度图像--图像增强 Robert算子.Sobel算子 目录(?)[+] 开篇废话 图像梯度介绍 Robert算子 Sobel算子 代码 结果 总结 学习DIP第36天 转载请标明本文 ...
- opencv——Sobel算子与Scharr算子
目录 算子 边缘提取与梯度 边缘提取 Sobel算子 原理 API 代码展示 结果 优化代码 结果 Scharr算子 代码 结果 算子 狭义的算子实际上是指从一个函数空间到另一个函数空间(或它自身)的 ...
- 【CV】Sobel算子简介
引言 Sobel算子是一种常用的边缘检测算法,是一种离散性差分算子,用差分近似代替梯度.对x求1阶差分用来检测竖直边缘,同样的对y求1阶差分用来检测水平边缘. sobel算子对垂直和水平方向上的排列表 ...
最新文章
- EdgeGallery — AIO 离线部署 v1.5 版本
- 【转】使用genstring和NSLocalizedString实现App文本的本地化
- PowerDesigner 小工具窗
- jQuery 基础学习笔记
- Python进阶:并发编程之Asyncio
- iptables防火墙基础
- 计算机处理器(CPU)基础
- 吉大网络教育护理学专升本病例分析
- STL之字符串类模板 string(一)、C++ string类库简介
- 银行卡所属银行的查询接口--阿里提供
- Kaggle入门项目,泰坦尼克号幸存者
- DSHOT600电调协议Verilog
- android studio计时器怎么用,android - Android Studio:启动倒数计时器时应用崩溃
- matlab中读文件的行数_【Matlab】 读取文件各种方法
- 【记录】Mac 预览(Preview)丢失PDF标注恢复
- 一文彻底搞懂go mod使用
- Qt编译通过,运行时出现the process was ended forcefully的crashed问题
- unity www 加载url 读微信头像
- not Chrome binary file---没有谷歌二进制文件 Windows10出现的问题
- 如何让Excel表使用一次后即自我销毁?