::返回OpenCV算子速查表
1. 函数定义
1.1 声明
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
);
void Scharr(
InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
);
- 以下是《学习OpenCV3》中对Sobel的讲解:
- Sobel算子有一个好处就是可以将核定义为各种大小,并且可以快速、迭代式地构造这些核。
- 大的核可以更好的近似导数,因为可以消除噪声影响。不过。假如导数在空间上变化剧烈,核太大会使结果发生偏差。
- Sobel不是真正的导数,因为它定义在离散空间上。它实际上是一个多项式,在x方向上进行二阶Sobel运算表示的并不是二阶导数,而是对抛物线函数的局部拟合。这也说明了为什么要使用一个更大的核,更大的核拟合了更多的像素。
- Sobel算子的缺点是核比较小的时候准确度不高。对于大型的核,近似过程使用了较多的点,因此精度问题不太显著。对于3×3的Sobel滤波器,梯度角距离水平或垂直方向越远,误差越明显。
- Scahrr可消除3×3这样小但是快的Sobel导数滤波器所带来的误差。Scharr同样很快,但是精度更高。
1.2 重要参数解析
- Sobel函数支持就地调用。
- dx: x方向的求导顺序,0表示不求导。
- dy: y方向的求导顺序,0表示不求导。
- ksize:Sobel滤波器的尺寸,正奇数,OpenCV给出的取值范围是 1, 3, 5, or 7,实际上最大可以支持到31。
- 一般情况下,都是用ksize x ksize内核来计算导数的。然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核。且这种情况下,并没有进行高斯平滑操作。
- scale:用来计算导数的可选择的缩放比例因子,缺省值是不使用缩放。
- delta:可选择的偏移值。
- 缩放因子和偏移值都会在把结果存入dst之前调用,这有助于将求导结果可视化。
- ksize有一个特殊的值“-1”,也就是FILTER_SCHARR,这意味着即将执行的是Scharr算法。使用的是 3×3 Scharr滤波器:
- 因此 Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType) 和 Sobel(src, dst, ddepth, dx, dy, FILTER_SCHARR, scale, delta, borderType) 是一样的,你完全可以只使用Sobel算子,想使用Scharr算子时设置一下ksize就好了。
- OpenCV官方文档中关于 Sobel 的讲解
- OpenCV官方文档中关于 Scharr 的讲解
2. 例程
2.1 处理效果
原图
在x,y方向分别求导
- 可以看出在x方向求导检测的是纵向的边缘,而在y方向求导检测的是横向的边缘。
如果两个方向一起求导,结果会如何呢?
- 结果并不好,边缘根本无法被检测出来。
dx的值为1和2有什么区别呢?
- 不难看出当dx为2相对于1来说,轮廓线条更多更细了。
参数scale对结果的影响
- 可以看出scale变大之后,边缘的亮度明显提升了
参数delta对结果的影响
- delta影响了除边缘以外的背景色灰度值
SCHARR和Scharr
- 这两者之间完全等同
2.2 代码
#include "stdafx.h"
#include <opencv.hpp>
using namespace cv;
int main()
{
Mat m_SrcImg = imread("./1.bmp", IMREAD_GRAYSCALE);
imshow("原图", m_SrcImg);
Mat m_DstImg;
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 0, 3);
imshow("Sobel x", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 0, 1, 3);
imshow("Sobel y", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 2, 0, 3);
imshow("Sobel x2", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 1, 3);
imshow("Sobel x1 y1", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 2, 3);
imshow("Sobel x1 y2", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 0, 3, 1, 0);
imshow("Sobel no scale no delta", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 0, 3, 3, 0);
imshow("Sobel scale", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 1, 0, 3, 1, 100);
imshow("Sobel delta", m_DstImg);
Sobel(m_SrcImg, m_DstImg, m_SrcImg.depth(), 0, 1, -1);
imshow("Sobel SCHARR", m_DstImg);
Scharr(m_SrcImg, m_DstImg, m_SrcImg.depth(), 0, 1);
imshow("Scharr", m_DstImg);
waitKey(0);
return 0;
}