【问题标题】:Calculate pixels belonging to corners of rectangle after rotating image旋转图像后计算属于矩形角的像素
【发布时间】:2020-12-09 20:58:38
【问题描述】:

我看到了一些与此主题相关的问题,但即使在关注它们之后我也无法获得我想要的结果,所以我认为我的数学有些问题。这是场景。

我有一张必须旋转 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 的乘法)必须与图像旋转后的中心相关,而不是与我最初写入代码的预旋转相关。该帖子已更新以反映解决方案。

【问题讨论】:

    标签: python geometry


    【解决方案1】:

    首先,一般情况下,全局坐标中的图像中心应该是这样的(我不知道你的旋转中心到底是什么):

    center_x = min_x + w/2
    center_y = min_y + h/2
    

    第二:三角函数的参数必须是弧度,而不是度数,所以math.cos(math.radians(degrees_angle))等等

    第三:如果在旋转之前,min_corner是左下,旋转后它变成右下(或者可能是左上,取决于你的坐标系方向); max_corner 相同。同样使用围绕某个中心的旋转,您必须在最后添加中心坐标。

    所以旋转矩形的最小/最大坐标是:

    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
    

    注意:

    1. 我使用了数学坐标系(OX 向右,OY 到顶部),如果您的 OY 轴向下,则根据需要更改方向。
    2. 我将 90 的 cos 和 sin 替换为 0 和 1。对于其他角度,请使用 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)
    

    【讨论】:

    • 是的,我把 cos 和 sin 留在了那里,因为以后我会为其他角度做。无论如何,可悲的是,在方程中添加中心并计算角度的弧度并不起作用。我已经用我正在使用的新计算更新了原始帖子,所以如果有人对错误有更多的了解,我将不胜感激!
    • 谢谢!但是,这种旋转不适用于我的矩形,因为您显示的矩形是围绕它自己的中心旋转的。我需要相对于图像旋转我的。我添加了一些我运行的本地测试的示例图像以进行澄清。
    • 您的公式对于围绕任何点的旋转都是正确的 - 只需将其坐标放入 center_x 和 center_y 即可。但结果是新点的坐标,而不是直接的最大值和最小值。看看加法。
    • 哦,有道理。再次感谢!不过,出于某种原因,现在它在 180 度旋转时工作得很好,但在 90 度和 180 度时仍然没有运气。
    • 糟糕。我的意思是 90 和 270!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    相关资源
    最近更新 更多