[英]Flipping image / mirror Image
我需要编写一个获取图像并返回镜像的函数(Y坐标永远不变),而无需使用PIL的任何镜像或翻转模块。
我必须自己写。 我收到一条错误消息:
IndexError: image index out of range
我在这里想念什么?
谢谢。
from os.path import exists
import tkMessageBox, tkFileDialog
from PIL import Image, ImageTk, ImageFilter
def flip(im):
'''Flips a picutre horizontally, and returns a new image that is a mirror view of the original'''
org=Image.open(im)
new=Image.new("RGB",org.size)
for x in range(org.size[0]):
a=org.size[0]
for y in range(org.size[1]):
pixel=org.getpixel((x,y))
new.putpixel((a,y),pixel)
a-=1
new.save("new.bmp","bmp")
使用ImageOps.mirror(image)水平翻转图像。
import Image
import ImageOps
img = Image.open(FILENAME)
mirror_img = ImageOps.mirror(img)
您的代码非常接近工作。 您有一个“ off-by-one”错误。
a=org.size[0]
...
new.putpixel((a,y),pixel)
假设org
宽度为100像素。 然后,第一次通过循环将像素放置在(100,y)
。 但是像素的索引范围是0--99。 这就是为什么(以及在何处)出现IndexError: image index out of range
异常的原因。
另外,请注意循环中要初始化和递减a
。 其实,我也不会建议使用a
在所有。
而是使用
w,h = org.size
for x in range(w):
for y in range(h):
pixel = org.getpixel((x, y))
new.putpixel(EXPRESSION, pixel)
然后将EXPRESSION替换为您要着色的像素位置的一些公式。
您正在混合基于0和1的索引。 x
范围是0
到org.size[0]-1
。 但a
范围从org.size[0]
到1
,因为你开始与a=org.size[0]
并使用,如果没有第1减法运算。
错误最有可能来自此行内的某个地方:
new.putpixel((a,y),pixel)
…在您的第一个电话上,当您尝试在仅以(0-279,0-279)运行的图像中写入像素(280,0)时。
因此,代替此:
for x in range(org.size[0]):
a=org.size[0]
for y in range(org.size[1]):
pixel=org.getpixel((x,y))
new.putpixel((a,y),pixel)
a-=1
做这个:
for x in range(org.size[0]):
a=org.size[0]-1
for y in range(org.size[1]):
pixel=org.getpixel((x,y))
new.putpixel((a,y),pixel)
a-=1
但是,一旦解决此问题,就会遇到另一个问题。 每次通过外循环而不是第一次都将org.size[0]
设置a
。 然后,您每次通过内循环而不是外循环递减a
。 因此,您将最终将原始图像中的每一行复制到从(279,0)到(0,279)的对角线。
因此,您需要这样做:
a=org.size[0]-1
for x in range(org.size[0]):
for y in range(org.size[1]):
pixel=org.getpixel((x,y))
new.putpixel((a,y),pixel)
a-=1
正是这种原因,您应该避免像这样手动修改索引。 您第一次尝试就永远做不到。 在第三次尝试中,您会得到看起来不错的东西,但是当您尝试测试套件中没有的第一个映像时,它就会崩溃。 最好计算这些值,而不是倒数。 例如:
for x in range(org.size[0]):
flipped_x = org.size[0] - x - 1
for y in range(org.size[1]):
pixel=org.getpixel((x,y))
new.putpixel((flipped_x,y),pixel)
在此过程中,如果您可以要求/依赖PIL 1.1.6或更高版本,则使用Image.load()
返回的数组会明显更简单,更高效且通常更容易调试:
orgpixels, newpixels = org.load(), new.load()
for x in range(org.size[0]):
flipped_x = org.size[0] - x - 1
for y in range(org.size[1]):
pixel=orgpixels[x, y]
newpixels[flipped_x, y] = pixel
如果您不能依靠1.1.6,则可以使用getdata
获取一个可迭代的像素序列,使用它来生成新的list
或其他序列(这意味着您可以使用列表推导, map
,甚至将它们输入numpy
通过例如np.array(org.getdata()).reshape(org.size)
),然后使用putdata
从结果中创建新图像。
当然, getdata
和putdata
处理一维序列,而您希望将其视为2D序列。 幸运的是, grouper
在功能itertools
文档,您可以复制和粘贴,或者只是pip install more-itertool
通常-is正是你想要的:
orgrows = more_itertools.grouper(org.size[0], org.getdata())
newrows = [list(reversed(row)) for row in orgrows]
new.putdata(newrows)
要注意的一件事是Image.open(im)
不一定会在RGB模式下返回图像。 如果仅将像素从XYZ或P图像复制到RGB,最终将导致变色的垃圾或仅出现红色通道。 您可能要print org.mode
,并可能要print org.pixel((0, 0))
以确保它实际上具有3个通道(它们看起来像RGB)`。
最简单的方法是在执行其他任何操作之前先转换org
:
org=Image.open(im).convert('RGB')
当然,某些格式要么没有直接转换,要么需要显式的矩阵或调色板。 如果出现ValueError
,则必须阅读有关转换输入类型的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.