在OpenCV中测量给定角度处轮廓的宽度

4

在OpenCV中给定一个轮廓,可以通过使用cv2.boundingRect(contour)来提取宽度和高度。这将返回一个边界矩形的宽度和高度,如左图所示。

给定角度,是否可能提取旋转边界矩形的宽度/高度,如右图所示?

Contour illustration

我想测量移动物体的长度,但我需要在运动方向上测量长度,这有时可能与水平线成45度角。
我知道有一种方法可以获取旋转的边界矩形,使用cv2.minAreaRect和cv2.boxPoints,但我需要的旋转不总是匹配最小区域矩形,因此我需要能够以某种方式指定角度。
我只需要旋转宽度和高度值,如果这样更容易的话,我并不需要旋转轮廓。

2
旋转对象并再次应用边界框,使用getRotationMatrix2D函数。 - ldgorman
为什么不呢?如果你拥有一个角度,那么你可以画出两条垂直的线。计算每个点到每条直线的距离,然后计算 max_dist - min_dict,你就能得到宽和高。 - Kinght 金
2个回答

3
作为我的评论:为什么不呢。假设你有一个角度,那么你可以画出两条垂直的线。计算每个点到每条线的距离,然后计算最大距离和最小距离之差,你就能得到宽度和高度。

我的母语是中文,而且我不擅长英语写作。所以我把它转化成了代码:

#!/usr/bin/python3
# 2017.12.13 22:50:16 CST
# 2017.12.14 00:13:41 CST
import numpy as np

def calcPointsWH(pts, theta=0):
    # 计算离散点在特定角度的长宽
    # Measuring width of points at given angle
    th = theta * np.pi /180
    e = np.array([[np.cos(th), np.sin(th)]]).T
    es = np.array([
    [np.cos(th), np.sin(th)],
    [np.sin(th), np.cos(th)],
    ]).T
    dists = np.dot(pts,es)
    wh = dists.max(axis=0) - dists.min(axis=0)
    print("==> theta: {}\n{}".format(theta, wh))

请使用这颗钻石进行测试:

enter image description here


pts = np.array([[100, 200],[200,  26],[300, 200],[200, 373]], np.int32)
for theta in range(0,91, 30):
    calcPointsWH(pts, theta)


==> theta: 0
[ 200.  347.]
==> theta: 30
[ 173.60254038  300.51081511]
==> theta: 60
[ 300.51081511  173.60254038]
==> theta: 90
[ 347.  200.]

现在是 2017.12.14 00:20:55 CST,晚安。


谢谢,这似乎正是我想要的。我并不打算让你真的做所有的工作,但我非常感激! :) - Erlend D.

1
使用
cv2.minAreaRect(cnt)

这里您可以找到这里完整的示例和解释。
编辑:实际上,您需要的是minAreaRect,从一个定向矩形中取宽度和高度有什么问题?

谢谢,但除非我想错了,最小包围矩形不总是朝着移动方向“面对”。例如,在@Silencer的钻石案例中:最小包围矩形将保持不变,但移动方向不会。 - Erlend D.
1
这听起来有点奇怪,你能加上一些图像示例来说明你代码中正在发生的事情吗?(或许还可以加上一小段代码片段) - Moia
考虑这个以45度角移动的100x100正方形:https://i.imgur.com/PvHyHL6.png cv2.minAreaRect将返回一个看起来与正方形完全相同的矩形,对吗?这将给我一个宽度为100,高度为100。但由于正方形以45度角移动,我想要在45度角处的宽度,大约是141。因此,minAreaRect不起作用(除非我们旋转矩形,这可能是一个解决办法,但然后我需要帮助实际旋转 :)) - Erlend D.
这与你所问的完全无关。那个正方形的角度为0度,无论方向如何。Silencer的菱形具有45°,加上kPI°,完全取决于您的参考系统。而一个旋转45°的100x100像素正方形的宽度仍然是100。 - Moia
抱歉,我的问题显然没有表达清楚。正如我在问题中试图说明的那样,形状实际上永远不会被旋转,但是移动方向可能会改变。我需要在运动方向上的宽度。Silencer的解决方案似乎正好计算了这一点。 - Erlend D.
只需测量从物体中心到新位置处物体中心的线长即可,甚至不需要知道角度。 - Moia

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