• 【OpenCV-Python】教程:3-13 Hough直线变换


    OpenCV Python Hough直线变换

    【目标】

    • 理解Hough变换的概念
    • 学会使用Hough变换检测直线
    • cv2.HoughLines(), cv2.HoughLinesP()

    【理论】

    Hough 变换是一个非常有用的技术,可以检测任何形状,只要那个形状可以通过数学方程表示出来,即使检测的形状断裂或者轻微变形。

    直线方程为:

    y = m x + c y=mx+c y=mx+c

    或者极坐标参数表示形式:

    ρ = x ∗ cos ⁡ θ + y ∗ sin ⁡ θ \rho=x*\cos\theta+y*\sin\theta ρ=xcosθ+ysinθ

    其中, ρ \rho ρ是原点到直线的垂直距离, θ \theta θ是垂直线与逆时针测量的水平轴形成的角度。

    任何直线都可以用 ( ρ , θ ) (\rho,\theta) (ρ,θ) 来表示。Hough变换是如何检测直线的呢?首先它创建一个2D数组或累加器,并将其初始设置为 0,设行表示 ρ \rho ρ,列表示 θ \theta θ。数组的大小取决于精度,假设角度的精度为1度,则需要180列。对于 ρ \rho ρ,可能的最大距离是图像的对角线长度。因此,以一个像素的精度计算,行数可以是图像的对角线长度。

    假设一个 100 ∗ 100 100*100 100100的图像,在图像中间有一个水平线,取这条线的第一个点 ( x , y ) (x,y) (x,y),计算 ( ρ , θ ) (\rho,\theta) (ρ,θ),对于每一个 ( ρ , θ ) (\rho,\theta) (ρ,θ) ,如果 ( x , y ) (x,y) (x,y)能找到对应的 ( ρ , θ ) (\rho,\theta) (ρ,θ),增加递增器的值。循环往复,对图像中所有的点都进行查找搜寻,不停的对每个 ( ρ , θ ) (\rho,\theta) (ρ,θ) 进行投票,假设在 ( 50 , 90 ) (50,90) (50,90)投票最多,请看下面的动画。

    houghlinesdemo.gif
    Image Courtesy: Amos Storkey

    houghlines2.jpg

    概率 Hough 变换

    在Hough变换中,尽管一条直线只有两个参数,但是还需要很多计算量,概率 Hough 变换是其中的一种优化,它不会将所有的点都考虑进去,相反,它会考虑一些能够充分进行直线检测的随机点集。我们必须降低 threshold,流程图如下:

    houghlines4.pngimage
    Image Courtesy : Franck Bettinger's home page

    OpenCV 的实现基于 Robust Detection of Lines Using the Progressive Probabilistic Hough Transform by Matas, J. and Galambos, C. and Kittler, J.V. [166]. 函数为 cv2.HoughLinesP()

    【代码】

    在这里插入图片描述

    import cv2
    import numpy as np
    
    # 读入图像
    img = cv2.imread('assets/sudoku.png')
    
    # 灰度化
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    # 边缘检测
    edges = cv2.Canny(gray, threshold1=50, threshold2=150, apertureSize = 3)
    
    # 直线检测
    lines = cv2.HoughLines(edges, rho=1, theta=np.pi/180, threshold=150 )
    
    
    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))
        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
    
    cv2.imshow("line", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • cv2.HoughLinesP

    在这里插入图片描述

    import cv2
    import numpy as np
    
    # 读入图像
    img = cv2.imread('assets/sudoku.png')
    
    # 灰度化
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 边缘检测
    edges = cv2.Canny(gray, threshold1=50, threshold2=150, apertureSize=3)
    
    # 直线检测
    lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=100, maxLineGap=10)
    
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(img, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=2)
    
    cv2.imshow("line", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    【接口】

    • HoughLines
    cv.HoughLines(	image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]	) ->	lines
    
    • 1

    用标准的Hough变换找二值图像中的直线

    • image: 8位单通道二值图像,图像可能被篡改
    • lines: 输出的直线 vector/list,每个直线是 ( ρ , θ , v o t e s ) (\rho, \theta, votes) (ρ,θ,votes) 表示, ρ \rho ρ是图像原点(左上角)到直线的距离, θ \theta θ是旋转的弧度,(0~vertical_line, pi/2 ~ horizontal line), v o t e s votes votes是投票值。
    • rho: 距离精度,单位像素
    • theta: 角度精度,单位弧度
    • threshold: 累积阈值,主要用于对投票值进行限制,只返 v o t e s votes votes 大于该值的 line
    • srn: 多尺度的Hough变换,是 rho 的除数,如果srn为0和stn=0时,则使用经典Hough变换,否则,这两个参数都应为正值,
    • stn: 多尺度的Hough变换,是 theta 的除数,
    • min_theta: 对于标准和多尺度的Hough变换,检测线条的最小角度,必须介于 0 ~ max_theta 之间。
    • max_theta: 对于标准和多尺度的Hough变换,检测线条的最大角度,必须介于min_theta ~ CV_PI之间。
    • HoughLinesP
    cv.HoughLinesP(	image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]	) ->	lines
    
    • 1

    利用概率 Hough 变换在二值图中找直线

    • image: 8位单通道二值图像,图像可能被篡改
    • lines: 输出的直线 vector/list,每个直线是 ( x 1 , y 1 , x 2 , y 2 ) (x1,y1, x2, y2) (x1,y1,x2,y2), 他们分别是线段的端点
    • rho: 距离精度,单位像素
    • theta: 角度精度,单位弧度
    • threshold: 累积阈值,主要用于对投票值进行限制,只返 v o t e s votes votes 大于该值的 line
    • minLineLength: 最小的直线长度,小于该长度的被拒绝掉。
    • maxLineGap: 允许同一条直线上连接两点之间最大的间隔。

    【参考】

    1. OpenCV官方文档
    2. Hough Transform on Wikipedia
    3. Hough Transform
  • 相关阅读:
    【数学模型】基于Matlab模拟疫情 SEIRS模型
    系统架构设计:15 论软件架构的生命周期
    dubbo(四)异常处理
    uniapp条件判断app,H5,微信小程序端
    linux文件压缩、解压缩以及归档
    Java中获取年份月份的方法
    JS实现图片懒加载
    我只说一遍!这几个程序员都在用的接单平台还不赶快收藏好!!!
    CV每日论文--2024.6.26
    [Spring Boot 6]企业级开发
  • 原文地址:https://blog.csdn.net/zhoujinwang/article/details/128152277