资源下载地址:https://download.csdn.net/download/sheziqiong/85627479
实验内容和要求
输入一张彩色图像,要求能够检测出其中的直线、圆。
实验器材
C++ OpenCV 4.5.0 开发平台:Visual Studio 2019 Debug x64

; 具体实现
3.1 直线检测——利用 Hough 变换
3.1.1 构造 Hough 空间
直线检测的 Hough 空间是对直角坐标系下的(x, y)映射到极坐标系下的(ρ,θ)后,以ρ和θ为轴建立的坐标系空间。映射关系如下图所示:
对于一副大小为 D×D 的图像,通常 ρ 的取值范围为[90,90]。计算方法与直角坐标系中累加器的计算方法相同,最后得到最大的 A 所对应的(ρ,θ)。
3.1.2 边缘检测
我自己实现了 Sobel 算子的检测,但是在面对比较复杂的图形时,效果不是特别好。在此处将 Sobel 边缘检测和 Canny 边缘检测都写出来,并比较结果。
Sobel 算子采用了边缘中心权值为 2 的版本,分别对 x 和 y 方向做了卷积,并且计算了方向。

Canny 边缘检测使用了 OpenCV 自带的函数:先进行一次高斯平滑,掩膜的大小由图像本身大小决定,然后用 Canny 函数进行检测。

对同一张图片进行两种方法滤波,结果如下:

左图为自己实现的 Sobel 算子检测结果,运算速度一般;右图为平滑滤波+Canny 检测的结果,运算速度很快。
; 3.1.3 对边缘点统计,投票,更新累加器
对检测完毕的边缘图像中的”边缘点”,在每一个θ进行遍历,计算出对应的ρ,投票(对应在Hough 空间的累加器里加 1)。

3.1.4 按照一定的阈值进行输出和绘制
遍历 Hough 空间(累加器),对于最多的交点(也就是比较大的值)处,提取ρ和θ还原原直线信息,并且绘制在图上。
结果分析与改进请见第四部分。
3.2 圆检测——利用 Hough 变换
一个圆的确定需要三个参数:两个参数用来确定圆心,一个参数用来确定半径。
[En]
The determination of a circle requires three parameters: two parameters are used to determine the center of the circle and one parameter is used to determine the radius.
3.2.1 构建 Hough 空间
圆检测的 Hough 累加器可以理解成一个三维数组(空间盒),长宽是原图像的长宽,深度是对半径的预测和累计。对于圆检测首先规定了一个半径的范围,只检测半径长度在该范围内的圆。

; 3.2.2 遍历边缘检测图像,统计与投票
对于边缘点,遍历所有可能的半径 r,根据圆的参数方程进行解析,得出两个可以确定圆心的点,对相应的累加器加 1。

3.2.3 根据阈值还原检测圆

在筛选与重现的过程中做了一次根据距离的筛选,即两个圆的圆心之间的距离,以防止很多重复。
[En]
In the process of screening and reproduction, a screening is made according to the distance, that is, the distance between the centers of the two circles, in order to prevent many repetitions.
; 实验结果与分析
4.1 直线检测分析
遍历全图的计算量很大,主要是在每一个需要检测的点的余弦值和正弦值的计算,因此在计算之前先对 0 到 180 的所有角度的余弦值和正弦值做了哈希表,用于后面的直接索引。这样一来加速了算法。
[En]
The amount of calculation of traversing the whole graph is very large, mainly the calculation of the cosine and sine values of each point to be detected, so before the calculation, a hash table is made for the cosine and sine values of all angles from 0 to 180, which is used for the following direct index. This speeds up the algorithm.

在对一般图片的检测中,呈现出的结果比较良好:





[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vOg03nK2-1655092296033)(https://www.writebug.com/myres/static/uploads/2022/6/12/9c06e5be879c9f6aa40e1ebb9078ef25.writebug)]
但是对于 highway 这张信息比较复杂的图片,用同样的滤波方式和检测出来的效果却不如人意。除了关键的几条直线被检测出来之外,其他的一些不希望出现的线条也被检测了出来,而且重复性非常大:所以加入了一步非极大值抑制,对累加器的一定邻域内选择最大值输出,减少了冗余的直线。


效果有了很大改观。但是可以看出,对于噪音的鲁棒性不是很好:

; 4.2 圆检测分析
效果比较好,但是由于设定了圆心之间的距离阈值,所以同心圆无法检测。
[En]
The effect is better, but because the distance threshold between the centers of the circle is set, the concentric circle can not be detected.

心得与体会
这次实验感觉难度比较大,在仔细学习了算法以后,就着手开始自己实现Hough 变换了。遇到了以下几个大问题,被用相应方法自己解决:
- 运算速度慢——将正弦值和余弦值列哈希表索引以加速;
- 圆检测的过程中有不希望出现的点被累加器计算——检测是否在原图像范围内,并且对 Hough 空间进行了一次二值化;
- 直线检测比较杂乱——在不改变阈值的情况下增加非极大值抑制,有一定效果。
[En]
Line detection is messy-adding non-maximum suppression without changing the threshold has a certain effect.*
但是还有问题,主要是在直线检测方面,对于噪音的影响鲁棒性很差。通过改变高斯滤波算子大小和 Canny 算子大小,甚至是用了形态学变化,效果都不是很好。
这次实验收获很大,自己基本实现了 Hough 变换检测直线和圆的算法,编程能力有了提升,阅读源码的能力也有了提升,同时自己实现了一下 Sobel 算子检测边缘的算法,效果也符合预期。
资源下载地址:https://download.csdn.net/download/sheziqiong/85627479
Original: https://blog.csdn.net/newlw/article/details/125257468
Author: biyezuopinvip
Title: 基于C++OpenCV实现的直线检测、圆检测
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/68271/
转载文章受原作者版权保护。转载请注明原作者出处!