【千律】OpenCV基础:Hough直线检测

环境:Python3.8 和 OpenCV

内容:Hough直线检测

Hough直线检测将直角坐标系中的直线检测转换为极坐标系中的点检测 


实现步骤:
1.读取灰度图I,并获取其边缘图像E
2.设置长度分辨率dr和角度分辨率dt,以及直线存在的点数阈值thresh
3.指定转换后的极坐标空间坐标轴的取值范围,分别记为[rmin, rmax],[tmin, tmax],将转换后的二维空间划分为多个bin,设置计数器N(r,θ),用于记录落入bin中的像素点
4.对边缘图像E的每个边缘点,其坐标记为(x,y),计算 r = xcosθ + ysinθ 对应的曲线在极坐标空间中所经过的点,所经过的点对应的N(r,θ) + 1
5.如果某个bin的点数超出阈值thresh,则认为存在对应的直线,取出该点(r,θ),求出直线方程。

实现方式1:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()



if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 边缘检测
    img_edge = cv.Canny(img_gray, 10, 300)

    # 霍夫直线检测
    lines = cv.HoughLines(img_edge, 2, np.pi / 180, 180)

    # 循环绘制直线
    length = img_gray.shape[0] + img_gray.shape[1]
    for (rho, theta) in lines.squeeze():

        # 计算直线方程的常数
        const_a = np.cos(theta)
        const_b = np.sin(theta)

        # 获取直线的两点
        x1 = int(rho * const_a - length * const_b)
        y1 = int(rho * const_b + length * const_a)
        x2 = int(rho * const_a + length * const_b)
        y2 = int(rho * const_b - length * const_a)

        # 绘制直线
        cv.line(img_desk, (x1, y1), (x2, y2), (0, 0, 255), 2)

    image_show(img_desk)

实现方式2:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()


if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 边缘检测
    img_edge = cv.Canny(img_gray, 10, 300)

    # 霍夫直线检测
    lines = cv.HoughLinesP(img_edge, 3, np.pi / 180, 140, minLineLength=30, maxLineGap=25)

    # 循环绘制直线
    for (x1, y1, x2, y2) in lines.squeeze():
        cv.line(img_desk, (x1, y1), (x2, y2), (0, 0, 255), 2)

    image_show(img_desk)

 实现方式3:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()


if __name__ == '__main__':

    # 读取灰度图
    img_desk = cv.imread('desk.png')

    # 转换为灰度图
    img_gray = cv.cvtColor(img_desk, cv.COLOR_BGR2GRAY)

    # 边缘检测
    img_edge = cv.Canny(img_gray, 10, 300)

    # 参数设置
    dr = 2              # 长度分辨率
    dt = np.pi / 180    # 角度分辨率
    thresh = 180        # 点数阈值

    # 设置极坐标空间的范围
    rmin, rmax = 0, np.sqrt(img_edge.shape[0] ** 2 + img_edge.shape[1] ** 2)
    tmin, tmax = 0, 2 * np.pi

    # 设置网格个数
    bin_r = int((rmax - rmin) / dr) + 1
    bin_t = int((tmax - tmin) / dt) + 1
    N = np.zeros((bin_r, bin_t), np.int32)

    # 获取各边缘点的坐标
    index_y, index_x = np.where(img_edge == 255)

    # 循环计算直线,累加计数器
    thetas = np.arange(tmin, tmax, dt)
    for (x, y) in zip(index_x, index_y):

        # 获取极坐标空间中各点位置(bin)
        rhos = abs(x * np.cos(thetas) + y * np.sin(thetas))
        ms = np.round(rhos / dr).astype(np.int32)
        ns = np.round(thetas / dt).astype(np.int32)

        # 累加计数器
        for (rho, theta) in zip(ms, ns):
            N[rho, theta] += 1

    # 显示极坐标空间曲线结果
    plt.imshow(N, cmap='jet')
    plt.show()

    # 获取超过阈值点数的位置
    rs, ts = np.where(N > thresh)
    rs = rs * dr
    ts = ts * dt

    # 循环绘制直线
    length = img_gray.shape[0] + img_gray.shape[1]
    for (rho, theta) in zip(rs, ts):
        # 计算直线方程的常数
        const_a = np.cos(theta)
        const_b = np.sin(theta)

        # 获取直线的两点
        x1 = int(rho * const_a - length * const_b)
        y1 = int(rho * const_b + length * const_a)
        x2 = int(rho * const_a + length * const_b)
        y2 = int(rho * const_b - length * const_a)

        # 绘制直线
        cv.line(img_desk, (x1, y1), (x2, y2), (0, 0, 255), 2)

    image_show(img_desk)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿飞_Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值