目录

  • 算子
    • 边缘提取与梯度
    • 边缘提取
  • Sobel算子
    • 原理
    • API
    • 代码展示
      • 结果
    • 优化代码
      • 结果
  • Scharr算子
    • 代码
    • 结果

算子

  • 狭义的算子实际上是指从一个函数空间到另一个函数空间(或它自身)的映射。

  • 广义的算子的定义只要把上面的空间推广到一般空间,可以是向量空间,赋范向量空间,内积空间,或更进一步,Banach空间,Hilbert空间都可以。算子还可分为有界的与无界的,线性的与非线性的等等类别。

边缘提取与梯度


如上图,在画圈处有明显的像素值变化,这就是图像中的边缘


上图,是图像像素的变化图
圆圈处就是和源图像对应的点。可以看出,这里的变化率是最大的
变化率也称梯度
谈及变化率,我们就要想到导数
如下图

边缘提取

边缘是什么 – 像素值发生跃迁的地方
是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。

如何捕捉/提取边缘 – 对图像求它的一阶导数

  delta =  f(x) – f(x-1)

delta越大,说明像素在X方向变化越大,边缘信号越强

在opencv中,我们只需要使用Sobel算子就可以提取边缘,不用再使用求导操作

Sobel算子

原理

Sobel算子又叫索贝尔算子,是计算机视觉领域的一种重要处理方法。

主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。

Sobel算子是把图像中每个像素的上下左右四领域的灰度值加权差,在边缘处达到极值从而检测边缘。

Sobel算子所采用的算法是先进行加权平均,然后进行微分运算,算子的计算方法如下:

对于一个二元函数f(x,y)来说,x有三个取值,y有三个取值,那我们就可以构造一个3×3的矩阵,矩阵的中心点为(x,y),向上向左为减一,向右向下为加一。我们用矩阵来表示一下上面的式子:
由此,我们设计两个核,一个是x方向上的,一个是y方向上的,设计的两个核是3×3的矩阵,分别是:


所以,如果对于一个图像I,我们能通过这两个核分别计算该图像X方向和Y方向的梯度:

我们也能根据两个方向的梯度计算总的梯度:

第二个式子是第一个式子的近似计算,这是由于CPU乘除的开销远大于加减
所以会这么用

Sobel算子对噪声比较敏感,在使用前建议高斯模糊去噪再使用Sobel算子进行边缘提取

