边缘检测滤波器

Scharr算子只有两种滤波器,Sobel算子却有不同尺寸、不同阶次

在实际使用过程中,即使了解Sobel算子的原理,推导出边缘提取需要的滤波器也是非常复杂而繁琐的任务

并且,有时我们并不希望提取图像的边缘,而是希望得到能够提取图像边缘的滤波器,通过对滤波器的修改提升边缘检测的效果

OpenCV4提供了getDerivKernel()函数,通过函数可以得到不同尺寸、不同阶次的Sobel算子和Scharr算子的滤波器

getDerivKernel()函数原型:

void getDerivKernel(OutputArray kx,
                    OutputArray ky,
                    int dx,
                    int dy,
                    bool normlize = flase,
                    int ktype = CV_32F
                    )
  • kx:行滤波器系数的输出矩阵,尺寸为 ksize x 1
  • ky:列滤波器系数的输出矩阵,尺寸为 ksize x 1
  • dx:X方向导数的阶次
  • dy:Y方向导数的阶次
  • ksize:滤波器的大小,可以选择参数为FILTER_SCHARR、1、3、5或7
  • normalize:是否对滤波器系数进行归一化的标志,默认值为false,表示不进行系数归一化
  • ktype:滤波器系数类型,可以选择CV_32F或CV_64F,默认为CV_32F

该函数可用于生成Sobel算子和Scharr算子,实际上,Sobel()函数和Scharr()函数内部就是通过调用该函数得到边缘检测算子

该函数的前两个参数分别为行滤波器系数的输出矩阵、列滤波器系数的输出矩阵,需要将两者通过卷积分离性原理得到最终的算子

最终的边缘检测算子对图像的边缘提取效果由第三、四个参数决定

当dx=1,dy=0时,就是检测X方向的一阶梯度边缘

该函数的第五个参数是滤波器的尺寸,取值为1、3、5、7,生成的是Sobel算子,取值为FILTER_SCHARR,生成的是Scharr算子

当第五个参数为1时,第三、四个参数最大值小于3

当第五个参数为FILTER_SCHARR时,第三、四个参数取值为1或0,并且两者和为1

示例:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat sobel_x1,sobel_y1,sobel_x2,sobel_y2,sobel_x3,sobel_y3; //存放分离的Sobel算子
    Mat scharr_x,scharr_y;  //存放分离的Scharr算子
    Mat sobelX1,sobelX2,sobelX3,scharrX;//存放最终算子
    //一阶X方向Sobel算子
    getDerivKernels(sobel_x1,sobel_y1,1,0,3);
    sobel_x1 = sobel_x1.reshape(CV_8U,1);
    sobelX1 = sobel_y1*sobel_x1; //计算滤波器
    //二阶X方向Sobel算子
    getDerivKernels(sobel_x2,sobel_y2,2,0,5);
    sobel_x2 = sobel_x2.reshape(CV_8U,1);
    sobelX2 = sobel_y2*sobel_x2; //计算滤波器
    //三阶X方向Sobel算子
    getDerivKernels(sobel_x3,sobel_y3,3,0,7);
    sobel_x3 = sobel_x3.reshape(CV_8U,1);
    sobelX3 = sobel_y3*sobel_x3; //计算滤波器
    //X方向Scharr算子
    getDerivKernels(scharr_x,scharr_y,1,0,FILTER_SCHARR);
    scharr_x = scharr_x.reshape(CV_8U,1);
    scharrX = scharr_y*scharr_x; //计算滤波器
    //输出结果
    cout << "X方向一阶Sobel算子:" << endl << sobelX1 << endl;
    cout << "X方向二阶Sobel算子:" << endl << sobelX2 << endl;
    cout << "X方向三阶Sobel算子:" << endl << sobelX3 << endl;
    cout << "X方向Scharr算子:" << endl << scharrX << endl;
    waitKey(0);
    return 0;
}

注:提取X方向和Y方向边缘的滤波器系数是互为转置的关系

results matching ""

    No results matching ""