如何使用PIL保存图像?


118

我刚刚使用Python图像库(PIL)进行了一些图像处理,这是我之前发现的用于执行图像的傅立叶变换的文章,但我无法使用save函数。整个代码运行良好,但不会保存生成的图像:

from PIL import Image
import numpy as np

i = Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j = Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")

我得到的错误如下:

save_handler = SAVE[string.upper(format)] # unknown format
    KeyError: '.BMP'

如何使用Pythons PIL保存图像?

Answers:


143

解决了与文件扩展名有关的错误,您可以使用BMP(不带点)或将输出名称与扩展名一起传递。现在要处理该错误,您需要在频域中适当地修改数据以将其保存为整数图像,PIL这告诉您它不接受将浮点数据保存为BMP。

这是进行转换以实现正确可视化的建议(还有其他一些小的修改,例如使用fftshiftnumpy.array代替numpy.asarray):

import sys
import numpy
from PIL import Image

img = Image.open(sys.argv[1]).convert('L')

im = numpy.array(img)
fft_mag = numpy.abs(numpy.fft.fftshift(numpy.fft.fft2(im)))

visual = numpy.log(fft_mag)
visual = (visual - visual.min()) / (visual.max() - visual.min())

result = Image.fromarray((visual * 255).astype(numpy.uint8))
result.save('out.bmp')

1
嘿,非常感谢。现在工作完美!现在我所要做的就是了解所有步骤,但这不会太糟。非常感谢您的帮助
2013年

@ user1999274的主要区别在于使用fft2而不是,rfft2因为对于离散数据,我看不到使用后者的意义。其余的纯粹是装饰性的,也就是说,如果不对它应用对数因子,就无法正确可视化傅立叶变换。然后,归一化是为了使转换到[0,255]范围简单。
mmgp

1
visual = (visual - visual.min()) / (visual.max() - visual.min())如果visual没有差异(不太可能,但值得注意),则将默认设置

1
我尝试使用此代码解决问题,但得到纯黑色图像。有人对此有任何想法吗?stackoverflow.com/questions/24266000/...
user961627

32

您应该能够简单地让PIL从扩展名中获取文件类型,即使用:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")

1
感谢您的输入。但是,当我尝试让保存功能像上面建议的那样获取文件类型时,出现以下错误:IOError:无法将模式F写入BMP。有什么建议吗?
user1999274 2013年

1
是的,您应该将数组转换为numpy.uint8dtype而不是float。
2013年

6

尝试删除.之前的.bmp(它BMP与预期的不匹配)。正如您从错误中看到的那样,save_handler就是format您提供的大写字母,然后在中寻找匹配项SAVE。但是,该对象中的对应键为BMP(而不是.BMP)。

我不太了解PIL,但是通过一些快速搜索,似乎mode图像的问题。将的定义更改j为:

j = Image.fromarray(b, mode='RGB')

似乎为我工作(但是请注意,我对的了解很少PIL,因此我建议使用@mmgp的解决方案,因为他/她清楚地知道他们在做什么:)))。对于的类型mode,我使用了页面-希望那里的一种选择适合您。


我尝试删除.bmp以支持bmp,但仍然无法正常工作。我现在得到的错误是:IOError:无法将模式F写入BMP。我检查了PIL页面的文档,并说要使用.bmp,所以总体上我仍然不知道为什么它不起作用。
user1999274 2013年

@ user1999274发布了一个似乎对我有用的更新(由于缺乏细节,我深表歉意,因为我将其拼凑在一起:))。
RocketDonkey

@RocketDonkey比这要聪明一些,因为将傅立叶变换的结果转换为RGB色彩空间将得到毫无意义的图像。仅仅因为它不再引发异常,并不意味着结果正确。
mmgp

@mmgp同意-这就是我为您+1并希望OP接受它的原因:)
RocketDonkey

4

我知道这很旧,但是我发现(在使用Pillow的同时)通过使用open(fp, 'w')然后保存文件来打开文件是可行的。例如:

with open(fp, 'w') as f:
    result.save(f)

fp 当然是文件路径。


1
Pillow的文档说,format如果在中使用文件对象,则应使用该参数save。没必要吗?
罗布·罗斯

在测试过程中,@ RobRose发布答案时,我没有发现类似的必要。但是,现在可能是这样。如果您确实进行了任何测试,请告诉我,我将编辑我的答案
Necko
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.