CV15 轮廓检测:霍夫变换原理及应用

简介: 虽然图二中有多个交点,但我们主要关注的是三线相交的情况,这也是霍夫变换的后处理的基本方式:选择由尽可能多直线汇成的点

1.基本原理


1.1数学分析


  • 如下图,y=kx+q


我们可以把k看作自变量,把q看作因变量,则有:


image.png


这个过程,称作霍夫变换,在霍夫空间上,可得到一个点,如下图所示:



由此可见:坐标系的直线,经霍夫变换后,变成了霍夫空间上的点,如下图:



  • 若有A(x1,y1) 、B(x2,y2),且x1!=x2,y1!=y2


image.png


有交点Q,在交点Q处,x1=x2,y1=y2


此时,可以说明A/B在同一条直线上


k变换,q也就随之变换。这个过程表示经过D点的直线,360°旋转,如下图:


  • 多点共线的情况,如下图:


虽然图二中有多个交点,但我们主要关注的是三线相交的情况,这也是霍夫变换的后处理的基本方式:选择由尽可能多直线汇成的点


  • 但是仅用k、q表示霍夫空间是有问题的,因为我们忽视了一种特殊情况:直线与x轴垂直的情况


k=∞是不方便表示的,所以我们必须改变一下坐标系:用极坐标表示点,线


image.png


所以,可用[ρ,θ]表示一个点


霍夫空间也随之改变,但也就是点的曲线变了而已


48e599b1ac9e29080a579589062032d2.png


1.2图像处理应用


那么我们应如何把它用在图像处理中呢?


  • 假设我们图像中有一段有8个像素点组成直线


。1.建立直角坐标系

。2.将第一个像素点的(x,y)代入公式中


image.png


。3.此时角度作为自变量,我们选用遍历查询的办法,不断旋转增加角度(记住,角度增加量极小,但下图为了方便计算,我每次旋转都增加了45°)

。4.在(1,8)处有5个ρ值,我们将结果记录下来

。5.然后计算(3,6)坐标处,依此类推,也将结果记录下来

。6.每个像素点的旋转的数据都记录下来之后,找哪一个ρ值出现的最多(下图是 (9√2)/2)

。7.再次带(9√2)/2到公式(4)中,得到角度

。8.计算出**[ρ,θ]**,即可表示出一条线了


以上就是标准霍夫变换的原理

但我们一般不用标准霍夫变换,而是用概率霍夫变换😂😂😂


参考资料:霍夫变换直线检测(Line Detection)原理及示例

(四十八)通俗易懂理解——霍夫变换原理

2.概率霍夫变换


2.1标准霍夫与概率霍夫


  • 标准霍夫变换:把图像映射到它的参数空间上,它需要计算所有的M个边缘点,这样它的运算量和所需内存空间都会很大。


  • 概率霍夫变换:如果在输入图像中只是处理m(m<M)个边缘点,则这m个边缘点的选取是具有一定概率性的,因此该方法被称为概率霍夫变换。该方法还有一个重要的特点就是能够检测出线端,即能够检测出图像中直线的两个端点,确切地定位图像中的直线。概率霍夫变换的优点:只分析图像点的一部分(标准的是分析全部),并估计这些点属于同一条线的概率,计算强度小,运行速度快


2.2概率霍夫检测步骤


1.随机抽取图像中的一个特征点,即边缘点,如果该点已经被标定为是某一条直线上的点,则继续在剩下的边缘点中随机抽取一个边缘点,直到所有边缘点都抽取完了为止;

2.对该点进行霍夫变换,并进行累加和计算;

3.选取在霍夫空间内值最大的点,如果该点大于阈值的,则进行步骤4,否则回到步骤1;

4.根据霍夫变换得到的最大值,从该点出发,沿着直线的方向位移,从而找到直线的两个端点;

5.计算直线的长度,如果大于某个阈值,则被认为是好的直线输出,回到步骤1。


3.霍夫变换检测线


3.1cv2.HoughLinesP()函数


HoughLinesP函数就是利用概率霍夫变换来检测直线的


cv2.HoughLinesP()函数

功能:概率霍夫变换检测直线


输入参数:


1.image:图像名,强烈建议输入经Canny检测之后的图像

2.rho:搜索线时的位置距离间隔(以像素为单位)

3.theta:搜索线时的旋转角度差(以度为单位)

4.threshold:表示丢弃长度低于该阈值的线,显然这个值越大,所判断出的直线越少;这个值越小,所判断出的直线越多

5.minLineLength:设置最小线段长度,一次性丢弃较短的线

6.maxLineGap:最大直线间隙,即如果有两条线段在一条直线上,但它们之间因为有间隙,所以被认为是两个线段,如果这个间隙大于该值,则被认为是两条线段,否则是一条


返回值:lines为输出的直线向量,每条线用4个元素表示,即直线的两个端点的4个坐标值(x1, y1, x2, y2)表示,其中(x1, y1)表示线段的起点,(x2, y2)表示线段的终点


示例:lines = cv2.HoughLinesP(edges,1,np.pi/180,30,minLineLength,maxLineGap)


3.2线检测程序


import cv2 as cv
import numpy as np
img = cv.imread('test2.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
  x1,y1,x2,y2 = line[0]
  cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imshow('houghlines5.jpg',img)
cv.waitKey()
cv.destroyAllWindows()


注意!!!:


市面上有些教材书上是这么写的,无法得到理论结果💔


正确的答案为:


for line in lines:
  x1,y1,x2,y2 = line[0]
  cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)


