gpt4 book ai didi

python - 使用 Open CV 从线条中提取消失点

转载 作者:行者123 更新时间:2023-12-02 16:07:21 25 4
gpt4 key购买 nike

我正在 Python 中处理基于 OpenCV 的项目,我必须计算/提取并直观地显示现有线条的消失点。

我的第一个任务是检测线条,使用 Canny 和 HoughLinesP 函数非常容易:

import cv2
import numpy as np

img = cv2.imread('.image.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
edges = cv2.Canny(gray, 500, 460)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 30, maxLineGap=250)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 128), 1)

cv2.imwrite('linesDetected.jpg', img)

enter image description here

但我想计算/推断 消失点在所有线条中,找到(并绘制)它们相互交叉的位置,如下图所示。

我知道我需要添加一个更大的框架来绘制线条的延续,以找到交叉点(消失点),但此时我非常迷茫。

太感谢了!!

vanishing point extraction, visually

最佳答案

而不是概率霍夫变换实现 cv2.HoughTransformP ,如果你使用传统的,cv2.HoughTransform , 线在参数空间 (ρ,Θ) 中表示。参数空间与实际点坐标相关为 ρ=xcosθ+ysinθ 其中 ρ 是原点到直线的垂直距离,θ 是该垂直线与水平轴以逆时针方向测量的角度。

lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
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 + 10000*(-b))
y1 = int(y0 + 10000*(a))
x2 = int(x0 - 10000*(-b))
y2 = int(y0 - 10000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),1)

正如您在下面看到的,消失线的投影已经开始出现。

enter image description here

现在,如果我们使用这个特定图像的参数并跳过已经平行的垂直线,我们可以获得一组更好的消失线。
# fine tune parameters
lines = cv2.HoughLines(edges, 0.7, np.pi/120, 120, min_theta=np.pi/36, max_theta=np.pi-np.pi/36)
for line in lines:
rho,theta = line[0]
# skip near-vertical lines
if abs(theta-np.pi/90) < np.pi/9:
continue
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 10000*(-b))
y1 = int(y0 + 10000*(a))
x2 = int(x0 - 10000*(-b))
y2 = int(y0 - 10000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),1)

enter image description here

在这一步,有多种选择可以找到线的交点,消失点。我将在下面列出其中的一些。
  • 最佳近似:所有这些线都有一个已知的 (ρ,θ),并且(理想情况下)只满足两个 (x,y) 点,我们称左边一个 (x0,y0) 和右边一个 (x1,y1)。如果您使用上述方程创建一个包含所有这些变量的线性系统,ρ=xcosθ+ysinθ,您可以将其写为 ρ_n=[x y][cosθ_n sinθ_n]T。这将问题转化为线性回归,您可以求解最佳 (x,y) 点。您可以根据线的斜率对线进行排序,并为 (x0,y0) 和 (x1,y1) 创建两个线性系统。
  • 繁琐的解决办法:正如其中一条评论中提到的,您可以找到所有线的成对交点,然后根据接近度对它们进行聚类,并根据交点数对聚类进行阈值处理。然后您可以输出两个人口最多的集群的集群均值。
  • 基于图像的简单解决方案:由于您已经有了交叉点的图像,您可以进行一些图像处理来找到这些点。这绝不是一个精确的解决方案,它是作为一个快速和近似的解决方案来练习的。您可以通过使用与线条大小相同的内核进行腐 eclipse 来去除线条。然后你可以通过一个更大的内核膨胀来加强交叉点。然后,如果您使用稍大的内核进行关闭操作,则只会保留最强的交叉点。您可以输出这些 blob 的平均值作为消失点。

  • 下面,您可以看到之前的线条图像,以及运行以下代码后产生的左右 Blob 图像。
    # delete lines
    kernel = np.ones((3,3),np.uint8)
    img2 = cv2.erode(img2,kernel,iterations = 1)
    # strengthen intersections
    kernel = np.ones((9,9),np.uint8)
    img2 = cv2.dilate(img2,kernel,iterations = 1)
    # close remaining blobs
    kernel = np.ones((11,11),np.uint8)
    img2 = cv2.erode(img2,kernel,iterations = 1)
    img2 = cv2.dilate(img2,kernel,iterations = 1)
    cv2.imwrite('points.jpg', img2)

    enter image description here
    enter image description here

    关于python - 使用 Open CV 从线条中提取消失点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57535865/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com