这是一个有关PIL的基本变换问题。在过去的几年中,我至少尝试了几次来正确地实现它,但似乎我对于PIL中Image.transform的使用还不太熟悉。我想要实现一种相似变换(或仿射变换),其中我可以明确指定图像的边界限制。为了确保我的方法可行,我在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的输出:
我在多个操作系统上使用了数个版本的Python和PIL尝试过这个问题,结果大多都相同。
这是最简单的情况,用来说明问题。如果我想要旋转图像,可以使用im.rotate调用进行旋转,但我也希望能够扭曲和缩放图像,这只是一个例子,以说明问题。我希望能够对所有仿射变换得到相同的输出结果,我希望能够正确地完成它。
编辑:
如果我将transform行更改为以下内容:
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,得到了以下结果: