OpenCV学习(4.13) 霍夫变换

2024-06-14 05:12
文章标签 学习 opencv 变换 霍夫 4.13

本文主要是介绍OpenCV学习(4.13) 霍夫变换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.霍夫变换

霍夫变换(Hough Transform)是图像处理中的一种技术,主要用于检测图像中的直线、圆或其他形状。它通过将图像空间中的点映射到参数空间来实现,这样,图像空间中在同一直线上的点在参数空间中会形成一条曲线,而这条曲线上的交点对应于图像空间中的直线。
霍夫变换的基本思想是:

  1. 对于图像中的每一个边缘点,考虑它可能属于的所有候选直线。
  2. 对于每一条候选直线,使用霍夫变换算法在参数空间中对其进行投票。
  3. 投票最多的候选直线即为检测到的直线。

霍夫变换有几种变体,包括:

  • - 霍夫直线变换:用于检测图像中的直线。
  • - 霍夫圆变换:用于检测图像中的圆。
  • - 霍夫椭圆变换:用于检测图像中的椭圆。

霍夫变换的优点是它对噪声和图像间断有一定的鲁棒性,但缺点是计算量大,特别是对于霍夫圆变换,因为需要考虑三个参数(圆心坐标和半径)。因此,在实际应用中,通常会采用一些优化技术来减少计算量,例如使用图像金字塔或限制参数范围。

2. 霍夫线变换

在这一章当中,

  • 我们将理解霍夫变换的概念。
  • 我们将看到如何使用它来检测图像中的线条。
  • 我们将了解以下函数: cv.HoughLines() , cv.HoughLinesP()

如果您能够以数学形式表示该形状,则霍夫变换是一种用于检测任何形状的流行技术。它可以检测到形状,即使它被破坏或扭曲一点点。我们将看到它如何适用于生产线。

一条线可以表示为 $$y = mx+c$$ 或以极坐标形式 $$\rho = x \cos \theta + y \sin \theta$$ 表示为其中 $$\rho$$ 是垂线从原点到直线的距离。$$\theta$$ 是这条垂直线形成的角度,水平轴是逆时针测量的(该方向因你代表坐标系而变化。这种表示用于 OpenCV )。检查下图:

所以如果这条线经过原点以下,它会有一个小于 180 度的正角度。如果它在原点上方,我们不是取一个大于 180 的角,而是取一个小于 180 的负角度。任何垂直线都是 0 度,水平线是 90 度。

现在我们来看看霍夫变换是怎么作用于直线的。任何线都可以被表示成这两项(r,θ) 。所以首先它创建了一个二维数组,或者是累加器(来保存这两个参数的值)然后他设置(r,θ) 作为初始值。 令(二维数组的)行表示r,令列表示 θ 。数组的大小取决于你需要的精准度。假设说你想要角度的精度是精确到 1 度,那你就需要 180 列。而对于r来说,最大可能的距离是图像的对角线长度。因此,要精确到一个像素的程度,行数应该是图像的对角长度。

想象有一张 100x100 的图像,它上面有一条水平的线条在图像正中间。取这条线的第一个点,你知道它的坐标 (x,y)值。现在,按照这条直线的等式,把值​​​​​​​θ = 0,1,2,...,180带入,并且查看你获取到的r值。对每一对​​​​​​​(r,θ) ,我们都把它们在累加器中对应的值计数增加 1。而此时,在这个计数器中,单元 (50,90) 和其他单元一样计数等于 1。

现在去这条线上的第二个点,重复上面的步骤。增加单元中你拿到的对应的值(rho, theta)。这一次,单元(50,90)的计数增到到了 2。你实际上做的是投票投出​​​​​​​(r,θ) 值。你不断为这条直线上所有的点继续这个过程。在每一个点,单元(50,90)都会得票,而其他的单元有可能会得票,也有可能不会。按这个方案,最终单元 (50,90) 会获得最高的投票(译者注:在 100X100 的图像正中水平的直线到原点距离为 50,垂角 90 度)。所以最终搜索我们的累加器来找最高得票的单元,我们就会取到 (50,90),这就说明图像中有一条线距离原点垂距 50,它过原点的垂线和水平线夹角为 90 度。这个过程很好的显示在了以下的动画中

