【问题标题】:Get new x,y coordinates of a point in a rotated image获取旋转图像中某个点的新 x,y 坐标
【发布时间】:2011-09-19 16:03:07
【问题描述】:

我有谷歌地图图标,在使用MarkerImage 在地图上绘图之前,我需要将其旋转一定角度。我使用 PIL 在 Python 中即时进行旋转,生成的图像与原始图像大小相同 - 32x32。例如,使用以下默认 Google 地图标记: ,使用以下python代码实现逆时针旋转30度:

# full_src is a variable holding the full path to image
# rotated is a variable holding the full path to where the rotated image is saved
image = Image.open(full_src)
png_info = image.info
image = image.copy()
image = image.rotate(30, resample=Image.BICUBIC)
image.save(rotated, **png_info)

生成的图像是

当使用新的旋转图像创建 MarkerImage 时,棘手的一点是要使用新的锚点。这需要是图标的尖端。默认情况下,锚点位于底部中间[定义为 x,y 坐标中的 (16,32),其中 (0,0) 是左上角]。有人可以向我解释一下如何在 JavaScript 中轻松解决这个问题吗?

谢谢。

2011 年 6 月 22 日更新: 发布了错误的旋转图像(原始图像是逆时针旋转 330 度)。我已经纠正了。还添加了重采样(Image.BICUBIC),使旋转的图标更清晰。

【问题讨论】:

  • @Trufa:感谢您的建议。

标签: javascript python api google-maps image-rotation


【解决方案1】:

要计算旋转点的位置,您可以使用rotation matrix

转换成JavaScript,这样计算旋转点:

function rotate(x, y, xm, ym, a) {
    var cos = Math.cos,
        sin = Math.sin,

        a = a * Math.PI / 180, // Convert to radians because that is what
                               // JavaScript likes

        // Subtract midpoints, so that midpoint is translated to origin
        // and add it in the end again
        xr = (x - xm) * cos(a) - (y - ym) * sin(a)   + xm,
        yr = (x - xm) * sin(a) + (y - ym) * cos(a)   + ym;

    return [xr, yr];
}

rotate(16, 32, 16, 16, 30); // [8, 29.856...]

【讨论】:

  • 谢谢。这正是我所需要的。
  • 这适用于方形图像,但不适用于矩形图像。调用rotate(10, 10, 160 / 2, 120 / 2, 90) 返回[130, -10]
【解决方案2】:

关于 0,0 的旋转公式是:

x1 = cos(theta) x0 - sin(theta) y0
y1 = sin(theta) x0 + cos(theta) y0

但这是针对常规轴和大约 0,0 的旋转。 PIL 旋转是顺时针的,带有“图形”轴。另外,它位于图像的中心附近。最后令人困惑的是图像的大小可以改变,这需要在最终结果中加以考虑。

程序:取原点,减去图像中心,应用“图形轴”校正旋转,找到图像的新尺寸,添加新图像的中心位置。

使用图形轴的旋转是:

x1 = cos(theta) x0 + sin(theta) y0
y1 = -sin(theta) x0 + cos(theta) y0

16,32 - 16,16 是 0, 16。顺时针旋转 30 度(根据您的图像)给出一个点 cos(-30)*0+sin(-30)*16, -sin(-30 )*0+cos(-30)*16 = -8, 13.86。最后一步是添加回旋转位置的中心位置。

【讨论】:

  • 你能解释一下“常规”轴和“图形”轴之间的区别吗?主要的不同似乎是哪个坐标有减法,但我不明白为什么。
  • 截至PIL VERSION 1.1.7,旋转是围绕中心逆时针,而不是本答案中提到的顺时针
  • 很好的解释,但这个公式与公认的答案有同样的问题:它不适用于非方形图像,因为有时输出为负数。
【解决方案3】:

在图像中,向下是正 Y,向右是正 X。但是,要应用 rotation formula,我们需要向上作为正 Y。因此,第一步是应用 f(x,y) = f(x,h-y),其中“h”是图像的高度。 假设图像相对于 x0,y0 旋转。然后,您需要将原点转换为这一点。因此,第 2 步将是f(x,y) = f(x-x0,y-y0)。在这个阶段(即两个步骤之后),您的新坐标将是x-x0h-y-y0。您现在可以应用旋转公式了

x1 = x*cos(theta) - y*sin(theta) 

y1 = xsin(theta) + ycos(theta) 

使用第二步后得到的 x 和 y 的值。 你会得到

x1 = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) 

y1 = (x-x0)*sin(theta) + (h-y-y0)*cos(theta)

现在,撤消在第 2 步和第 1 步中完成的转换(按此顺序)。

撤消步骤2后:xNew = x1 + x0yNew = y1 + y0

撤消步骤1后:xNew = x1 + x0yNew = h - (y1 + y0)

这给了你:

xNew = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) + x0

yNew = -(x-x0)*sin(theta) - (h-y-y0)*cos(theta) + (h-y0)

【讨论】:

  • 也许你的意思是xNew = (x-x0)*cos(theta) + (h-y-y0)*sin(theta) + x0
猜你喜欢
  • 1970-01-01
  • 2010-10-14
  • 2021-07-10
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多