Аффинное преобразование в PIL Python

У меня проблемы с методом im.transform в библиотеке Python PIL. Я думал, что понял логику параметров от 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

person Matej    schedule 21.09.2011    source источник


Ответы (2)


преобразование отлично работает для меня. В качестве примера мы повернем изображение вокруг центра, отличного от (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)
person bytefish    schedule 07.10.2011
comment
Между тем я разобрался. Я тоже попробую ваш пример. Спасибо - person Matej; 08.10.2011
comment
Расширение не работает. Если значение равно True, то первым аргументом вызова image.transform() должен быть масштабированный размер, а преобразование необходимо выполнить заново. Первую часть я прошел, а вторую провалил. Можете ли вы помочь заставить expand=True работать? - person theoden; 05.02.2020

Я думаю, что моя версия гораздо более четкая и понятная.

def scale_rotate_translate(image, angle, sr_center=None, displacment=None, scale=None):
    if sr_center is None:
        sr_center = 0, 0
    if displacment is None:
        displacment = 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, displacment[0]],
                  [0, 1, displacment[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)
person Marat Zakirov    schedule 12.07.2021