旋转图像后计算属于矩形角的像素
Calculate pixels belonging to corners of rectangle after rotating image
我看到了一些与此主题相关的问题,但即使关注了这些问题,我也无法得到我想要的结果,所以我假设我的数学有问题。这是场景。
我有一张图片必须旋转 90 度。同时,我得到了在某个对象上绘制的矩形角的坐标(x_min、y_min)和(x_max、y_max)在图像中。让我们以下图为例,这里使用的矩形由 (4, 196) 和 (145, 269) 定义。
那么,我的目标是旋转图像并对矩形执行相同操作,确保它始终包围目标对象。
首先,我使用 imutils 将图像旋转 90 度(顺时针)。
90_rotated_image = imutils.rotate_bound(original_image, 90)
然后,我正在计算矩形的新坐标。为此,我需要知道 imutils 旋转图像所围绕的点。我尝试了一些组合,包括 (0,0),但这里我假设它是图像本身的中心。
radians = math.radians(90)
h, w, c = original_image.shape
center_x = w/2
center_y = h/2
# Changes to solve the problem. Center of rotated image is now considered.
h_rotated, w_rotated, c = 90_rotated_image.shape
center_x_rotated = w_rotated/2
center_y_rotated = h_rotated/2
x_min_90 = center_x_rotated + math.cos(radians) * (x_min - center_x) - math.sin(radians) * (y_min - center_y)
y_min_90 = center_y_rotated + math.sin(radians) * (x_min - center_x) + math.cos(radians) * (y_min - center_y)
x_max_90 = center_x_rotated + math.cos(radians) * (x_max - center_x) - math.sin(radians) * (y_max - center_y)
y_max_90 = center_y_rotated + math.sin(radians) * (x_max - center_x) + math.cos(radians) * (y_max - center_y)
最后,我在旋转后的图像上绘制新的旋转矩形。
start_point = (x_min_90, y_min_90)
end_point = (x_max_90, y_max_90)
image = cv2.rectangle(90_rotated_image, start_point, end_point, (255, 0, 0), 2)
这是我得到的结果。
问题是:这里出了什么问题?为什么矩形不能正确旋转并给我预期的结果,如下所示。
编辑: 对于遇到同样问题的任何人来说,使用矩形图像进行旋转的解决方案非常简单。添加到旋转结果的 center_x 和 center_y 变量(涉及 sin 和 cos 的乘法)必须与图像的中心相关 post - 旋转而不是预旋转我最初写进了代码。 post 已更新以反映解决方案。
首先,一般情况下全局坐标中的图像中心应该是这样的(我不知道你的旋转中心到底是什么):
center_x = min_x + w/2
center_y = min_y + h/2
其次:三角函数的参数必须是弧度,而不是度数,所以math.cos(math.radians(degrees_angle))
等等
第三:如果旋转前min_corner是左下,旋转后变成右下(或者可能是左顶部取决于您的坐标系方向); max_corner 也一样。同样使用围绕某个中心的旋转,你必须在最后添加中心坐标。
所以min/max旋转矩形的坐标是:
x_min_90 = center_x + (y_min - center_y)
y_min_90 = center_y - (x_max - center_x)
x_max_90 = center_x + (y_max - center_y)
y_max_90 = center_y - (x_min - center_x)
对于这个例子 ABCD -> FGHI:
xmin = 2 ymin = 1
xmax = 8 ymax = 5
center_x = 2 + 3 = 5
center_y = 1 + 2 = 3
xmin90 = 5 + (1 - 3) = 3
y_min_90 = 3 - (8 - 5) = 0
x_max_90 = 5 + (5 - 3) = 7
y_max_90 = 3 - (2 - 5) = 6
注:
- 我用的是数学坐标系(OX在右,OY在上),如果你的OY轴往下,就根据需要改变方向。
- 我用 0 和 1 替换了 90 的 cos 和 sin。对于其他角度,使用 cos 和 sin 但不要忘记弧度:
如何使用问题中的公式获得 90,180,270 度角的正确结果:
x_a_90 = center_x + math.cos(radians) * (x_min - center_x) - math.sin(radians) * (y_min - center_y)
y_a_90 = center_y + math.sin(radians) * (x_min - center_x) + math.cos(radians) * (y_min - center_y)
x_b_90 = center_x + math.cos(radians) * (x_max - center_x) - math.sin(radians) * (y_max - center_y)
y_b_90 = center_y + math.sin(radians) * (x_max - center_x) + math.cos(radians) * (y_max - center_y)
x_min_90 = min(x_a_90, x_b_90)
x_max_90 = max(x_a_90, x_b_90)
y_min_90 = min(y_a_90, y_b_90)
y_max_90 = max(y_a_90, y_b_90)
我看到了一些与此主题相关的问题,但即使关注了这些问题,我也无法得到我想要的结果,所以我假设我的数学有问题。这是场景。
我有一张图片必须旋转 90 度。同时,我得到了在某个对象上绘制的矩形角的坐标(x_min、y_min)和(x_max、y_max)在图像中。让我们以下图为例,这里使用的矩形由 (4, 196) 和 (145, 269) 定义。
那么,我的目标是旋转图像并对矩形执行相同操作,确保它始终包围目标对象。
首先,我使用 imutils 将图像旋转 90 度(顺时针)。
90_rotated_image = imutils.rotate_bound(original_image, 90)
然后,我正在计算矩形的新坐标。为此,我需要知道 imutils 旋转图像所围绕的点。我尝试了一些组合,包括 (0,0),但这里我假设它是图像本身的中心。
radians = math.radians(90)
h, w, c = original_image.shape
center_x = w/2
center_y = h/2
# Changes to solve the problem. Center of rotated image is now considered.
h_rotated, w_rotated, c = 90_rotated_image.shape
center_x_rotated = w_rotated/2
center_y_rotated = h_rotated/2
x_min_90 = center_x_rotated + math.cos(radians) * (x_min - center_x) - math.sin(radians) * (y_min - center_y)
y_min_90 = center_y_rotated + math.sin(radians) * (x_min - center_x) + math.cos(radians) * (y_min - center_y)
x_max_90 = center_x_rotated + math.cos(radians) * (x_max - center_x) - math.sin(radians) * (y_max - center_y)
y_max_90 = center_y_rotated + math.sin(radians) * (x_max - center_x) + math.cos(radians) * (y_max - center_y)
最后,我在旋转后的图像上绘制新的旋转矩形。
start_point = (x_min_90, y_min_90)
end_point = (x_max_90, y_max_90)
image = cv2.rectangle(90_rotated_image, start_point, end_point, (255, 0, 0), 2)
这是我得到的结果。
问题是:这里出了什么问题?为什么矩形不能正确旋转并给我预期的结果,如下所示。
编辑: 对于遇到同样问题的任何人来说,使用矩形图像进行旋转的解决方案非常简单。添加到旋转结果的 center_x 和 center_y 变量(涉及 sin 和 cos 的乘法)必须与图像的中心相关 post - 旋转而不是预旋转我最初写进了代码。 post 已更新以反映解决方案。
首先,一般情况下全局坐标中的图像中心应该是这样的(我不知道你的旋转中心到底是什么):
center_x = min_x + w/2
center_y = min_y + h/2
其次:三角函数的参数必须是弧度,而不是度数,所以math.cos(math.radians(degrees_angle))
等等
第三:如果旋转前min_corner是左下,旋转后变成右下(或者可能是左顶部取决于您的坐标系方向); max_corner 也一样。同样使用围绕某个中心的旋转,你必须在最后添加中心坐标。
所以min/max旋转矩形的坐标是:
x_min_90 = center_x + (y_min - center_y)
y_min_90 = center_y - (x_max - center_x)
x_max_90 = center_x + (y_max - center_y)
y_max_90 = center_y - (x_min - center_x)
对于这个例子 ABCD -> FGHI:
xmin = 2 ymin = 1
xmax = 8 ymax = 5
center_x = 2 + 3 = 5
center_y = 1 + 2 = 3
xmin90 = 5 + (1 - 3) = 3
y_min_90 = 3 - (8 - 5) = 0
x_max_90 = 5 + (5 - 3) = 7
y_max_90 = 3 - (2 - 5) = 6
注:
- 我用的是数学坐标系(OX在右,OY在上),如果你的OY轴往下,就根据需要改变方向。
- 我用 0 和 1 替换了 90 的 cos 和 sin。对于其他角度,使用 cos 和 sin 但不要忘记弧度:
如何使用问题中的公式获得 90,180,270 度角的正确结果:
x_a_90 = center_x + math.cos(radians) * (x_min - center_x) - math.sin(radians) * (y_min - center_y)
y_a_90 = center_y + math.sin(radians) * (x_min - center_x) + math.cos(radians) * (y_min - center_y)
x_b_90 = center_x + math.cos(radians) * (x_max - center_x) - math.sin(radians) * (y_max - center_y)
y_b_90 = center_y + math.sin(radians) * (x_max - center_x) + math.cos(radians) * (y_max - center_y)
x_min_90 = min(x_a_90, x_b_90)
x_max_90 = max(x_a_90, x_b_90)
y_min_90 = min(y_a_90, y_b_90)
y_max_90 = max(y_a_90, y_b_90)