OpenCV之Sobel算子(C++实现)

53 篇文章 15 订阅

sobel算子的基本概念

Sobel算子是一个主要用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,都会得倒对应的梯度矢量或其法向量。

sobel算子的计算过程

假设图像为I,分别在x和y方向上计算梯度,其实就是用卷积核在两个方向上与图像进行卷积,以大小为3的卷积核为例:

然后在图像上的每一点,结合以上两个结果求出近似梯度:

另外也可以用下面更简单的公式替代:

函数原型:

void Sobel(InputArray src, OutputArray dst, int ddpth, int dx, int dy, int ksize=3, double scale=1, double delta=0,int borderType=BORDER_DEFAULT);

参数详解:

  • 第一个参数:输入图像,Mat类型即可;
  • 第二个参数:输出,需要和源图像有一样的大小和类型;
  • 第三个参数:int类型的ddepth,输入图像的深度,支持ruxiasrc.depth()和ddepth的组合。
  1. 若sec.depth()=CV_8U,取ddepth=-1/CV_16S/CV_32F/CV_64F;
  2. 若sec.depth()=CV_16U/CV_16S,取ddepth=-1/CV_16S/CV_32F/CV_64F;
  3. 若sec.depth()=CV_32F,取ddepth=-1/CV_16S/CV_32F/CV_64F;
  4. 若sec.depth()=CV_64F,取ddepth=-1/CV_16S/CV_64F;
  • 第四个参数:int类型的dx,x方向上的差分阶数。
  • 第五个参数:it类型dy,y方向上的差分阶数。
  • 第六个参数:int类型的ksize,默认值是3,卷积核的大小,只能取1,3,5,7.
  • 第七个参数:double类型的scale,计算导数时的可选尺度因子,默认值是1,表示默认情况下是没有应用缩放的。
  • 第八个参数:double类型的delta,表示在结果存入目标图之前可选的delta值,默认值是0.
  • 第九个参数:int类型的borderType,边界模式,默认值是BORDER_DEFALULT。

一般情况下都是用ksize*ksize的内核来计算导数的,但是一种特殊情况是,当ksize=1时,往往会使用3*1或1*3的内核,且这种情况下,并没有进行高斯平滑操作。

代码示例:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
//    初始化x和y方向的梯度
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;

    Mat srcImage;
    srcImage = imread("/Users/dwz/Desktop/cpp/1.jpg");
    cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
//    计算x方向的梯度
    Sobel(srcImage, grad_x,CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
    convertScaleAbs(grad_x, abs_grad_x);

//    计算y方向的梯度
    Sobel(srcImage, grad_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
    convertScaleAbs(grad_y, abs_grad_y);

//    合并梯度
    Mat dstImage;
    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dstImage);
    imwrite("sobel.jpg", dstImage);
}

输入:

输出:

 

  • 8
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Tenengrad函数是一种边缘检测算法,可以使用Sobel算子实现。下面是使用OpenCV C++实现Tenengrad函数的代码: ```c++ #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char** argv) { // 读取图像 Mat src = imread("lena.jpg", IMREAD_GRAYSCALE); if (src.empty()) { cout << "Could not open or find the image!" << endl; return -1; } // 计算Sobel算子 Mat grad_x, grad_y; Sobel(src, grad_x, CV_16S, 1, 0, 3); // x方向梯度 Sobel(src, grad_y, CV_16S, 0, 1, 3); // y方向梯度 // 计算Tenengrad函数 Mat tenengrad; pow(grad_x, 2, grad_x); // x方向梯度平方 pow(grad_y, 2, grad_y); // y方向梯度平方 add(grad_x, grad_y, tenengrad); // 平方和 sqrt(tenengrad, tenengrad); // 开方 // 显示图像 namedWindow("Source", WINDOW_NORMAL); imshow("Source", src); namedWindow("Tenengrad", WINDOW_NORMAL); imshow("Tenengrad", tenengrad); waitKey(0); return 0; } ``` 在这个程序中,我们首先读取了一张灰度图像,然后使用Sobel算子计算了x方向和y方向的梯度。接下来,我们将这两个梯度平方并相加得到了Tenengrad函数,并对其进行了开方操作。最后,我们显示了原始图像和Tenengrad函数图像。 需要注意的是,这个程序中使用了OpenCVSobel函数来计算梯度,它的第三个参数是输出图像的数据类型。在这里,我们使用了CV_16S作为输出图像的数据类型,因为梯度值可能为负数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值