Opencv图像处理---Sobel 导数

本文详细介绍了如何使用Sobel算子进行图像边缘检测,包括理论基础、具体实现及OpenCV代码示例。Sobel算子通过计算图像中像素强度的梯度,能够有效地检测出图像中的边缘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理论

  •  最重要的卷积之一是计算图像中的导数(或它们的近似值)。
  • 我们想要检测图像中存在的边缘。 例如:
  • 为了更加图形化,让我们假设我们有一维图像。 边缘由下图中的“跳跃”强度显示:
  • 如果我们采用一阶导数(实际上,这里显示为最大值),则可以更容易地看到边缘“跳跃”.
  • 因此,根据上面的解释,我们可以推断出可以通过定位梯度高于其邻居的像素位置(或概括,高于阈值)来执行检测图像中的边缘的方法。

Sobel运算符

  • Sobel算子是一个离散微分算子。 它计算图像强度函数的梯度的近似值。
  • Sobel算子结合了高斯平滑和差分。

公式

  • 我们计算两个导数:
  1. 水平变化:这是通过将I与奇数大小的内核Gx进行卷积来计算的。 例如,对于内核大小为3,Gx将计算为:
  2. 垂直变化:这是通过将I与具有奇数大小的内核Gy进行卷积来计算的。 例如,对于内核大小为3,Gy将被计算为:
  • 在图像的每个点,我们通过组合上面的两个结果来计算该点的梯度的近似值:
  • 虽然有时会使用以下更简单的公式:
  • 当内核的大小为3时,上面显示的Sobel内核可能会产生明显的不准确性(毕竟,Sobel只是导数的近似值)。 OpenCV通过使用cv :: Scharr函数解决了大小为3的内核的这种不准确性。 这比标准的Sobel功能更快但更准确。 它实现了以下内核:

代码


#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
int main( int, char** argv )
{
  Mat src, src_gray;
  Mat grad;
  const char* window_name = "Sobel Demo - Simple Edge Detector";
  int scale = 1;
  int delta = 0;
  int ddepth = CV_16S;
  src = imread( argv[1] );
  if( src.empty() )
    { return -1; }
  GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
  cvtColor( src, src_gray, COLOR_RGB2GRAY );
  namedWindow( window_name, WINDOW_AUTOSIZE );
  Mat grad_x, grad_y;
  Mat abs_grad_x, abs_grad_y;
  //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 );
  //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 );
  addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
  imshow( window_name, grad );
  waitKey(0);
  return 0;
}

解释

       该函数采用以下参数:

      (1)src_gray:输入图像。 这是CV_8U 

      (2)grad_x /  grad_y :输出图像。

      (3)ddepth:输出图像的深度。 我们将其设置为CV_16S以避免溢出。

        (4)   x_order:x方向导数的阶数。

        (5)   y_order:y方向导数的阶数。

        (6)   scale,delta和BORDER_DEFAULT:我们使用默认值。

请注意,要计算x方向的渐变,我们使用:xorder = 1和yorder = 0。 我们类似地为y方向做。

  • 我们声明我们将要使用的变量:
  • 我们加载源图像src:
  • 我们将cv :: GaussianBlur应用于我们的图像以减少噪音(内核大小= 3)
  • 现在我们将滤波后的图像转换为灰度图像:
  • 我们计算x和y方向的导数。 为此,我们使用函数cv :: Sobel,如下所示:
  • 我们将部分结果转换回CV_8U:
  • 最后,我们尝试通过添加两个方向渐变来近似渐变
  • 最后,我们展示了我们的结果:

效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值