手动实现霍夫直线检测

手动实现霍夫直线检测

参考视频:hough transform(霍夫变换直线检测)
在这里插入图片描述
注意: r r r θ \theta θ不是极坐标,这里一根直线只有一组 r r r θ \theta θ

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors

np.random.seed(777)
np.set_printoptions(precision=3, suppress=True)
np.set_printoptions(formatter={'float': '{: 0.3f}'.format})

def fake_image():
    image = np.zeros([100, 100, 1], dtype=np.uint8)
    rs = []
    thetas = []
    for _ in range(3):
        theta = np.random.uniform(0, np.pi/2)
        r = np.random.randint(30, 70)
        rs.append(r)
        thetas.append(np.rad2deg(theta))
        if theta > np.pi/4:
            x = np.arange(100)
            y = np.uint8((r - x*np.cos(theta)) / np.sin(theta))
            print(list(zip(x, y)))
            valid_y = y[(y >= 0) & (y < 100)]
            valid_x = x[(y >= 0) & (y < 100)]
        else:
            y = np.arange(100)
            x = np.uint8((r - y*np.sin(theta) / np.cos(theta)))
            valid_x = x[(x >= 0) & (x < 100)]
            valid_y = y[(x >= 0) & (x < 100)]
        for i, j in zip(valid_x, valid_y):
            image[j, i, 0] = 255
    return image, np.array(rs), np.array(thetas)

def houghline(image, thetas, rhos, r_max):
    cos_t = np.cos(thetas)
    sin_t = np.sin(thetas)
    
    y_idx, x_idx, _ = np.nonzero(image)
    
    vote = np.zeros([len(rhos), len(thetas)])
    
    for i in range(len(x_idx)):
        x = x_idx[i]
        y = y_idx[i]
        for j in range(len(thetas)):
            r = x*cos_t[j] + y*sin_t[j] + r_max
            vote[int(r), j] += 1
    
    return vote

def get_line(vote, thetas, rhos):
    row, col = np.unravel_index(np.argmax(vote, axis=None), vote.shape)
    max_value = vote[row, col]
    thr = 0.5 * max_value
    ii, jj = np.nonzero(vote > thr)
    
    # NMS
    cands = list(zip(ii, jj, vote[ii, jj]))
    cands = sorted(cands, key=lambda x: x[2])
    final_cands = []
    while cands:
        final_cands.append(cands.pop())
        temp_cands = []
        for i in range(len(cands)):
            if abs(cands[i][0] - final_cands[-1][0]) > 2 or abs(cands[i][1] - final_cands[-1][1]) > 2:
                temp_cands.append(cands[i])

        cands = temp_cands
    
    pred_rs = []
    pred_thetas = []
    for cand in final_cands:
        theta = thetas[cand[1]]
        rho = rhos[cand[0]]
        pred_rs.append(rho)
        pred_thetas.append(np.rad2deg(theta))
    return np.array(pred_rs), np.array(pred_thetas)
    
    
        
    
if __name__ == "__main__":
    image, target_rs, target_thetas = fake_image()
    
    thetas = np.deg2rad(np.arange(0, 180))
    height, width = image.shape[:2]
    r_max = np.ceil(np.linalg.norm([height, width]))
    rhos = np.linspace(-r_max, r_max, int(r_max*2) + 1)
    
    vote = houghline(image, thetas, rhos, r_max)
    
    pred_rs, pred_thetas = get_line(vote, thetas, rhos)
    
    print(f"target rs: ", target_rs, "target thetas: ", target_thetas)
    print(f"pred rs: ", pred_rs, "pred thetas: ", pred_thetas)
    
    fig, axes = plt.subplots(1, 2, figsize=(8, 8))
    axes[0].imshow(image, cmap=plt.cm.gray)
    axes[0].set_title('Input image')
    pcm = axes[1].imshow(vote, extent=[0, vote.shape[1], vote.shape[0]//2, -vote.shape[0]//2])
    fig.colorbar(pcm, ax=axes[1])
    axes[1].set_title('Hough transform')
    axes[1].set_xlabel('Angle (degree)')
    axes[1].set_ylabel('Distance (pixel)')
    plt.tight_layout()
    plt.show()

"""
target rs:  [68 37 69] target thetas:  [ 13.740  5.583  22.325]
pred rs:  [ 65.000  36.000  63.000] pred thetas:  [ 14.000  6.000  22.000]
"""


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咬着棒棒糖闯天下

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

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

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

打赏作者

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

抵扣说明:

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

余额充值