美文网首页
OpenCV-Python教程:29.霍夫线变换

OpenCV-Python教程:29.霍夫线变换

作者: xxxss | 来源:发表于2017-06-20 11:34 被阅读1404次

    理论

    Hough Transform 是一个用来检测任意形状的流行技术,如果你能用数理形式表达一个形状,即便它是残缺不全的或者略微扭曲的,也能检测出来,我们来看看对于直线是怎么做的。

    一个直线可以表达为y = mx + c 或者参数形式p = x cosθ + y sinθ, 其中p是从原点到直线的垂直距离,θ是垂线和水平坐标轴的夹角。

    任何直线都可以表示成(ρ,θ). 首先它创建一个2D数组或者是收集器(拿着两个参数)初始化是0 。用行来代表ρ列代表θ.数组的大小由你需要的准确率来决定。假设你想要角度的准确率是1度,你需要180列。对于ρ,最大的可能距离是图的对角线的距离。所以对于一个像素的精确度来说,行数就是图像对角线的长度。

    假设一个100x100的图像,中间有一个水平线,对于线的第一个点,你知道他的(x,y)的值。在直线方程里,把θ = 0,1,2,...,180带入然后看ρ的值。对于每个(ρ,θ)对,你每次在收集器里加1,看他对应的(ρ,θ)。(50, 90)= 1

    现在看直线的第二个点,仍然按上面的做法,增加值得到对应的(ρ,θ).这次(50, 90) = 2, 你持续这个过程知道直线上的每个点,对于每个点,(50,90)会被增加或者投票,其他单元也有可能被投票,这样到了最后,(50, 90)会得到最大投票。如果你搜索收集器找最大投票,你会得到(50, 90)。也就是说,在这个图片里距离远点50有一个直线,角度是90度。


    这就是霍夫线变换。很简单,你可以自己用Numpy实现,下面的图片展示了收集器。两点表示他们是图像中可能的直线。


    OpenCV里的霍夫变换

    在OpenCV里,上面的过程被封装在了函数cv2.HoughLines()里。它返回数组(ρ,θ). ρ的单位是像素,θ的单位是弧度。第一个参数是图像,应该是个二元图像。所以可以用canny边缘检测法或者使用阈值然后再做霍夫变换。第二个和第三个参数是ρ和θ的准确度。第四个参数是阈值,是它认为是个直线的最小的票数。记住,投票数依赖线上的点数,所以它表示了我们要检测的直线的最小长度。

    import cv2
    import numpy as np

    img = cv2.imread('dave.jpg')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray,50,150,apertureSize = 3)

    lines = cv2.HoughLines(edges,1,np.pi/180,200)
    for rho,theta in lines[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))

        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

    cv2.imwrite('houghlines3.jpg',img)

    概率霍夫变换

    在霍夫变换里,你可以看到即便对于一个有两个参数的直线,也要做一堆计算。概率霍夫变换是优化的霍夫变换,它不考虑所有点,只取一个随机的子集点,所以对于检测直线来说更有效,只是我们要减低阈值。


    OpenCV的实现使用cv2.HoughLinesP()。它有两个新参数:

    ·minLineLength - 直线最小长度,小于这个的线段就被忽略了。

    ·maxLineGap - 最大线隙, 如果两根线中间缝隙小于这个就认为是一根直线。

    最好的事情是它直接返回直线的两个端点,在前面的例子里,你只是得到直线的参数,你还得找到左右点,这里,所有事情的简单直接。

    import cv2
    import numpy as np

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

    cv2.imwrite('houghlines5.jpg',img)

    END

    相关文章

      网友评论

          本文标题:OpenCV-Python教程:29.霍夫线变换

          本文链接:https://www.haomeiwen.com/subject/rxgqsttx.html