Python 旋转后的图片看起来像';s缺少像素

Python 旋转后的图片看起来像';s缺少像素,python,image,image-processing,matrix,python-imaging-library,Python,Image,Image Processing,Matrix,Python Imaging Library,我在玩PIL和变换矩阵,以了解简单的2D图像处理背后的内容 在我尝试将图像旋转为尽可能“低水平”(即,不使用任何旋转(度)函数,而是进行数学运算)时,我决定使用顺时针旋转矩阵旋转图像的每个像素: 旋转进行得很顺利,但图像现在看起来缺少了一些像素 在435x353黑色背景上绘制的原始图像: 顺时针旋转45°并向右移动300像素: 奇怪的是,将图片顺时针旋转90°时(并向右移动400像素),问题并没有出现: 这可能是什么原因造成的?使用Image.Image.rotate效果很好,所以我想问

我在玩PIL和变换矩阵,以了解简单的2D图像处理背后的内容

在我尝试将图像旋转为尽可能“低水平”(即,不使用任何
旋转(度)
函数,而是进行数学运算)时,我决定使用顺时针旋转矩阵旋转图像的每个像素:

旋转进行得很顺利,但图像现在看起来缺少了一些像素

在435x353黑色背景上绘制的原始图像:

顺时针旋转45°并向右移动300像素:

奇怪的是,将图片顺时针旋转90°时(并向右移动400像素),问题并没有出现:

这可能是什么原因造成的?使用
Image.Image.rotate
效果很好,所以我想问题在于我的代码。值得一提的是,原始图片有一个透明的背景,上传到这里时在压缩过程中丢失了。但是,我对jpeg(不透明)图像执行了完全相同的操作,结果是相同的

用于执行旋转的代码:

import Image, ImageDraw
from scipy import misc
import math

WHITE = (255,255,255)
BLACK = (0,0,0)
W, H = 435, 353
im = Image.new('RGBA', (W, H), BLACK)
draw = ImageDraw.Draw(im)
bitmap = misc.imread('Image.png')

def affine_t(x, y, a, b, c, d, e, f):
    """Returns ((a, b), (c, d))*((x), (y)) + ((e), (f)).""" 
    return a*x + b*y + e, c*x + d*y + f

def crotate(x, y, r):
    """Rotate (x, y) clockwise by r radians."""
    # And move 300 px to the right for this example
    return affine_t(
        x, y, math.cos(-r), math.sin(-r), -math.sin(-r), math.cos(-r), 300, 0
    )

x, y = 0, 0
angle = math.pi/4
for row in bitmap:
    for pt in row:
        draw.point([crotate(x, y, angle),],fill=tuple(pt))
        x+= 1
    x = 0
    y += 1

im.save('out.png')

对于每个目标像素,您需要计算源像素,而不是相反。由于舍入,您将多个源像素映射到同一目标像素。这就是为什么在没有插值的情况下无法获得良好的45°旋转。我的建议实际上是一个最近邻插值。

如果你仔细研究枕头,你可以看到它是如何实现的(主要是用C表示速度;一个中等大小的图像很容易就是一个百万字节数组),这里是and(据说更快,我不知道数学)函数。+1表示使用“orient”Watch您可能会发现skimage中的扭曲功能对实验很有用:
skimage.transform的API在这里有文档记录:在每个反向变换的目标像素的对应源像素之间,比简单地使用最近邻像素会得到更好的结果。Wikipedia上的文章对此进行了说明。旋转和缩放的更好方法是算法。RotSprite看起来非常优雅和高效,感谢链接。我可以推荐George Wolberg的书《数字图像扭曲》,以了解更多有关该主题的信息。是的,当目标图像的每个像素是源图像的某个像素时,实际上不进行插值,这称为“最近邻”。当您插值某些内容时,您实际上可以获得原始图像上没有的颜色。