python机器视觉实用工具集NO.18——查找手绘棋盘直线交叉点

发布时间:2024年01月05日

前言

在计算机视觉中,检测图像中的直线交叉点是一个常见的任务。本篇博客将介绍一种使用Python的机器视觉实用工具集来查找手绘棋盘直线交叉点的方法。这个工具集使用了OpenCV库和NumPy库。
在这里插入图片描述

在这里插入图片描述
原图如下:
在这里插入图片描述

准备条件

在开始之前,我们需要准备以下条件:

  1. 安装Python环境以及OpenCV库和NumPy库。
  2. 一张包含手绘棋盘的图像。

步骤

下面是查找手绘棋盘直线交叉点的步骤:

1. 导入所需的库:


import cv2
import numpy as np

2. 定义合并直线的函数:

def merge_lines(lines, e0, e1):
    merged_lines = []
    # 遍历每条直线
    for i, line in enumerate(lines):
        if len(merged_lines) == 0:
            merged_lines.append(line)
        else:
            merged = False
            # 遍历已合并的直线
            for i, merged_line in enumerate(merged_lines):
                theta = line[1]
                distan= line[0]
                mtheta = merged_line[1]
                mdistan= merged_line[0]
                dtheta=abs(np.sin(theta))-abs(np.sin(mtheta))
                ds=abs(abs(mdistan)-abs(distan))
                # 判断两条直线是否可合并
                if dtheta < e0 and ds < e1 :
                    merged_lines[i] = [(line[0] + merged_line[0]) / 2, (line[1] + merged_line[1]) / 2]
                    merged = True
                    break
            # 如果不能合并,则将直线添加到已合并的直线列表中
            if not merged:
                merged_lines.append(line)
    return merged_lines

3. 定义延长直线的函数:

def extend_lines(lines, img_shape):
    extended_lines = []
    # 遍历每条直线
    for line in lines:
        rho = line[0]
        theta = line[1]
        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))
        extended_lines.append([(x1, y1), (x2, y2)])
    return extended_lines

4. 定义查找直线交叉点的函数:

def find_intersections(lines):
    intersections = []
    # 遍历每条直线的组合
    for i in range(len(lines)):
        for j in range(i+1, len(lines)):
            line1 = lines[i]
            line2 = lines[j]
            x1, y1 = line1[0]
            x2, y2 = line1[1]
            x3, y3 = line2[0]
            x4, y4 = line2[1]
            denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
            # 判断两条直线是否相交
            if denominator != 0:
                x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denominator
                y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denominator
                intersections.append((int(x), int(y)))
    return intersections

5. 定义绘制直线的函数:

def draw_lines(img, lines):
    for line in lines:
        cv2.line(img, line[0], line[1], (0, 0, 255), 2)

6. 定义绘制直线交叉点的函数:

def draw_intersections(img, intersections):
    for intersection in intersections:
        cv2.circle(img, intersection, 5, (0, 255, 0), -1)

7. 定义检测直线和交叉点的函数:

def detect_lines(img, e0, e1, rho, threshold):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)
    lines = cv2.HoughLines(edges, rho, np.pi/180, threshold)
    lines = lines[:, 0, :]
    merged_lines = merge_lines(lines, e0, e1)
    extended_lines = extend_lines(merged_lines, img.shape)
    intersections = find_intersections(extended_lines)
    draw_lines(img, extended_lines)
    draw_intersections(img, intersections)
    return img

8. 设置参数并读取图像进行检测:

e0 = 10 # 角度误差阈值
e1 = 10 # 距离误差阈值
rho = 2 # 像素偏差
threshold = 260 # 投票数阈值

img = cv2.imread('jing.png')
result = detect_lines(img, np.sin(e0/180*np.pi/2), e1, rho, threshold)

cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

总结

本篇博客介绍了使用Python的机器视觉实用工具集来查找手绘棋盘直线交叉点的方法。通过利用OpenCV库和NumPy库,我们可以很轻松地实现直线合并、直线延长和直线交叉点查找操作。这个工具集可以帮助我们在图像处理中更好地处理直线交叉点的检测任务。
本站源码链接
或入下方公众号获取:

文章来源:https://blog.csdn.net/kanbide/article/details/135405018
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。