这就是霍夫变化针对直线工作的原理。非常简单,也许你可以用 Numpy 自己来实现它。以下是一张显示了累加器的图像。在某些地方的亮点说明它们是图像中可能线条的参数。 

 

2. 1 OpenCV中的霍夫变换

上面解释的这一堆东西,在 OpenCV 里都封装起来成为**cv.HoughLines()** 函数了。它简单的返回了一个(rho, theta)`值得数组。$$\rho$$ 的单位是像素,$$\theta$$的单位是弧度。第一个参数,输入图像应该是个二元图像,所以在应用霍夫线性变换之前先来个阈值法或者坎尼边缘检测。第二、第三参数分别是 $$\rho$$ 和 $$\theta$$ 的精度。第四个参数则是一个阈值,它代表了一个$$(\rho,\theta)$$单元被认为是一条直线需要获得的最低票数。要记住的是,得票数其实取决于这条直线穿过了多少个点。所以它也代表了应被检测出的线条最少有多长。

霍夫变换作用于直线的过程通常指的是霍夫直线变换(Hough Line Transform),它是一种在数字图像中检测直线的常用技术。霍夫直线变换的基本思想是将图像空间中的直线映射到参数空间中的点上,从而将直线检测问题转化为在参数空间中寻找交点的问题。
霍夫直线变换的具体步骤如下:
1. **边缘检测**:首先,使用边缘检测算法(如Canny边缘检测)找到图像中的边缘像素。
2. **参数空间投票**:对于每个边缘像素,考虑所有可能的直线方程,通常是直线方程的极坐标形式:\( r = x \cos(\theta) + y \sin(\theta) \),其中 \( (r, \theta) \) 是参数空间中的点,\( (x, y) \) 是图像空间中的边缘像素坐标。对于每个 \( (x, y) \) ,在参数空间中画出对应的所有 \( (r, \theta) \) 曲线。
3. **累加和阈值**:在参数空间中,对于每个可能的 \( (r, \theta) \) 对,累加器数组中的一个单元被增加。当多个边缘像素对应的曲线在参数空间中相交于同一点时,该点的累加器值会很高。
4. **检测峰值**:在累加器数组中,峰值对应于图像中的直线。设置一个阈值,只有超过这个阈值的累加器值才被认为是检测到的直线。
5. **提取直线**:对于每个检测到的峰值,其对应的 \( (r, \theta) \) 值可以用来确定图像空间中的一条直线。
霍夫直线变换的优点是它对图像中的直线断裂和噪声不敏感,能够检测出图像中所有的直线,无论其方向如何。然而,这种方法的一个缺点是计算量大,特别是对于高分辨率图像。此外,它通常只适用于检测直线,而不适用于检测曲线或其他复杂的形状。对于这些情况,需要使用霍夫变换的其他变体,如霍夫圆变换或广义霍夫变换。
 

import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLines(edges,1,np.pi/180,200)
for line in lines:rho,theta = line[0]a = np.cos(theta)b = np.sin(theta)x0 = a*rhoy0 = b*rhox1 = int(x0 + 1000*(-b))y1 = int(y0 + 1000*(a))x2 = int(x0 - 1000*(-b))y2 = int(y0 - 1000*(a))cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imwrite('houghlines3.jpg',img)

检查以下结果: 

2.2 概率Hough变换 

概率Hough变换(Probabilistic Hough Transform)是标准Hough变换的一种改进版本,它用于检测图像中的直线,但是相比于标准Hough变换,它更加高效,因为它不需要遍历整个参数空间。概率Hough变换通过随机选择图像空间中的边缘点,并只考虑这些点对应的参数空间中的少量可能直线,从而减少了计算量。
概率Hough变换的基本步骤如下:
1. **边缘检测**:与标准Hough变换一样,首先使用边缘检测算法找到图像中的边缘像素。
2. **随机采样**:从检测到的边缘点中随机选择一个点。
3. **局部峰值搜索**:对于选中的边缘点,在参数空间中搜索其可能的直线参数。这一步通常是通过在较小的邻域内进行累加器投票来实现的。
4. **累加器阈值**:如果参数空间中的某个局部区域的累加器值超过了设定的阈值,则认为找到了一条直线。
5. **重复过程**:重复步骤2到4,直到所有的边缘点都被考虑过,或者达到了某种停止条件(如找到了足够的直线)。
6. **结果验证**:最后,可能需要对检测到的直线进行验证,以确保它们是真实的直线,而不是由噪声或错误的边缘检测引起的假阳性。

概率Hough变换相比于标准Hough变换的优点是它更快,因为它不需要为每个边缘点计算和投票所有的参数空间。此外,它通常能够给出更准确的结果,因为它考虑了边缘点之间的局部关系。这种方法的缺点是它可能不会检测到图像中所有的直线,特别是当直线的支持点较少时。因此,概率Hough变换适用于直线较为密集的场景,而在直线稀疏的情况下可能不如标准Hough变换有效。

在霍夫变换中,你可以发现即使是一条仅有两个参数的直线,也需要用到大量的计算。概率霍夫变换是我们已知的,针对霍夫变换的优化方案。它不去取所有的点来列入考虑,取而代之的是取足够完成直线检测的这些点的随机子集。只要我们把阈值下调一点。下图在霍夫空间中比较了霍夫变换与概率霍夫变换。

OpenCV 实现基于使用 Matas,J。和 Galambos,C。和 Kittler,J.V。 [133] 的渐进概率 Hough 变换的线的鲁棒检测。使用的函数是 cv.HoughLinesP() 。它比之前介绍的函数多出来两个参数:

  • minLineLength - 最小线长。比这个值小的线条会被丢弃。
  • maxLineGap - 允许线段之间的最大间隙,以便将(在同一条直线上的)线段视为同一条。

最好的是,它直接返回直线的两个端点。在前面的例子中,你只得到直线的参数,你必须找到所有的点。而这个方法,一切都是那么的直接和简单。

import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
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.imwrite('houghlines5.jpg',img)

 

3. 霍夫圆变换 

在这一章当中,

  • 我们将学习使用霍夫变换来查找图像中的圆圈。
  • 我们将了解这些函数: cv.HoughCircles()

圆圈在数学上表示为$(x-x_{center})^2 + (y - y_{center})^2 = r^2$其中$(x_{center},y_{center})$是圆的中心,$r$ 是圆的半径。从这个公式来看,得知我们有三个参数,这样我们就需要一个三维度的累加器来做霍夫变换了,这样效率是非常低的。所以 OpenCV 用了更巧妙的方法Hough Gradient Method ,它利用了边缘的梯度信息。

霍夫圆变换(Hough Circle Transform)是霍夫变换的一种变体,专门用于检测图像中的圆。与霍夫直线变换不同,霍夫圆变换需要检测三个参数:圆心坐标 \( (x, y) \) 和半径 \( r \)。这导致参数空间成为三维的,因此计算量相对较大。
霍夫圆变换的基本步骤如下:

  • 1. **图像预处理**:首先对图像进行滤波和边缘检测,以突出圆的特征。
  • 2. **参数空间投票**:对于每个边缘点,考虑所有可能的半径大小,对于每个可能的半径,计算圆心可能的位置,并在三维参数空间中对应的 \( (x, y, r) \) 处进行投票。
  • 3. **累加和峰值检测**:在参数空间中,累加器数组中的值表示找到圆的可能性。累加器数组中的局部峰值对应于图像中的圆。设置一个阈值,只有超过这个阈值的累加器值才被认为是检测到的圆。
  • 4. **提取圆心和半径**:对于每个检测到的峰值,其对应的 \( (x, y, r) \) 值可以用来确定图像空间中的一个圆。

由于霍夫圆变换的计算量很大,实际应用中通常会采用一些启发式方法来减少搜索空间,例如限制半径的范围或使用图像金字塔进行多尺度检测。
霍夫圆变换的优点是它对图像中的圆具有一定的鲁棒性,即使圆不完整或存在一定的噪声也能检测出来。然而,它的计算量大,且对噪声敏感,因此在实际应用中需要根据具体情况选择合适的参数和预处理步骤。
 

我们在这里使用的函数是 cv.HoughCircles() 。它的参数非常的多,这些参数在文档中都有详细的解释。所以我们直接上代码吧。

import numpy as np
import cv2 as cv
img = cv.imread('opencv-logo-white.png',0)
img = cv.medianBlur(img,5)
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:# draw the outer circlecv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)# draw the center of the circlecv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imshow('detected circles',cimg)
cv.waitKey(0)
cv.destroyAllWindows()

结果如下图所示:

 

 

 

这篇关于OpenCV学习(4.13) 霍夫变换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059466

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个