快乐学习
前程无忧、中华英才非你莫属!

14-OpenCV-霍夫变换

目标:

本章节你需要学习以下内容:

*我们将理解霍夫变换的概念。

*我们将看到如何使用它来检测图像中的线条。

*我们将看到以下函数:cv.HoughLines(),cv.HoughLinesP()

1、理论

如果你能够以数学形式表示该形状,则霍夫变换是一种检测任何形状的流行技术。

它可以检测形状,即使它被破坏或扭曲一点点。我们将看到它如何适用于生产线。

线可以表示为$y=mx+c$或以参数形式表示为$rho =x costheta +y sintheta$其中$rho$是从原点到线的垂直距离,

$theta$是由该垂直线和水平轴形成的角度 以逆时针方向测量(该方向因你表示坐标系的方式而异。此表示在OpenCV中使用)。检查下图:

因此,如果线在原点以下通过,它将具有正rho和小于180的角度。

如果它超过原点,而不是采用大于180的角度,则角度小于180,并且rho被认为是否定的。任何垂直线都有0度,水平线有90度。

现在让我们看看霍夫变换如何为线条工作。任何线都可以用这两个术语表示,$left ( rho ,theta right )$。

因此,首先它创建一个2D数组或累加器(以保存两个参数的值),并且最初设置为0。

令行表示$rho$,列表示$theta$。阵列的大小取决于你需要的准确度。

假设你希望角度精度为1度,则需要180列。对于$rho$,可能的最大距离是图像的对角线长度。因此,取一个像素精度,行数可以是图像的对角线长度。

考虑一个100x100的图像,中间有一条水平线。

取第一点。你知道它的(x,y)值。现在在线方程中,将值$theta= 0,1,2,cdots ,180$并检查你得到的$rho$。

对于每个$left ( rho ,theta right )$对,在我们的累加器中将其在相应的$left ( rho ,theta right )$单元格中增加1。所以现在在累加器中,单元格(50,90)= 1以及其他一些单元格。

现在取第二点就行了。和上面一样。增加与你获得的(rho,theta)对应的单元格中的值。

这次,单元格(50,90)= 2.你实际做的是投票给$left ( rho ,theta right )$值。

你可以继续执行此过程中的每个点。在每个点,单元格(50,90)将递增或投票,而其他单元格可能会或可能不会被投票。这样,最后,单元格(50,90)将获得最大票数。因此,如果你在累加器中搜索最大投票数,则会得到值(50,90),表示此图像中距离原点和角度为90度的距离为50。

它在下面的动画中有很好的展示(图片提供:Amos Storkey)

这就是霍夫变换对线条的作用。 它很简单,也许你可以自己使用Numpy来实现它。 下面是显示累加器的图像。 某些位置的亮点表示它们是图像中可能线条的参数。 (图片提供:维基百科)

2、OpenCV中的霍夫变换

上面解释的所有内容都封装在OpenCV函数cv.HoughLines()中。 它只返回一个数组:math:(rho,theta)`values。$rho$以像素为单位测量,$theta$以弧度为单位测量。第一个参数,输入图像应该是二进制图像,因此在应用霍夫变换之前应用阈值或使用精确边缘检测。 第二和第三参数分别是$rho$和$theta$精度。第四个参数是阈值,这意味着它应该被视为一条线的最小投票。请记住,投票数取决于该线上的点数。因此它表示应检测的最小行长度。

import cv2 as cv
import numpy as np
img = cv.imread('../data/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*rho
    y0 = b*rho
    x1 = 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)

窗口将如下图显示:

3、概率Hough变换

在霍夫变换中,你可以看到即使对于具有两个参数的行,也需要大量计算。概率Hough变换是我们看到的Hough变换的优化。它没有考虑所有要点。相反,它只需要一个足以进行线检测的随机点子集。我们必须降低门槛。 请参见下图,其中比较霍夫空间中的霍夫变换和概率霍夫变换。(图片提供:Franck Bettinger的主页)

OpenCV实现基于使用Matas,J。和Galambos,C。和Kittler,J.V。[122]的渐进概率Hough变换的线的鲁棒检测。 使用的函数是cv.HoughLinesP()。 它有两个新的论点。

  • minLineLength - 最小线长。 短于此的线段将被拒绝。

  • maxLineGap - 线段之间允许的最大间隙,将它们视为一条线。

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

import cv2 as cv
import numpy as np
img = cv.imread('../data/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)


窗口将如下图显示:

十四、霍夫圆变换


目标:

本章节你需要学习以下内容:

*我们将学习使用Hough变换来查找图像中的圆圈。

*我们将看到这些函数:cv.HoughCircles()

理论

圆圈在数学上表示为$left ( x-x_{center} right )^{2}+left ( y-y_{center} right )^{2}=r^{2}$其中$left ( x_{center},y_{center} right )$是圆的中心,r是圆的半径。从等式中,我们可以看到我们有3个参数,因此我们需要一个用于霍夫变换的3D累加器,这将非常无效。 因此,OpenCV使用更棘手的方法,Hough Gradient Method,它使用边缘的梯度信息。

我们在这里使用的函数是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 circle
    cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imshow('detected circles',cimg)
cv.waitKey(0)
cv.destroyAllWindows()


窗口将如下图显示:

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » 14-OpenCV-霍夫变换

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!