PIL无法识别io.BytesIO对象的图像文件

52

我正在使用Pillow的分支来代替PIL,在打开图像时不断收到以下错误信息:

OSError: 无法识别图像文件 <_io.BytesIO object at 0x103a47468>

我正在使用Python 3.4和没有安装PIL的virtualenv。

我已经尝试根据其他人遇到同样问题的解决方案来解决这个问题,但是那些解决方案对我没有起作用。以下是我的代码:

from PIL import Image
import io

# This portion is part of my test code
byteImg = Image.open("some/location/to/a/file/in/my/directories.png").tobytes()

# Non test code
dataBytesIO = io.BytesIO(byteImg)
Image.open(dataBytesIO) # <- Error here

图片存在于文件的初始开头,并转换为字节。这似乎对几乎所有其他人都有效,但我想不出为什么它会对我失败。

编辑:

dataBytesIO.seek(0)

尝试过后发现不起作用,因为我没有通过流来保存图像,而是仅仅使用数据实例化了BytesIO,因此(如果我想得正确的话)seek应该已经在0处。


4
可能是与PIL的open()方法无法与BytesIO一起使用的重复问题。 - G4bri3l
4
我建议将帖子中的解决方案移动到单独的答案中。只是为了格式上的考虑。 - eshimoniak
1
@FracturedRetina 我同意。请将答案移动到单独的帖子中,以便社区可以对其进行投票,并使您可以获得声望,Elan M。 - Flimm
当我不小心加载了一个PDF而不是PNG时,这种情况发生在我身上。 - Bohumir Zamecnik
7个回答

46

(这个解决方案来自作者本人。我只是将它移到这里。)

解决办法:

# This portion is part of my test code
byteImgIO = io.BytesIO()
byteImg = Image.open("some/location/to/a/file/in/my/directories.png")
byteImg.save(byteImgIO, "PNG")
byteImgIO.seek(0)
byteImg = byteImgIO.read()


# Non test code
dataBytesIO = io.BytesIO(byteImg)
Image.open(dataBytesIO)
问题出在Image.tobytes()返回的字节对象上。它看起来是无效数据,且“编码方式”只能是原始编码,但输出的数据仍然是错误的,因为几乎每个字节都以\xff\格式出现。 然而,通过使用BytesIO保存字节,并使用.read()函数读取整个图像,可以获得正确的字节,稍后需要时可以实际使用。

3
在某些情况下,处理CR2等原始图像文件时可能会出现相同的错误。例如:http://www.rawsamples.ch/raws/canon/g10/RAW_CANON_G10.CR2。当您尝试运行以下命令时:
byteImg = Image.open("RAW_CANON_G10.CR2")

您将会得到以下错误信息:
OSError: cannot identify image file 'RAW_CANON_G10.CR2'

因此,您需要首先使用rawkit转换图像,以下是如何执行的示例:

from io import BytesIO
from PIL import Image, ImageFile
import numpy
from rawkit import raw
def convert_cr2_to_jpg(raw_image):
    raw_image_process = raw.Raw(raw_image)
    buffered_image = numpy.array(raw_image_process.to_buffer())
    if raw_image_process.metadata.orientation == 0:
        jpg_image_height = raw_image_process.metadata.height
        jpg_image_width = raw_image_process.metadata.width
    else:
        jpg_image_height = raw_image_process.metadata.width
        jpg_image_width = raw_image_process.metadata.height
    jpg_image = Image.frombytes('RGB', (jpg_image_width, jpg_image_height), buffered_image)
    return jpg_image

byteImg = convert_cr2_to_jpg("RAW_CANON_G10.CR2")

代码来源于 GitHub 上的 mateusz-michalik (https://github.com/mateusz-michalik/cr2-to-jpg/blob/master/cr2-to-jpg.py)


2

image = Image.open(io.BytesIO(decoded)) # File "C:\Users\14088\anaconda3\envs\tensorflow\lib\site-packages\PIL\Image.py", line 2968, in open # "cannot identify image file %r" % (filename if filename else fp) # PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x000002B733BB11C8>

我已修复如下: message = request.get_json(force=True)

encoded = message['image']
# https://dev59.com/Z18e5IYBdhLWcg3wHXeJ
#image_data = re.sub('^data:image/.+;base64,', '', message['image'])
image_data = re.sub('^data:image/.+;base64,', '', encoded)
# Remove extra "data:image/...'base64" is Very important
# If "data:image/...'base64" is not remove, the following line generate an error message: 
# File "C:\Work\SVU\950_SVU_DL_TF\sec07_TF_Flask06_09\32_KerasFlask06_VisualD3\32_predict_app.py", line 69, in predict
# image = Image.open(io.BytesIO(decoded))
# File "C:\Users\14088\anaconda3\envs\tensorflow\lib\site-packages\PIL\Image.py", line 2968, in open
# "cannot identify image file %r" % (filename if filename else fp)
# PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x000002B733BB11C8>
# image = Image.open(BytesIO(base64.b64decode(image_data)))
decoded = base64.b64decode(image_data)
image = Image.open(io.BytesIO(decoded))
# return json.dumps({'result': 'success'}), 200, {'ContentType': 'application/json'}
#print('@app.route => image:')
#print()
processed_image = preprocess_image(image, target_size=(224, 224))

prediction = model.predict(processed_image).tolist()
#print('prediction:', prediction)
response = {
    'prediction': {
        'dog': prediction[0][0],
        'cat': prediction[0][1]
    }
}
print('response:', response)
return jsonify(response)

2

在阅读Dicom文件时,问题可能是由于Dicom压缩引起的。请确保已安装gdcm和pydicom。

通常情况下,安装GDCM比较困难。最简单的安装方法是:

conda install -U conda-forge gdcm

1

在处理URL时,这种错误可能来自下载文件的错误扩展名或损坏的文件。

因此,为了避免这种情况,使用try/except块来防止应用程序崩溃并继续执行操作。

在except部分,您可以检索有问题的文件以进行分析:

以下是代码片段:

for url in urls:
    with closing(urllib.request.urlopen(url)) as f:
        try:
            img = Image(f, 30*mm, 30*mm)
            d_img.append(img) 

         except Exception as e:
                    print(url) #here you get the file causing the exception
                    print(e)

这里有一个相关答案



0

图片文件本身可能已损坏。因此,如果您要处理大量的图像文件,则只需将处理每个图像文件的行用try catch语句括起来。


0
你可以尝试这种方法,这对我来说可以打开图像链接:
from PIL import Image
import urllib.request
urllib.request.urlretrieve('https://blog.finxter.com/wp-content/uploads/2022/04/greenland_01a.jpg',"C:\\Users\luxman\Desktop\Devon5G ROW India test bat\gfg.jpg")
img = Image.open("C:\\Users\luxman\Desktop\Devon5G ROW India test bat\gfg.jpg")
img.show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接