PIL Python中的仿射变换

6

我在使用Python的PIL库中的im.transform方法时遇到了问题。我以为我已经理解了参数A到F的逻辑,但是结果图像旋转方向错误并被裁剪,尽管下面函数计算出的所有四个角都有正确的正值。

请问是否有人能给我公式,通过两个坐标系中的三个相同点来计算仿射参数(A到F)?

def tran (x_pic, y_pic, A, B, C, D, E, F):
  X = A * x_pic + B * y_pic + C
  Y = D * x_pic + E * y_pic + F
  return X, Y
2个回答

15

transform对我来说很有效。作为示例,我们将围绕与(0,0)不同的中心旋转图像,并且可以选择缩放和平移到一个新的中心。以下是如何使用transform进行操作:

def ScaleRotateTranslate(image, angle, center = None, new_center = None, scale = None,expand=False):
    if center is None:
        return image.rotate(angle)
    angle = -angle/180.0*math.pi
    nx,ny = x,y = center
    sx=sy=1.0
    if new_center:
        (nx,ny) = new_center
    if scale:
        (sx,sy) = scale
    cosine = math.cos(angle)
    sine = math.sin(angle)
    a = cosine/sx
    b = sine/sx
    c = x-nx*a-ny*b
    d = -sine/sy
    e = cosine/sy
    f = y-nx*d-ny*e
    return image.transform(image.size, Image.AFFINE, (a,b,c,d,e,f), resample=Image.BICUBIC)

与此同时,我想出来了。我也会尝试您的示例。谢谢。 - Matej
1
Expand是无效的。如果为True,则image.transform()调用的第一个参数应该是缩放后的大小,并且需要重新进行翻译。我理解了第一部分,但在第二部分失败了。你能帮忙让expand=True起作用吗? - theoden

1
我认为我的版本更加明确易懂。
def scale_rotate_translate(image, angle, sr_center=None, displacement=None, scale=None):
    if sr_center is None:
        sr_center = 0, 0
    if displacement is None:
        displacement = 0, 0
    if scale is None:
        scale = 1, 1

    angle = -angle / 180.0 * np.pi

    C = np.array([[1, 0, -sr_center[0]],
                  [0, 1, -sr_center[1]],
                  [0, 0, 1]])

    C_1 = np.linalg.inv(C)

    S = np.array([[scale[0], 0, 0],
                  [0, scale[1], 0],
                  [0,        0, 1]])

    R = np.array([[np.cos(angle), np.sin(angle), 0],
                  [-np.sin(angle), np.cos(angle), 0],
                  [0,                         0, 1]])

    D = np.array([[1, 0, displacement[0]],
                  [0, 1, displacement[1]],
                  [0, 0,            1]])

    Mt = np.dot(D, np.dot(C_1, np.dot(R, np.dot(S, C))))

    a, b, c = Mt[0]
    d, e, f = Mt[1]

    return image.transform(image.size, Image.AFFINE, (a, b, c, d, e, f), resample=Image.BICUBIC)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接