• OpenCV(二十五):边缘检测(一)


    目录

    1.边缘检测原理

    2.Sobel算子边缘检测

    3.Scharr算子边缘检测

    4.两种算子的生成getDerivKernels()


    1.边缘检测原理

           其原理是基于图像中灰度值的变化来捕捉图像中的边界和轮廓。梯度则表示了图像中像素强度变化的强弱和方向。 所以沿梯度方向找到有最大梯度值的像素,就可以获得图像中的边缘信息。

    2.Sobel算子边缘检测

    原理:

            Sobel算子是一种常用的边缘检测算子,它可以通过计算图像的梯度来捕捉图像中的边缘信息。它分别计算图像在x和y方向上的导数,然后根据导数的值确定边缘的位置和强度。

           具体来说,Sobel算子可以通过一个3x3的卷积核在图像上进行卷积操作。有两个Sobel卷积核,一个用于水平方向(x方向)的边缘检测,另一个用于垂直方向(y方向)的边缘检测。这两个卷积核分别如下:

    对于输入图像中的每个像素,Sobel算子将使用这些卷积核计算其水平和垂直方向上的梯度。然后,通过对梯度的幅度进行合并,可以计算出每个像素的总梯度大小。总梯度大小表示像素点周围灰度值的变化强度,较大的变化强度通常对应于图像中的边缘。

    函数:

    cv::Sobel()函数将Sobel算子应用于输入图像进行卷积操作。

    函数的原型如下:

    CV_EXPORTS_W 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 );

    下面是参数的详细解释:

    • src:输入图像,可以是单通道灰度图像或多通道图像。

    • dst:输出图像,与输入图像具有相同的尺寸和类型。

    • ddepth:输出图像的数据类型,它可以是负值(如-1)表示与输入图像保持一致,也可以是CV_8U、CV_16U、CV_32F等值,表示输出图像的深度。

    • dx和dy:分别表示在x和y方向上的导数阶数。可选值为0、1和2。

    • ksize:Sobel内核的大小,必须为1、3、5或7。值越大,滤波器的响应越平缓。

    • scale:可选的缩放因子,用于调整输出图像的值域范围。默认为1。

    • delta:可选的指定delta值,用于调整输出图像的亮度。默认为0。

    • borderType:可选的边界扩充方法,用于处理邻域超出图像边界的情况。默认为cv::BORDER_DEFAULT。

           示例代码:

    1. void Sobel_f(Mat image){
    2. Mat gray;
    3. cvtColor(image,gray,COLOR_BGR2GRAY);
    4. Mat resultX,resultY,resultXY;
    5. //X方向一阶边缘
    6. Sobel(gray,resultX,CV_16S,1,0,1);
    7. convertScaleAbs(resultX,resultX);
    8. //Y方向一阶边缘
    9. Sobel(gray,resultY,CV_16S,0,1,3);
    10. convertScaleAbs(resultY,resultY);
    11. //整幅图像的一阶边缘
    12. resultXY=resultX+resultY;
    13. //显示图像
    14. imwrite("/sdcard/DCIM/resultX.png",resultX);
    15. imwrite("/sdcard/DCIM/resultY.png",resultY);
    16. imwrite("/sdcard/DCIM/resultXY.png",resultXY);
    17. }

             (X方向)                                 ( Y方向)                               ( XY方向)

    3.Scharr算子边缘检测

    原理:

            Scharr算子是一种边缘检测算子,它是Sobel算子的改进版本。Scharr算子采用了更加精确的权重分配,可以提供更好的边缘检测性能。

            Scharr算子也是通过卷积操作来计算图像的梯度,类似于Sobel算子。它包含两个卷积核,一个用于水平方向(x方向)的边缘检测,另一个用于垂直方向(y方向)的边缘检测。

            Scharr算子的差异在于卷积核中的权重分配相对于Sobel算子更加平衡,以提高对边缘信号的敏感度。这种平衡权重的分配可以产生更加准确的梯度估计。

            Scharr算子使用相同的原理来计算像素点周围的梯度大小和方向。通过在x和y方向上对梯度进行计算,并根据梯度的幅度和方向确定边缘的位置和强度。

    函数:

    cv::Scharr()函数是OpenCV中的一个函数,用于计算图像的Scharr导数。它类似于Sobel算子,但是使用了更准确的权重分配。

    函数原型:

    CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth,

    int dx, int dy, double scale = 1, double delta = 0,

    int borderType = BORDER_DEFAULT );

    下面是参数的详细解释:

    • src:输入图像,可以是单通道灰度图像或多通道图像。

    • dst:输出图像,与输入图像具有相同的尺寸和类型。

    • ddepth:输出图像的数据类型,可以是负值(如-1),表示与输入图像保持一致,也可以是CV_8U、CV_16U、CV_32F等值,表示输出图像的深度。

    • dx和dy:分别表示在x和y方向上的导数阶数。可选值为0、1和2。

    • scale:可选的缩放因子,用于调整输出图像的值域范围。默认为1。

    • delta:可选的指定delta值,用于调整输出图像的亮度。默认为0。

    • borderType:可选的边界扩充方法,用于处理邻域超出图像边界的情况。默认为cv::BORDER_DEFAULT。

    示例代码:

    1. void Scharr_f(Mat img) {
    2. Mat image;
    3. cvtColor(img,image,COLOR_BGR2GRAY);
    4. cv::Mat grad_x, grad_y; // 存放Scharr滤波器的梯度
    5. cv::Mat abs_grad_x, abs_grad_y; // 存放梯度的绝对值
    6. // 计算X方向的Scharr滤波器
    7. cv::Scharr(image, grad_x, CV_16S, 1, 0);
    8. cv::convertScaleAbs(grad_x, abs_grad_x);
    9. // 计算Y方向的Scharr滤波器
    10. cv::Scharr(image, grad_y, CV_16S, 0, 1);
    11. cv::convertScaleAbs(grad_y, abs_grad_y);
    12. // 合并X和Y方向的梯度
    13. cv::Mat grad;
    14. cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
    15. // 显示结果
    16. imwrite("/sdcard/DCIM/grad.png",grad);
    17. }

    结果: (grad)

    4.两种算子的生成getDerivKernels()

    getDerivKernels()函数是OpenCV中用于生成一维卷积核的函数,可用于计算图像的一阶导数。

    函数的原型如下:

    void cv::getDerivKernels ( OutputArray kx,

    OutputArray ky,

    int    dx,

    int    dy,

    int   ksize,

    bool   normalize =false,

    int   ktype = CV_32F

    )

    • kx:行滤波器系数的输出矩阵,尺寸为ksize*1
    • ky:列滤波器系数的输出矩阵,尺寸为ksize*1。
    • dx:X方向导数的阶次。
    • dy:Y方向导数的阶次
    • ksize:滤波器的大小,可以选择的参数为FILTER SCHARR,1.35或7。
    • normalize: 是否对滤波器系数进行归一化的标志,默认值为false,表示不进行系数归一化。
    • ktype:滤波器系数类型,可以选择CV 32F或CV 64F,默认参数为CV 32F。

    示例代码:

    以下是一个使用使用getDerivKernels()函数来生成Sobel和Scharr算子卷积核的示例:

    1. //生成边缘检测器
    2. void f(){
    3. cv::Mat sobel_xl, sobel_yl; // 存放分离的Sobel算子
    4. cv::Mat scharr_x, scharr_y; // 存放分离的Scharr算子
    5. cv::Mat sobelXl, scharrX; // 存放最终算子
    6. // 一阶X方向Sobel算子
    7. cv::getDerivKernels(sobel_xl, sobel_yl, 1, 0, 3);
    8. sobel_xl = sobel_xl.reshape(1, 1); // 转换为单行矩阵
    9. sobelXl = sobel_yl * sobel_xl; // 计算滤波器
    10. // X方向Scharr算子
    11. cv::getDerivKernels(scharr_x, scharr_y, 1, 0, cv::FILTER_SCHARR);
    12. scharr_x = scharr_x.reshape(1, 1); // 转换为单行矩阵
    13. scharrX = scharr_y*scharr_x; // 计算滤波器
    14. ostringstream ss;
    15. // 打印生成的卷积核
    16. ss<< "Sobel X方向卷积核:" << sobelXl << endl;
    17. ss << "Scharr X方向卷积核:" << scharrX <<endl;
    18. LOGD("%s",ss.str().c_str());
    19. }

    我们使用getDerivKernels()函数生成了X方向Sobel算子和X方向Scharr算子的卷积核。然后,我们将其转换为单行矩阵,并通过乘法运算计算得到滤波器。

  • 相关阅读:
    欢迎来到对抗路——机器学习-多元线性回归模型(详解)
    24、订单和购物车-srv服务
    如何最大程度使用AWS?
    python 中用opencv开发虚拟键盘------可以只选择一个单词不会出现一下选择多个
    如何使用GPT?初学者的指南
    linux定时任务(crontab)
    YOLOv5剪枝 | 模型剪枝理论篇 | 1/2
    Nomad 系列-快速上手
    【第10天】SQL进阶-表的创建、修改与删除(SQL 小虚竹)
    蓝牙SDK状态机与车载音频HSM状态机比较
  • 原文地址:https://blog.csdn.net/weixin_63357306/article/details/132725000