【译】Sobel 算子文档
来源:互联网 发布:淘宝cad画图接活群 编辑:程序博客网 时间:2024/06/05 20:54
参考网址:https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html
一.目标
在这篇指南中你将学会如何:
- 使用OpenCV 中的Sobel 算子计算图像中的导数。
- 使用OpenCV 中的Scharr 算子计算一个3*3大小的核的一个更精确的导数。
二.理论
说明:下面的解释说明来自由Bradski 和Kaehler写的《Learning OpenCV》
为什么计算图像中的衍生物的微积分十分重要?让我们想象如果我们想要检测到图像中出现的边缘,如下图:
你会发现在边缘处,像素点亮度出现显著的变化。使用导数能够很好的展现变化。梯度上的变化表现出图像中的较大的变化。
为了图示的更加清晰,假设我们有一个一维的图像,下面图表中亮度值的“跳跃”表现出边缘部分:
如果我们求第一次导数(事实上,图中表现为最大点),边缘部分的“跳跃”更能够表现出来。
所以,根据上述的解释说明,我们可以推导出一个在图像中检测边缘的方法,即通过确定一个梯度值大于领域中其他像素点(推广思路可改用阈值)的点的位置并表现在图像中。
更多的细节解释,可以参考Bradski 和Kaehler 的《Learning OpenCV》
Sobel 算子
- Sobel 算子是一个具体的差异化的算子。它用于计算图像中亮度梯度的估计值。
- Sobel 算子是将差异化和高斯滤波合并起来
处理
假设待处理的图像为I:
- 我们计算两个导数:
a.水平变化:通过计算I 与核Gx 的卷积,其中Gx 是一个具有奇数边长的核。比如对于一个3*3的核,Gx 可以像下面这样计算:Gx =∣∣∣∣−1−2−1000+1+2+1∣∣∣∣ * I
b.竖直变化:通过计算I 与核Gx 的卷积,其中Gx 是一个具有奇数边长的核。比如对于一个3*3的核,Gx 可以像下面这样计算:Gy =∣∣∣∣−10+1−20+2−10+1∣∣∣∣ * I - 在图像中的每个像素点上,我们通过使用下述公式计算结果来获取该像素点的梯度的估计值:
G =(Gx)2+(Gy)2−−−−−−−−−−−√
尽管有时会使用下面的公式:
G = |
注意:当核的尺寸为3*3时,上面提到的Sobel 算子将会产生很明显的误差(毕竟,Sobel 算子是一种对导数的估计)。OpenCV 强调可以用Scharr 函数来处理使用3*3 的核产生的误差。这种方法和标准的Sobel 算子要快,同时更加准确,它是使用如下的形式的核:
你可以在OpenCV 参考中找到更多有关Scharr 的相关信息。并且,在下面相同的代码中,你讲发现不仅有Sobel 算子还有注释过的Scharr 算子。取消注释将展现这个方法的工作原理。
代码:
- 这段代码用来干什么?
使用Sobel 算子并且生成一张图作为输出,输出的图像将在深色的背景上用亮色表示找到的边缘。 - 下面展示指导代码:
#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <stdlib.h>#include <stdio.h>using namespace cv;/** @function main */int main( int argc, char** argv ){ Mat src, src_gray; Mat grad; char* window_name = "Sobel Demo - Simple Edge Detector"; int scale = 1; int delta = 0; int ddepth = CV_16S; int c; /// Load an image src = imread( argv[1] ); if( !src.data ) { return -1; } GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); /// Convert it to gray cvtColor( src, src_gray, CV_BGR2GRAY ); /// Create window namedWindow( window_name, CV_WINDOW_AUTOSIZE ); /// Generate grad_x and grad_y Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; /// Gradient X //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); convertScaleAbs( grad_x, abs_grad_x ); /// Gradient Y //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); convertScaleAbs( grad_y, abs_grad_y ); /// Total Gradient (approximate) addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad ); imshow( window_name, grad ); waitKey(0); return 0; }
注释:
- 首先我们声明我们将要使用的变量:
Mat src, src_gray;Mat grad;char* window_name = "Sobel Demo - Simple Edge Detector";int scale = 1;int delta = 0;int ddepth = CV_16S;
- 然后加载我们的源图像:
src = imread( argv[1] );if( !src.data ){ return -1; }
- 第一步,我们使用高斯滤波过滤噪点(核为3*3):
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
- 将过滤后的图像转换成灰度图:
cvtColor( src, src_gray, CV_BGR2GRAY );
- 下一步,我们在x 和y 方向上计算导数,我们按照下面的方式使用Sobel 算子:
Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y;/// Gradient XSobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );/// Gradient YSobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
函数中的参数:
- src_gray :在我们的例子中是输入的图像,这里图像格式为CV_8U
- grad_x | grad_y:输出的图像
- ddepth :输出的图像的深度,我们将格式设置为CV_16S防止溢出。
- x_order :x轴方向上的导数序列
- y_order :y轴方向上的导数序列
- scale ,delta 和BORDER_DEFAULT:使用默认值
注意到我们使用
- 将部分得到的结果重新转换为CV_8U
convertScaleAbs( grad_x, abs_grad_x );convertScaleAbs( grad_y, abs_grad_y );
- 最后,我们通过两个方向的梯度估算每个像素点的梯度值(需要指出的是,这并不是最好的计算结果,但是的确符合我们的要求)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
- 最后我们展示出处理后的结果:
imshow( window_name, grad );
结果:
下面是我们通过基本的检测得到的结果图:
- 【译】Sobel 算子文档
- Sobel算子
- Sobel算子
- sobel算子
- Sobel算子
- Sobel算子
- sobel算子
- Sobel算子
- sobel算子
- Sobel算子
- sobel算子
- Sobel算子及cvSobel
- Sobel算子及cvSobel
- Sobel算子及cvSobel
- 【转】Sobel 算子
- Sobel梯度算子
- Sobel算子及cvSobel
- sobel算子,matlab实现
- C语言 volatile 关键字
- Java三大器之拦截器(Interceptor)的实现原理及代码示例
- Java拦截器(interceptor)原理
- 微信小程序从子页面退回父页面时的数据传递 wx.navigateBack()
- 分治法之归并排序
- 【译】Sobel 算子文档
- Bootstrap
- 第一(2)部份 ic615 ubuntu mmsim bashrc设定
- DUT数模组第一周周记
- 自动化运维工具SaltStack详细部署及用SaltStack实现自动部署lamp架构
- 棋盘覆盖
- 一个ajax上传文件的简单案例
- java反转字符串
- Codeforces Round #397 B