PIL Python 中的仿射变换

发布于 2024-12-05 11:51:11 字数 304 浏览 1 评论 0原文

我对 PIL python 库中的 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

I have problems with the im.transform method in PIL python library. I thought I figured out the logic of parameters, A to F, however, the resulting image gets rotated in the wrong direction and cut off although all four corners calculated by the bellow function have correct positive values.

Could anybody give me formulas to calculate affine parameters (A to F) from three identical points in both coordinate systems?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤千羽 2024-12-12 11:51:11

变换对我来说效果很好。作为示例,我们将围绕不同于 (0,0) 的中心旋转图像,并可选择缩放和平移到新中心。以下是如何使用转换来做到这一点:

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)

transform works fine for me. As an example we'll rotate an image around a center different from (0,0) with optional scaling and translation to a new center. Here is how to do it with 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)
浅浅淡淡 2024-12-12 11:51:11

我认为我的版本更加明确且易于理解。

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)

I think my version of is much more explicit and easy to understand.

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文