在两个给定点之间绘制线条(OpenCV,Python)

8

我已经苦恼了一个小时,仍无法解决这个问题...

我有一张带有矩形的图片:

rect

这是我编写的查找角点的代码:

import cv2
import numpy as np


img = cv2.imread('rect.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

points = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10)
points = np.int0(points)

for point in points:
    x, y = point.ravel()
    cv2.circle(img, (x, y), 3, (0, 255, 0), -1)

print(points[0])
print(points[1])
print(points[2])
print(points[3])

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.imwrite('rect.png', img)

这是结果:

rst

如您所见,它运行得很完美。我想要的是在上/下点(x1,x2-x3,x4)沿着一条直线画出来。

到目前为止,我制作的内容如下...

cv2.line(img, (points[0]), (points[1]), (0, 255, 0), thickness=3, lineType=8)

cv2.imshow('img', img)
cv2.waitKey(0)

但它不起作用。

有什么想法吗?

结果应该像这样:

out

这两行必须沿着点的坐标传递。例如,print(points[0]) 的输出如下:

[[561 168]]
[[155 168]]
[[561  53]]
[[155  53]] 

谢谢


请尝试执行以下代码:cv2.line(img, points[0].ravel(), points[1].ravel(), (0, 255, 0), thickness=3, lineType=8) - grovina
尝试执行 cv2.line(img,(561,168),(155,168),(0,255,0),3)。如果能正常工作,可能是你传递的点参数有误。 - api55
是的,这样可以工作,但点必须保留在变量中。我不能手动给它们。此外,线必须沿着这个轴,而不仅仅是连接两个点。 - BlueTrack
你尝试过points[0][0]吗? - api55
我使用了(points[0][0][0],points[0][0][1]),但ravel函数在边缘周围生成了某种随机行走,并且每次运行代码时points[0]-[3]都不同。 - Eamonn Kenny
显示剩余3条评论
2个回答

7

首先,让我们看一下您的打印输出。它显示points[0]为

[[561 168]]

但是OpenCV中的点类似于:
(561, 168)

你可以像你之前对圆做的那样拆开它,然后再处理元组。
x, y = points[0].ravel()
(x,y)

或者你可以使用

tuple(points[0].ravel())

或者

tuple(points[0][0])

编辑

如果你想要让一个元素从屏幕的一侧移动到另一侧,这也很容易实现。你需要做的是将其中一个点的 x 值设为 0,而另一个点的列值设为相应的值。我认为最简单的方法是像这样做:

y = points[0].ravel()[1]
cv2.line(img, (0, y), (img.shape[1], y), (0, 255, 0), thickness=3, lineType=8)

需要注意两点:

  1. 如您所见,我并没有关注第二点,因为我假设它将在同一水平线上,如果不是,它会变得有些复杂,但并不难。

  2. img.shape返回一个元组,其中包含图像的详细信息,格式为(rows, cols, channels),由于我们需要cols,所以我们取了[1]。


解释得非常好。从这个角度看,可以将Silencer的答案结合起来使得代码行变长(不仅限于这两个给定的点),或者您的答案有一个不同的方法吗? - BlueTrack
哦,我以为你想要从点到点的,给我一秒钟,我来修复它。 - api55
没问题,从一点到另一点都是正确的。只是问一下...也许可以在第一个回答后添加第二个(长行回答),不要编辑第一个。谢谢。 - BlueTrack
1
@BlueTrack 抱歉,这是没有括号的形状 :/ 它不是一个函数,我已经编辑了答案。 - api55

6
points = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10)
points = np.int0(points).reshape(-1,2)

for point in points:
    x, y = point.ravel()
    cv2.circle(img, (x, y), 3, (0, 255, 0), -1)


y1 = min(points[:,1])
y2 = max(points[:,1])

## small and big enough 
cv2.line(img, (0, y1), (1000, y1), (0, 255, 0), thickness=3, lineType=8)
cv2.line(img, (0, y2), (1000, y2), (0, 255, 0), thickness=3, lineType=8)

女士们先生们,我们有一个获胜者。这个可以直接完成工作。你能像api55一样尝试解释一下吗?谢谢。 - BlueTrack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接