提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
笔者本科时候有幸接触了OpenCV3.2.0版本的学习,后因考研压力不得不暂时停下学习的脚步,现在考研任务结束了,未来的导师也是从事的该方向,笔者又开始了新一轮的学习。回来发现OpenCV已经出到了4.5.5版本,遂重新下载新版本并决定记录这一学习历程。由于笔者水平有限,可能有错误之处还请诸位大佬多多包涵并烦请指出,让我们一起学习,共同进步。
首先需要说明的是:我是按着毛星云前辈编写的OpenCV3编程入门进行学习的,我会尽力把星云前辈的程序转成符合OpenCV4.5.5版本的。毛星云前辈于2021年12月11日不幸过世,他是我非常敬仰的一位业内大佬,我也是看他的书才开始接触OpenCV。
提示:以下是本篇文章正文内容,下面案例可供参考
Canny算子由 John F. Canny 在 1986 年开发。Canny 算法也被许多人称为最佳检测器,旨在满足三个主要标准:
步骤:
非极大值抑制
这会删除不被视为边缘一部分的像素。因此,只保留细线(候选边缘)。
滞后阈值
最后一步。Canny 确实使用了两个阈值(上限和下限):
如果像素梯度高于上限阈值,则该像素被接受为边缘
如果像素梯度值低于下阈值,则将其拒绝。
如果像素梯度在两个阈值之间,那么只有当它连接到高于上限阈值的像素时才会被接受。
我们常用的是Canny()函数
在OpenCV官方文档中是这么写的:
void cv::Canny (
InputArray image,
OutputArray edges,
double threshold1,
double threshold2,
int apertureSize = 3,
bool L2gradient = false
)
第一个参数是输入图像,
第二个参数是输出边缘图;单通道 8 位图像,其大小与 image 相同,
第三个参数是滞后过程的第一个阈值,
第四个参数是滞后过程的第二个阈值,
第五个参数是Sobel算子的孔径大小,
第六个参数是计算图像梯度幅值的标识
Sobel算子结合了高斯平滑和微分求导两个部分,用来计算图像灰度函数的近似梯度。因此结果或多或少能抵抗噪声。大多数情况下,使用 (xorder = 1, yorder = 0, ksize = 3) 或 (xorder = 0, yorder = 1, ksize = 3) 调用该函数来计算第一个 x 或 y 图像导数。
第一种情况(计算x)对应于一个内核:
第二种情况(计算y)对应于第二个内核:
我们常用的是Sobel()函数
在OpenCV官方文档中是这么写的:
void cv::Sobel (
InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
int ksize = 3,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
第一个参数是输入图像,
第二个参数是输出与 src 大小和通道数相同的图像,
第三个参数是导数 x 的阶数,
第四个参数是导数 y 的阶数,
第五个参数是扩展 Sobel 核的大小;它必须是 1、3、5 或 7,
第六个参数是计算导数值的可选比例因子;默认情况下,不应用缩放,
第七个参数是在将结果存储到 dst 之前添加到结果中的可选增量值,
第八个参数是像素外推法
函数通过将使用 Sobel 算子计算的第二个 x 和 y 导数相加来计算源图像的拉普拉斯算子:
这是在ksize > 1. 当 时ksize == 1,拉普拉斯算子是通过使用以下方法过滤图像来计算的3 × 3阵:
我们常用的是Laplacian()函数
在OpenCV官方文档中是这么写的:
void cv::Laplacian (
InputArray src,
OutputArray dst,
int ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
第一个参数是输入图像,
第二个参数是输出与 src 大小和通道数相同的图像,
第三个参数是目标图像的所需深度,
第四个参数是用于计算二阶导数滤波器的孔径大小,
第五个参数是计算的拉普拉斯值的可选比例因子,
第六个参数是在将结果存储到 dst 之前添加到结果的可选增量值,
第七个参数是像素外推法
使用 Scharr 算子计算第一个 x 或 y 图像导数。该函数使用 Scharr算子计算第一个 x 或 y 空间图像导数:
我们常用的是Scharr()函数
在OpenCV官方文档中是这么写的:
void cv::Scharr (
InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
第一个参数是输入图像,
第二个参数是输出与 src 大小和通道数相同的图像,
第三个参数是目标图像的所需深度,
第四个参数是导数 x 的阶数,
第五个参数是导数 y 的阶数,
第六个参数是计算导数值的可选比例因子;默认情况下,不应用缩放,
第七个参数是在将结果存储到 dst 之前添加到结果中的可选增量值,
第八个参数是像素外推法
霍夫线变换是一种用于检测直线的变换。为了应用变换,首先需要进行边缘检测预处理。(这段星云前辈的书中讲的非常好,很容易懂)
原理:在笛卡尔坐标系中:可由参数斜率和截距(m,b)表示
在极坐标系:可由参数极径和极角(r,θ)表示
对于霍夫变换,可采用第二种方式极坐标系来表示直线:
化简得:
如果对于给定的(X0,y0)我们绘制穿过它的直线,我们会得到一个正弦曲线
如果两个不同点的曲线在平面上相交,这意味着他们将通过同一条直线
我们常用的是HoughLines()函数
在OpenCV官方文档中是这么写的:
void cv::HoughLines (
InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double srn = 0,
double stn = 0,
double min_theta = 0,
double max_theta = CV_PI
)
第一个参数是输入图像,
第二个参数是线的输出向量,
第三个参数是累加器的距离分辨率,
第四个参数是累加器的角度分辨率,
第五个参数是累加器阈值参数,
第六个参数是对于多尺度霍夫变换,它是距离分辨率 rho 的除数,
第七个参数是对于多尺度霍夫变换,它是距离分辨率 theta 的一个除数,
第八个参数是对于标准和多尺度霍夫变换,检查线的最小角度,
第九个参数是对于标准和多尺度霍夫变换,检查线的最大角度
霍夫圆变换的工作方式与前面教程中解释的霍夫线变换大致相似。
在线检测案例中,一条线由两个参数定义。在圆形的情况下,我们需要三个参数来定义一个圆形:( x,y,r )
为了提高效率,OpenCV 实现了一种比标准霍夫变换稍微复杂的检测方法:霍夫梯度法,它由两个主要阶段组成。第一阶段涉及边缘检测并找到可能的圆心,第二阶段为每个候选中心找到最佳半径
我们常用的是HoughCircles ()函数
在OpenCV官方文档中是这么写的:
void cv::HoughCircles (
InputArray image,
OutputArray circles,
int method,
double dp,
double minDist,
double param1 = 100,
double param2 = 100,
int minRadius = 0,
int maxRadius = 0
)
第一个参数是输入图像,
第二个参数是找到的圆的输出向量,
第三个参数是检测方法,
第四个参数是累加器分辨率与图像分辨率的反比,
第五个参数是检测到的圆的中心之间的最小距离,
第六个参数是第一个特定于方法的参数,
第七个参数是第二个方法特定的参数,
第八个参数是最小圆半径,
第九个参数是最大圆半径
今天主要学习了边缘检测和直线与圆的检测,星云前辈的《OpenCV3》关于这一部分讲的特别好,非常通俗易懂。