博客
关于我
Sobel算子边缘检测原理及实现
阅读量:798 次
发布时间:2023-04-15

本文共 3934 字,大约阅读时间需要 13 分钟。

Sobel算子:边缘检测的精确选择

1. 算子概述

Sobel算子是一种广泛应用于图像处理领域的边缘检测算子。它通过计算图像在水平和垂直方向上的梯度,能够有效地提取图像的边缘信息。与Prewitt算子和Roberts算子相比,Sobel算子的特点是其对像素位置的加权处理,能够在保持精度的同时,提高边缘检测的准确性。

2. 优点分析

Sobel算子的主要优势体现在以下几个方面:

  • 边缘定位准确:Sobel算子能够较为精确地定位图像的边缘,尤其在处理灰度渐变和噪声较多的图像时表现突出。
  • 计算简便:相比于其他边缘检测算子,Sobel算子的计算过程较为简单,且可以分别计算水平和垂直方向的边缘。
  • 可分离性:Sobel算子的边缘检测过程具有很强的可分离性,可以通过先平滑后差分的方式实现,从而提高了计算效率。

3. 工作原理

3.1 平滑算子

Sobel算子的平滑过程采用了非归一化的高斯平滑原理。具体来说,平滑算子的系数来源于二项式展开式的系数。对于窗口大小为3的情况,平滑算子的系数为:[ [1, 1] ]而对于更大的窗口大小,平滑算子的系数可以通过将二项式系数进行扩展得到。例如,窗口大小为5时,平滑算子的系数为:[ [1, 3, 3, 1] ]

3.2 差分算子

差分算子是通过对平滑算子进行后向差分得到的。例如,窗口大小为5时,差分算子的系数为:[ [1, 2, 0, -2, -1] ]差分算子的作用是从平滑算子中提取出边缘的变化信息。

3.3 边缘检测流程

