zoukankan      html  css  js  c++  java
  • OpenCV-Python:霍夫变换

    霍夫变换常用来在图像中提取直线和圆等几何形状。如下图:

    我们下面来看看如何使用霍夫变换来检测直线。一条直线可以用数学表达式 y = mx + 或者 ρ = xcosθ + y sinθ表示(极坐标)

    简单说明一下:

    ρ 是从原点到直线的垂直距离,θ是直线的垂线与横轴顺时针方向的夹角,如下图所示:

    首先创建一个2D数组(累加器),初始化累加器,所有的值都为0。行表示 ρ,列表示 θ。这个数组的大小决定了最后结果的准确性。如果你希望角度精确到1°,你就需要180列。对于 ρ,最大值为图片对角线距离。

    想象一下我们有一个大小为100x100的直线位于图像中央。取直线上的第一个点,我们知道此处的(x,y)值,把x和y带入公式:ρ = xcosθ + y sinθ,然后遍历 θ 的取值0, 1, 2, 3,...,180.分别求出对应的 ρ 值,这样我们就得到了一系列(ρ,θ)的数值对,如果这个数值对在累加器中也存在相应的位置,就在这个位置上加 1。由于同一条直线上的点必然会有同样的(ρ,θ)。所以现在累加器中的(50,90)=1。现在取直线上的第二个点。重复上边的过程。更新累加器中的值。现在累加器中(50,90)的值为 2。你每次做的就是更新累加器中的值。对直线上的每个点都执行上边的操作,每次操作完成之后,累加器中的值就加 1,但其他地方有时会加 1, 有时不会。按照这种方式下去,到最后累加器中(50,90)的值肯定是最大的。如果你搜索累加器中的最大值,并找到其位置(50,90),这就说明图像中有一条直线,这条直线到原点的距离为 50,它的垂线与横轴的夹角为 90 度。

    OpenCV中首先计算(r,θ) 累加数,累加数超过一定值后就认为在同一直线上(有一个阈值)。

    霍夫直线变换

    import cv2
    import numpy as np
    # 1.加载图片,转为二值图
    img = cv2.imread('shapes.jpg')
    drawing = np.zeros(img.shape[:], dtype=np.uint8)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 150)
    # 2.霍夫直线变换
    lines = cv2.HoughLines(edges, 0.8, np.pi / 180, 90)

    函数中:

    • 参数1:要检测的二值图(一般是阈值分割或边缘检测后的图)
    • 参数2:距离 ρ 的精度,值越大,考虑越多的线
    • 参数3:角度 θ 的精度,值越小,考虑越多的线
    • 参数4:累加数阈值,值越小,考虑越多的线
    # 3.将检测的线画出来(注意是极坐标噢)
    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(drawing, (x1, y1), (x2, y2), (0, 0, 255))

    统计概率霍夫直线变换

    前面的方法又称为标准霍夫变换,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线,并不知道原图中直线的端点。所以提出了概率霍夫直线变换(Probabilistic Hough Transform),是一种改进的霍夫变换:

    drawing = np.zeros(img.shape[:], dtype=np.uint8)
    # 统计概率霍夫线变换
    lines = cv2.HoughLinesP(edges, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10)
    
    # 将检测的线画出来
    for line in lines: x1, y1, x2, y2 = line[0] cv2.line(drawing, (x1, y1), (x2, y2), (0, 255, 0), 1, lineType = cv2.LINE_AA) cv2.imwrite('houghlines4.jpg', drawing)

    参数:

    • minLineLength:最短长度阈值,比这个长度短的线会被排除
    • maxLineGap:同一直线两点之间的最大距离

    cv2.LINE_AA:抗锯齿线型

    霍夫圆变换

    霍夫圆变换跟直线变换类似,只不过线是用(r,θ),圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法去减少计算量

    drawing = np.zeros(img.shape[:], dtype=np.uint8)
    # 霍夫圆变换
    circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param2=30)
    circles = np.int0(np.around(circles))
    
    # 将检测的圆画出来
    for i in circles[0, :]:
        cv2.circle(drawing, (i[0], i[1]), i[2], (0, 255, 0), 2)  # 画出外圆
        cv2.circle(drawing, (i[0], i[1]), 2, (0, 0, 255), 3)  # 画出圆心
    cv2.imwrite('HoughCircles.jpg', drawing)
    • 参数2:变换方法,一般使用霍夫梯度法,详情:HoughModes
    • 参数3 dp=1:表示霍夫梯度法中累加器图像的分辨率与原图一致
    • 参数4:两个不同圆圆心的最短距离
    • 参数5:param2跟霍夫直线变换中的累加数阈值一样

  • 相关阅读:
    Visual Studio Error C4335 检测到Mac文件格式:请将源文件转换为DOS格式或UNIX格式
    Visual Studio 2017在编译时出现错误E2512:功能测试宏的参数必须是简单标识符
    PCL 注意事项
    Realsense D435i Winodws和Linux开发环境配置
    Hybrid Astar
    Git 分支管理
    Visula Studio 安装 Visual Assist
    Typora 设置字体颜色
    Mac上使用Charles+Chrome
    linux Kill 命令
  • 原文地址:https://www.cnblogs.com/gezhuangzhuang/p/10737499.html
Copyright © 2011-2022 走看看