如何在缩放和旋转后重新计算点的cooredinates?

时间:2018-03-04 02:02:03

标签: python image-processing computer-vision draw cv2

我在图像中有6个点的坐标

(170.01954650878906, 216.98866271972656)
(201.3812255859375, 109.42137145996094)
(115.70114135742188, 210.4272918701172)
(45.42426300048828, 97.89037322998047)
(167.0367889404297, 208.9329833984375)
(70.13690185546875, 140.90538024902344)

我有一个点作为中心[89.2458, 121.0896]。我试图用4个旋转度(从0,90,-90,180)和6个比例因子(0.5,0.75,1,1.10,1.25,1.35,1.5)重新计算python中点的位置。
我的问题是如何旋转和缩放相对于中心点的上述点并获得这6个点的新坐标?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:5)

数学

数学方法是将此数据表示为从中心到图像点的矢量,将这些矢量转换为原点,应用变换并将它们重新定位在中心点周围。让我们看看它是如何工作的。

表示为向量

我们可以在网格中显示这些向量,这将产生以下图像

Representation of the given points as vectors around the center point

此图像提供了查看这些点的好方法,因此我们可以看到我们的行为以可视方式发生。中心点在所有箭头的开头标有一个点,每个箭头的末尾是问题中提供的一个点的位置。

矢量可以看作是点坐标值的列表,所以

my_vector = [point[0], point[1]]

可以是python中矢量的表示,它只保存一个点的坐标,因此问题中的格式可以按原样使用!请注意,在我的答案中,我将使用位置0作为x坐标,1作为y坐标。

我只添加了这种表示作为视觉辅助,我们可以将任意两个点视为一个向量,不需要计算,这只是查看这些点的不同方式。

翻译成原点

第一次计算发生在这里。我们需要将所有这些向量转换为原点。我们可以通过从所有其他点减去中心点的位置来轻松完成此操作(例如,可以在一个简单的循环中完成):

point_origin_x = point[0] - center_point[0] # Xvalue point - Xvalue center
point_origin_y = point[1] - center_point[1] # Yvalue point - Yvalue center

现在可以围绕原点旋转结果点并相对于原点进行缩放。新点(作为向量)看起来像这样:

The same vectors as above, but translated around the origin

在这张图片中,我故意不改变音阶,因此很明显这些矢量(箭头)的大小和方向完全相同,只是转移到(0,0)左右。

为什么起源

那么为什么要将这些点转换为原点呢?好吧,旋转和缩放动作很容易(在数学上)围绕原点进行,而不是在其他点周围很容易。

此外,从现在开始,我将只在这些图像中包含第1,第2和第4点以节省一些空间。

缩放原点

缩放操作在原点周围很容易。只需将点的坐标乘以缩放系数:

scaled_point_x = point[0] * scaling_factor
scaled_point_y = point[1] * scaling_factor

以可视方式,看起来像这样(全部缩放1.5):

Scaled vectors and original vectors

蓝色箭头是原始矢量,红色箭头是缩放矢量。

旋转

现在轮换。这有点困难,因为旋转通常用这个向量的矩阵乘法来描述。

要乘以的矩阵如下

rotation matrix

(来自wikipedia: Rotation Matrix

因此,如果V是向量而不是我们需要执行V_r = R(t) * V来获得旋转向量V_r。此旋转始终为逆时针!为了顺时针旋转,我们只需要使用R(-t)

因为在问题中只需要90°的倍数,矩阵变得几乎无足轻重。对于逆时针旋转90°,矩阵为:

Rotation matrix for 90° counterclockwise

基本上是代码:

rotated_point_x = -point[1]    # new x is negative of old y
rotated_point_y = point[0]     # new y is old x

同样,这可以通过视觉方式很好地展示:

rotation 90° counterclockwise

我匹配了矢量的颜色。

顺时针旋转90°将

rotated_counter_point_x = point[1]    # x is old y
rotated_counter_point_y = -point[0]   # y is negative of old x

180°的旋转将采用负坐标,或者您可以按-1的比例缩放,这基本上是相同的。

作为这些操作的最后一点,我可以补充说,您可以根据需要在序列中进行缩放和/或旋转,以获得所需的结果。

转换回中心点

在缩放动作和/或旋转之后,唯一剩下的就是将矢量重新转换到中心点。

retranslated_point_x = new_point[0] + center_point_x
retranslated_point_y = new_point[1] + center_point_y

一切都已完成。

回顾一下

所以回顾这篇长篇文章:

  1. 从图像点的坐标
  2. 中减去中心点的坐标
  3. 通过简单乘以坐标
  4. 按比例缩放
  5. 使用矩阵乘法的思想来考虑旋转(你可以在Google或维基百科上轻松找到这些东西)。
  6. 将中心点的坐标添加到图像点的新坐标
  7. 我现在意识到我可以刚刚给出这个回顾,但是现在这篇文章中至少有一些视觉辅助和轻微的数学背景,这也很好。我真的相信这些问题应该从数学角度来看,数学描述可以帮助很多。