4.霍夫变换检测圆


Opencv中还有一个函数cv2.HoughCircles,它通过霍夫梯度法,实现了圆的检测


参考资料:opencv —— HoughCircles 霍夫圆变换原理及圆检测


4.1cv2.HoughCircles()函数


cv2.HoughCircles()函数


功能:霍夫变换检测圆


输入参数:

1.img: 待检测的灰度图


2.cv2.HOUGH_GRADIENT:检测的方法,霍夫梯度,也是唯一的检测方法


3.1:检测的圆与原始图像具有相同的大小,dp=2,检测的圆是原始图像的一半


4.20:检测到的相邻圆的中心的最小距离(如果参数太小,除了一个真实的圆外,还可能会错误地检测到多个相邻圆。如果太大,可能会漏掉一些圆。)


5.param1:Canny 边缘检测的高阈值,低阈值被自动置为高阈值的一半,默认为 100


(霍夫梯度法里面已存在Canny检测,故我们无需重复)


6.param2:被计算机判定为圆的难度。它越小,就越可能检测到假圆;


而它越大的话,能通过检测的圆就更加接近完美的圆形了


7.minRadius:最小圆半径


8.maxRadius:最大圆半径,如果<=0,则使用最大图像尺寸。如果<0,则返回没有找到半径的中心。


返回值:cv2.HoughCircles的返回将其reshape为(-1, 3),每一行就是一圆的参数,分别是(圆心横坐标,圆心纵坐标,半径),最后用于该处:


cv2.circle(coins_img, (i[0], i[1]), i[2], (0, 0, 255), 5)   # 画圆


示例:circle=cv2.HoughCircles(gray_img,cv2.HOUGH_GRADIENT,1,120,param1=100,param2=30,minRadius=0,maxRadius=0)


4.2圆检测程序


import cv2
import numpy as np
planets = cv2.imread('planet_glow.jpg')
gray_img = cv2.cvtColor(planets,cv2.COLOR_BGR2GRAY)
gray_img = cv2.medianBlur(gray_img,5)
circles = cv2.HoughCircles(gray_img,cv2.HOUGH_GRADIENT,1,120,param1=80,param2=35,minRadius=0,maxRadius=0)
print(circles)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
    cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('planet',planets)
cv2.waitKey()
cv2.destroyAllWindows()


效果显著!😎😎😎


5.结语


Opencv入门篇已经学完了,接下来有其它的事情❌,这个专栏预计停更一两周📵


车牌检测,周三看看能不能做完😭😭😭


忙完之后,估计就到了用Haar级联实现人脸检测🐵

相关文章
|
缓存 NoSQL Java
后端接口性能优化分析-多线程优化(中)
后端接口性能优化分析-多线程优化
302 0
|
算法 安全 PHP
密码学系列之二:密码学基本概念
密码学系列之二:密码学基本概念
1206 0
密码学系列之二:密码学基本概念
|
机器学习/深度学习 监控 算法
图像去雾综述
图像去雾综述
|
人工智能 自然语言处理 IDE
通义灵码 AI IDE使用体验(1)项目初创
通义灵码 AI IDE上线,作为AI IDE的重度使用者怎能错过?本文详细体验了从安装到项目开发的全过程,界面友好,操作简便,支持智能问答、文件编辑、智能体三种模式。通过智能体方式快速开发项目,自动规划功能、管理环境,虽在复杂项目中仍有提升空间,但整体体验流畅,适合开发者尝试。
838 0
|
10月前
|
机器学习/深度学习 存储 人工智能
【科普向】我们所说的AI模型训练到底在训练什么?
人工智能(AI)模型训练类似于厨师通过反复实践来掌握烹饪技巧。它通过大量数据输入,自动优化内部参数(如神经网络中的权重和偏置),以最小化预测误差或损失函数,使模型在面对新数据时更加准确。训练过程包括前向传播、计算损失、反向传播和更新权重等步骤,最终生成权重文件保存模型参数,用于后续的应用和部署。理解生物神经网络的工作原理为人工神经网络的设计提供了灵感,后者广泛应用于图像识别、自然语言处理等领域。
|
编解码 前端开发 UED
探索无界:前端开发中的响应式设计深度解析与实践####
【10月更文挑战第29天】 本文深入探讨了响应式设计的核心理念,即通过灵活的布局、媒体查询及弹性图片等技术手段,使网站能够在不同设备上提供一致且优质的用户体验。不同于传统摘要概述,本文将以一次具体项目实践为引,逐步剖析响应式设计的关键技术点,分享实战经验与避坑指南,旨在为前端开发者提供一套实用的响应式设计方法论。 ####
297 4
|
机器学习/深度学习 人工智能 算法
【AI系统】关键设计指标
本文介绍了AI芯片设计中的关键指标与设计点,涵盖OPS、MACs、FLOPs等计算单位,以及精度、吞吐量、时延、能耗、成本和易用性等六大关键指标。文章还探讨了MACs和PE优化策略,以及通过算术强度和Roofline模型评估AI模型在特定芯片上的性能表现,为AI芯片的性能优化提供了理论依据和实践指导。
1034 1
|
存储 分布式计算 大数据
【大数据】分布式文件系统HDFS
【大数据】分布式文件系统HDFS
482 0
【大数据】分布式文件系统HDFS
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
596 0