Sobel边缘检测算子OpenCV实现

基本概念

1.算子

算子也就是滤波器,或者又称作卷积核,通常是一个3x3或者8x8的矩阵,在数字图像处理中有广泛的应用,将滤波器用来对二维图像中的每个像素做点积操作,及对应的像素点相乘再求和,可以达到边缘提取,图像分割等各种效果

2.图像的梯度

在二维图像中,边缘就是图像的像素值发生突变的那些点的集合,边缘的像素点与周围领域的像素点在亮度上存在较大差异,在高等数学中梯度代表了函数在某个点上最大的方向导数,也就是在沿着该方向函数的变化最快,那么在图像中,二维函数的梯度就可以理解为沿着x轴或者y轴的偏导数,由于二维图像是一个离散函数,所以我们这里需要采用偏导数的差分形式

在这里插入图片描述

因此,Sobel算子是一个一阶微分算子,图像的梯度可以通过相邻像素值的差分得到,所以也就不难理解Sobel算子的滤波器结构

在这里插入图片描述

上图是x方向上的,y方向上的很类似
在这里插入图片描述

后续通过求该梯度的模,开平方根,或者通过直接相加得到一个梯度的近似值

[公式]

下面我们可以自己动手通过C++来实现一个Sobel算子的边缘检测

代码如下

这里的gx与gy分别代表x方向和y方向上图像梯度的计算结果,最后二者叠加,得到整幅图像的结果

cv::Mat Sobel(cv::Mat img) {
    int width = img.cols;
    int height = img.rows;
    
    //  存储x方向的sobel算子结果
    cv::Mat gx = cv::Mat::zeros(height, width, CV_8UC1);
    //  存储y方向的sobel算子结果
    cv::Mat gy = cv::Mat::zeros(height, width, CV_8UC1);
    for(int i = 1 ; i < height - 1; i ++) {
        for(int j = 1; j < width - 1; j ++) {
            //  calculate sobel for x
            gx.at<uchar>(i,j) = img.at<uchar>(i-1,j-1) * (-1) +
                                img.at<uchar>(i-1,j) * 0 +
                                img.at<uchar>(i-1,j+1) * 1 +
                                img.at<uchar>(i,j-1) * (-2) +
                                img.at<uchar>(i,j) * 0 +
                                img.at<uchar>(i,j+1) * 2 +
                                img.at<uchar>(i+1,j-1) * (-1) +
                                img.at<uchar>(i+1, j) * 0 +
                                img.at<uchar>(i+1, j+1) * 1;
            
            //  calculate sobel for y
            gy.at<uchar>(i,j) = img.at<uchar>(i-1,j-1) * (-1) +
                                img.at<uchar>(i-1,j) * 0 +
                                img.at<uchar>(i-1,j+1) * 1 +
                                img.at<uchar>(i,j-1) * (-2) +
                                img.at<uchar>(i,j) * 0 +
                                img.at<uchar>(i,j+1) * 2 +
                                img.at<uchar>(i+1,j-1) * (-1) +
                                img.at<uchar>(i+1, j) * 0 +
                                img.at<uchar>(i+1, j+1) * 1;
        }
    }
    
    cv::Mat result = cv::Mat::zeros(height, width, CV_8UC1);
    //  两个方向上的梯度计算结果叠加
    addWeighted(gx, 1, gy, 1, 0, result);
    return result;
}

sobel算子的应用结果为(下面贴一张自己的照片):
在这里插入图片描述

由于部分噪声可能对Sobel算子的结果有影响,所以对原图先做了一次高斯模糊,然后转换成灰度图,再应用了Sobel算子。

Sobel对部分图像较弱的边缘可能检测效果教差,OpenCV自带的API cv::Sobel函数中,还可以传入Scharr算子,Scharr是对Sobel算子差异性的增强,其滤波器结构如下
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值