Python PIL:旋转和缩放图像,使两个点与另外两个点匹配

Python PIL: Rotate and scale image so that two points match two other points

假设我有一张包含两个点的图像。

pointA = (100,100)
pointB = (200,200)

我想旋转和缩放图像,使两个点现在位于不同的位置。

newPointA = (250,320)
newPointB = (540, 330)

在伪代码中我正在寻找这样的东西

adjusted = im.transformToPoint(originalA, originalB, newA, newB)

换句话说,如果 pointA 和 pointB 是触摸时的手指,newPointA 和 newPointB 是抬起时的手指,那么缩放和旋转在触摸屏设备上的工作方式。

创建黑边不是问题。

我知道这可能是一个简单的操作,因为它是在触摸屏设备上用两根手指缩放和旋转的方式,但不幸的是,我对几何的理解太有限,无法弄清楚。

绕原点A的旋转可以表示为

xNew = xOld·cos(A) - yOld·sin(A)
yNew = xOld·sin(A) + yOld·cos(A)

用因子 F 缩放,再次从原点开始是

xScaled = xBase · F
yScaled = yBase · F

你可能会说,有两个 (x,y) 点和它们的最终变换点,通过将它们代入方程并求解系统来解决问题。但问题是系统不好解决;你需要一些数值近似值。

但并非一切都丢失了:)

两点之间的角度 B 很容易计算:取增量 dx=x2-x1dy=y2-y1 并使用 B= atan2(dx,dy)(防止自己atan(dx,dy))。使用 before/after 移动触摸你会得到两个角度。旋转角度为A= B2-B1.

缩放因子F也很简单:计算手指在触摸时和手指移动后的距离。因数是它们之间的商。

注意:
我想你还需要一个翻译,否则你的最终图像可能不是你所期望的。

我会做的是:

  1. 首先计算触摸动作中手指(mx,my)的中点。同时使用触摸和提升动作计算旋转角度 A 和比例因子 F
  2. 然后平移整个图像,使其原点成为中间点。只是 减去那些中间坐标 (mx,my).
  3. 然后旋转和缩放。
  4. 然后通过添加之前使用的存储中间坐标来撤消平移。

在步骤“1”中。我假设旋转发生在中间点附近。你可以考虑其他点。例如,如果手指“一”的移动幅度不大,但手指“二”的移动幅度很大,则可能是 rotation/scaling 位于手指“一”的坐标附近。如果是这样,请使用这些坐标。

也许获得“中间”点的一般情况是计算手指一到手指二在触摸和抬起动作时的线的交点。