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

Это основной вопрос преобразования в PIL. Я'За последние несколько лет я пытался, по крайней мере, пару раз, чтобы реализовать это правильно, и, кажется, что-то я неЯ не совсем понимаю Image.transform в PIL. Я хочу реализовать преобразование сходства (или аффинное преобразование), в котором я могу четко указать пределы изображения. Чтобы убедиться, что мой подход работает, я реализовал его в Matlab.

Реализация Matlab заключается в следующем:

im = imread('test.jpg');
y = size(im,1);
x = size(im,2);
angle = 45*3.14/180.0;
xextremes = [rot_x(angle,0,0),rot_x(angle,0,y-1),rot_x(angle,x-1,0),rot_x(angle,x-1,y-1)];
yextremes = [rot_y(angle,0,0),rot_y(angle,0,y-1),rot_y(angle,x-1,0),rot_y(angle,x-1,y-1)];
m = [cos(angle) sin(angle) -min(xextremes); -sin(angle) cos(angle) -min(yextremes); 0 0 1];
tform = maketform('affine',m')
round( [max(xextremes)-min(xextremes), max(yextremes)-min(yextremes)])
im = imtransform(im,tform,'bilinear','Size',round([max(xextremes)-min(xextremes), max(yextremes)-min(yextremes)]));
imwrite(im,'output.jpg');

function y = rot_x(angle,ptx,pty),
    y = cos(angle)*ptx + sin(angle)*pty

function y = rot_y(angle,ptx,pty),
    y = -sin(angle)*ptx + cos(angle)*pty

это работает как ожидалось. Это вход:

и это вывод:

Это код Python / PIL, который реализует то же преобразование:

import Image
import math

def rot_x(angle,ptx,pty):
    return math.cos(angle)*ptx + math.sin(angle)*pty

def rot_y(angle,ptx,pty):
    return -math.sin(angle)*ptx + math.cos(angle)*pty

angle = math.radians(45)
im = Image.open('test.jpg')
(x,y) = im.size
xextremes = [rot_x(angle,0,0),rot_x(angle,0,y-1),rot_x(angle,x-1,0),rot_x(angle,x-1,y-1)]
yextremes = [rot_y(angle,0,0),rot_y(angle,0,y-1),rot_y(angle,x-1,0),rot_y(angle,x-1,y-1)]
mnx = min(xextremes)
mxx = max(xextremes)
mny = min(yextremes)
mxy = max(yextremes)
im = im.transform((int(round(mxx-mnx)),int(round((mxy-mny)))),Image.AFFINE,(math.cos(angle),math.sin(angle),-mnx,-math.sin(angle),math.cos(angle),-mny),resample=Image.BILINEAR)
im.save('outputpython.jpg')

и это вывод из Python: I '

В течение многих лет мы пробовали это с несколькими версиями Python и PIL на нескольких ОС, и результаты всегда были в основном одинаковыми.

Это простейший возможный случай, который иллюстрирует проблему, я понимаю, что если бы это было вращение, которое я хотел, я мог бы сделать вращение с помощью вызова im.rotate, но я хочу также срезать и масштабировать, это просто пример, чтобы проиллюстрировать проблема. Я хотел бы получить одинаковый вывод для всех аффинных преобразований. Я хотел бы быть в состоянии понять это правильно.

РЕДАКТИРОВАТЬ:

Если я изменю строку преобразования на это:

im = im.transform((int(round(mxx-mnx)),int(round((mxy-mny)))),Image.AFFINE,(math.cos(angle),math.sin(angle),0,-math.sin(angle),math.cos(angle),0),resample=Image.BILINEAR)

это вывод, который я получаю:

РЕДАКТИРОВАТЬ № 2

Я повернулся на -45 градусов и изменил смещение на -0,5 * mnx и -0,5 * mny и получил это:

Ответы на вопрос(3)

Ваш ответ на вопрос