Sobel算子的边缘检测流程可以分为两个主要步骤:

  • 水平方向平滑:使用平滑算子对图像进行水平方向的平滑处理。
  • 垂直方向差分:对平滑后的图像进行垂直方向的差分操作,从而得到垂直方向的边缘信息。
  • 水平方向差分:对平滑后的图像进行水平方向的差分操作,从而得到水平方向的边缘信息。
  • 通过上述流程,Sobel算子能够分别计算出图像的水平和垂直边缘信息。

    4. 代码实现

    4.1 平滑算子和差分算子的构建

    int factorial(int n) {    int fac = 1;    if (n == 0) return fac;    for (int i = 1; i <= n; ++i) {        fac *= i;    }    return fac;}cv::Mat getSobelSmooth(int wsize) {    int n = wsize - 1;    cv::Mat smoothKernel = cv::Mat::zeros(cv::Size(wsize, 1), CV_32FC1);    for (int k = 0; k <= n; ++k) {        float *ptr = smoothKernel.ptr
    (0); ptr[k] = factorial(n) / (factorial(k) * factorial(n - k)); } return smoothKernel;}cv::Mat getSobeldiff(int wsize) { cv::Mat diffKernel = cv::Mat::zeros(cv::Size(wsize, 1), CV_32FC1); cv::Mat smoothKernel = getSobelSmooth(wsize - 1); for (int k = 0; k < wsize; ++k) { if (k == 0) { diffKernel.at
    (0, k) = 1; } else if (k == wsize - 1) { diffKernel.at
    (0, k) = -1; } else { diffKernel.at
    (0, k) = smoothKernel.at
    (0, k) - smoothKernel.at
    (0, k - 1); } } return diffKernel;}

    4.2 可分离卷积实现

    void sepConv2D_Y_X(cv::Mat &src, cv::Mat &dst, cv::Mat &kernel_Y, cv::Mat &kernel_X, int ddepth, cv::Point anchor = cv::Point(-1, -1), int delta = 0, int borderType = cv::BORDER_DEFAULT) {    cv::Mat temp = conv2D(src, temp, kernel_Y, ddepth, anchor, delta, borderType);    conv2D(temp, dst, kernel_X, ddepth, anchor, delta, borderType);}void sepConv2D_X_Y(cv::Mat &src, cv::Mat &dst, cv::Mat &kernel_X, cv::Mat &kernel_Y, int ddepth, cv::Point anchor = cv::Point(-1, -1), int delta = 0, int borderType = cv::BORDER_DEFAULT) {    cv::Mat temp = conv2D(src, temp, kernel_X, ddepth, anchor, delta, borderType);    conv2D(temp, dst, kernel_Y, ddepth, anchor, delta, borderType);}

    4.3 边缘检测主函数

    void Sobel(cv::Mat &src, cv::Mat &dst_X, cv::Mat &dst_Y, cv::Mat &dst, int wsize, int ddepth) {    cv::Mat smoothKernel = getSobelSmooth(wsize);    cv::Mat diffKernel = getSobeldiff(wsize);        sepConv2D_Y_X(src, dst_X, smoothKernel, diffKernel, ddepth);    sepConv2D_X_Y(src, dst_Y, smoothKernel, diffKernel, ddepth);        cv::abs(dst_X, dst_X);    cv::abs(dst_Y, dst_Y);    cv::convertScaleAbs(dst, dst);}

    4.4 使用示例

    int main() {    cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig1025(a)(building_original).tif");    if (src.empty()) {        return -1;    }    if (src.channels() > 1) {        cv::cvtColor(src, src, CV_RGB2GRAY);    }        int wsize = 3;    cv::Mat SobelDiff, SobelSmooth;    Sobel(src, dst_Y, dst_X, dst, wsize, CV_32FC1);        cv::namedWindow("src", CV_WINDOW_NORMAL);    imshow("src", src);        cv::namedWindow("水平边缘", CV_WINDOW_NORMAL);    imshow("水平边缘", dst_Y);        cv::namedWindow("垂直边缘", CV_WINDOW_NORMAL);    imshow("垂直边缘", dst_X);        cv::namedWindow("边缘强度", CV_WINDOW_NORMAL);    imshow("边缘强度", dst);        cv::namedWindow("边缘强度取反-铅笔素描", CV_WINDOW_NORMAL);    imshow("边缘强度取反-铅笔素描", 255 - dst);        cv::waitKey(0);    return 0;}

    5. 效果展示

    5.1 原图和边缘检测结果

    通过对比原图和边缘检测结果,可以清晰地看到Sobel算子捕捉到的边缘信息。图像的水平和垂直方向的边缘都被准确地提取出来,显示出图像的轮廓和细节。

    5.2 铅笔素描效果

    将边缘检测结果取反后,可以得到一种类似铅笔素描的效果。这种效果特别适用于手绘风格的图像处理,能够突出图像的轮廓和主要细节。

    6. 参考文献

    • 《OpenCV算法精解》--- 张平

    转载地址:http://ggrfk.baihongyu.com/

    你可能感兴趣的文章
    MySQL DBA 数据库优化策略
    查看>>
    multi_index_container
    查看>>
    MySQL DBA 进阶知识详解
    查看>>
    Mura CMS processAsyncObject SQL注入漏洞复现(CVE-2024-32640)
    查看>>
    Mysql DBA 高级运维学习之路-DQL语句之select知识讲解
    查看>>
    mysql deadlock found when trying to get lock暴力解决
    查看>>
    MuseTalk如何生成高质量视频(使用技巧)
    查看>>
    mutiplemap 总结
    查看>>
    MySQL DELETE 表别名问题
    查看>>
    MySQL Error Handling in Stored Procedures---转载
    查看>>
    MVC 区域功能
    查看>>
    MySQL FEDERATED 提示
    查看>>
    mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
    查看>>
    Mysql group by
    查看>>
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>