API

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
);
  • (1)InputArray类型的src ,输入图像。

  • (2)OutputArray类型的dst ,输出图像,图像的大小、通道数和输入图像相同。

  • (3)int类型的ddepth,输出图像深度,请参阅@ref filter_depth“组合”;如果是8位输入图像,则会导致导数截断。
    计算sobel的时候有负,一边黑一边白就变成500多了。如果我们的depth是-1,输入图像是CV_8U的灰度图像,输出也是CV_8U。那么超过255的就会被截断,与实际数值不吻合。所以输出图像的位数要比输入高,比如输入CV_8U,输出就要用CV_16S

  • (4)int类型的dx,导数x的阶数。

  • (5)int类型的dy,导数y的阶数。

  • (6)int类型的ksize,扩展Sobel内核的大小;它必须是1、3、5或7。

  • (7)double类型的scale,计算派生值的可选比例因子;默认情况下,不应用缩放(有关详细信息,请参见cv::getDerivKernels。

  • (8)double类型的delta,在将筛选的像素存储到dst中之前添加到这些像素的可选值。说的有点专业了其实就是给所选的像素值添加一个值delta。

  • (9)int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT。

我们还用了一个很简单的函数,用于计算绝对值

void convertScaleAbs( InputArray src, OutputArray dst, double alpha= 1,                       double belt= 0,
);

我们这个函数只需要设置前两个参数,这个函数可以计算图像src的像素绝对值,输出到图像dst。

代码展示

#include<iostream>
#include<opencv2/opencv.hpp>using namespace std;
using namespace cv;int main()
{Mat src, gx, gy, dst;src = imread("C:/Users/86176/Pictures/pics/lena(1).tiff");if (!src.data){cout << "could not load image !";return -1;}imshow("【输入图像】", src);Mat tmp,gray;GaussianBlur(src, tmp, Size(3,3), 0, 0);cvtColor(tmp, gray, CV_BGR2GRAY);Sobel(gray, gx, CV_16S, 1, 0,3);Sobel(gray, gy, CV_16S, 0, 1,3);convertScaleAbs(gx, gx);convertScaleAbs(gy, gy);//若不用绝对值,那么产出的图像就会缺失很多细节addWeighted(gx, 0.5, gy, 0.5, 0, dst);imshow("【输出图像】", dst);waitKey(0);return 0;
}

结果

优化代码

我们在上述代码使用的是加权相加,并非是绝对值相加
我们现在来优化代码

#include<iostream>
#include<opencv2/opencv.hpp>using namespace std;
using namespace cv;int main()
{Mat src, gx, gy, dst;src = imread("C:/Users/86176/Pictures/pics/lena(1).tiff");if (!src.data){cout << "could not load image !";return -1;}imshow("【输入图像】", src);Mat tmp,gray;GaussianBlur(src, tmp, Size(3,3), 0, 0);cvtColor(tmp, gray, CV_BGR2GRAY);Sobel(gray, gx, CV_16S, 1, 0);Sobel(gray, gy, CV_16S, 0, 1);convertScaleAbs(gx, gx);convertScaleAbs(gy, gy);//若不用绝对值,那么产出的图像就会缺失很多细节//addWeighted(gx, 0.5, gy, 0.5, 0, dst);dst = Mat(gx.size(), gx.type());//printf("type : %d\n", gx.type()); //这里能看到gx的type是0,即CV_8U,所以下面指针类型都是ucharint width = dst.cols;int height = dst.rows;for (int row = 0; row < height; row++){for (int col = 0; col < width; col++){   //每个取号绝对值的像素值都相加int xg = gx.at<uchar>(row, col);int yg = gy.at<uchar>(row, col);int xy = xg + yg;dst.at<uchar>(row, col) = saturate_cast<uchar>(xy);//指定像素值在0~255,防止被截断}}imshow("【输出图像】", dst);waitKey(0);return 0;
}

结果


可以看到,细节比上面加权相加多了很多

加权相加的结果如下

如果我们直接使用加权相加,丢失了一些细节,那么我们后续的处理可能会差的更远。所谓差之毫厘,谬以千里。
所以我们需要了解图像处理的本质。

Scharr算子

我们之前聊到梯度,即周围像素差值的变化率,要了解这个概念,我们就需要求导。

导数是对于连续函数来说的,图像差值不是连续的函数,所以这种方式,其实只是一个近似解。

这种近似解,对于上面的来说又不是特别的精确,所以,在opencv中,采用更加精确的Scharr算子:

代码

#include<iostream>
#include<opencv2/opencv.hpp>using namespace std;
using namespace cv;int main()
{Mat src, gx, gy, dst;src = imread("C:/Users/86176/Pictures/pics/lena(1).tiff");if (!src.data){cout << "could not load image !";return -1;}imshow("【输入图像】", src);Mat tmp,gray;GaussianBlur(src, tmp, Size(3,3), 0, 0);cvtColor(tmp, gray, CV_BGR2GRAY);Scharr(gray, gx, CV_16S, 1, 0);Scharr(gray, gy, CV_16S, 0, 1);//Sobel(gray, gx, CV_16S, 1, 0);//Sobel(gray, gy, CV_16S, 0, 1);convertScaleAbs(gx, gx);convertScaleAbs(gy, gy);//若不用绝对值,那么产出的图像就会缺失很多细节//addWeighted(gx, 0.5, gy, 0.5, 0, dst);dst = Mat(gx.size(), gx.type());//printf("type : %d\n", gx.type()); //这里能看到gx的type是0,即CV_8U,所以下面指针类型都是ucharint width = dst.cols;int height = dst.rows;for (int row = 0; row < height; row++){for (int col = 0; col < width; col++){ //每个取号绝对值的像素值都相加int xg = gx.at<uchar>(row, col);int yg = gy.at<uchar>(row, col);int xy = xg + yg;dst.at<uchar>(row, col) = saturate_cast<uchar>(xy);//指定像素值在0~255,防止被截断}}imshow("【输出图像】", dst);waitKey(0);return 0;
}

结果


相较于Sobel,Scharr对图像的边缘有了更大的加强
即,Scharr对抗噪声的干扰强于Sobel

opencv——Sobel算子与Scharr算子相关推荐

  1. sobel算子,scharr算子,Laplacian算子

    1.sobel算子: sobel算子可以计算图像梯度,计算图像梯度的作用是提取边界,一般我们用一个3x3的卷积核去指示sobel算子是如何运算的: 图中左边就是计算水平梯度时的卷积核,简单来说就是右边 ...

  2. 一文解决Opencv四大经典算子——sobel算子、scharr算子、laplacian算子、canny算子

    Opencv四大算子 Sobel算子 Scharr算子 laplacian算子 canny算子 总结 边缘是像素值发生跃迁的位置,是图像的显著特征之一,在图像特征提取,对象检测,模式识别等方面都有重要 ...

  3. 【opencv学习笔记】018之Sobel算子与Scharr算子

    目录 一.前言 二.算子 1.咋理解算子 2.算子定义 三.Sobel算子 1.讲解 2.API 3.代码展示 4.执行结果 四.Scharr算子 1.讲解 2.API 3.代码展示 4.执行结果 一 ...

  4. 【OpenCV 4开发详解】Scharr算子

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  5. python实现sobel_OpenCV-Python系列之Sobel和Scharr算子

    我们再上个教程中留了一个小彩蛋--形态学的梯度问题,通常情况下,它被用于提取图像的轮廓,今天我们来了解图像边缘的另一种方法,它将比形态学梯度更有效,适用范围也更广. Sobel算子 前面的例子,已经接 ...

  6. 空间滤波 - 锐化处理 - 一阶差分算法(Sobel、Scharr算子)

    目录 1. 介绍 2. Sobel 算子 3. Scharr 算子 1. 介绍 空间滤波的另一种用途是图像的锐化,锐化的作用是突出灰度中的过渡区域 图像的模糊在空间域当中可以通过平滑(平均)邻域中的像 ...

  7. 图像梯度——Sobel算子和Laplacian算子

    一.Sobel算子 1.定义 Sobel算子是一种离散的微分算子,结合了高斯平滑和微分求导运算,利用局部拆分寻找边缘,计算所得的是一个梯度的近似值. Sobel算子=|左-右|/|下-上| Schar ...

  8. OpenCV Sobel检测算子和Scharr检测算子

    Sobel边缘检测算法比较简单,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,Sobel算子是高斯平滑与微分操作的结合体 ...

  9. opencv学习笔记16:梯度运算之scharr算子及其函数使用

    前文介绍了sobel算子 opencv学习笔记14:sobel算子及其函数使用 scharr算子理论 系数和sobel不一样,其他一样. scharr函数使用 dst=cv2.Scharr(src,d ...

最新文章

  1. 初识ES-es与mysql的概念对比
  2. 二分图之匈牙利算法模版
  3. Ps 初学者教程,如何使用图层混合模式合成图像?
  4. PPTP拨号后无法打开网页处理
  5. linux SCALA 安装及环境配置
  6. 计算机装系统找不到硬盘,安装系统找不到硬盘怎么办
  7. 网易考拉布局和css样式
  8. QQ被盗后被敲诈500元怎么办
  9. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.25日(2019省赛A组第3题)
  10. AndroidManifest文件
  11. win10内存占用率过高怎么办_DNF:WIN10玩DNF卡顿,内存占用过高的解决方法
  12. 2023-2028年中国燕麦奶行业市场预测与投资规划分析报告
  13. 今天距离2022年除夕还有多少天?春节放假倒计时在手机便签上提醒
  14. 数电知识点总结第二章:逻辑代数基础
  15. mysql 实现日期格式化(date_format)
  16. java 高内聚低耦合_高内聚低耦合法则实例解析
  17. Android 高德地图 自己位置的显示与点地图上任意一点的坐标
  18. python:scipy.optimize.minimize(method=’Nelder-Mead’)
  19. Registration system
  20. 成功将log4cpp升级到了vs2005版本,总结下编译时报错及相应的解决方法

热门文章

  1. docsify安装,docsify搭建,docsify使用教程
  2. Conflux Studio 安装教学
  3. 矩阵的投影、线性拟合与最小二乘法
  4. 在计算机中 无符号书最常用于表示,2012年9月计算机等考《一级MS Office》全真模拟试卷(19)...
  5. 【开发工具】【memtester】内存测试工具(memtester)的使用
  6. 数字图像处理 实验二:图像的平滑滤波
  7. 一卡通系统软件测试,公共交通一卡通互联互通测试平台的研究
  8. c语言课程设计猜数字游戏报告,C语言课程设计-猜数字游戏报告.doc
  9. niuke题霸SQ/L篇
  10. 菜鸟学好 Linux 大绝招