You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PIL打开图像报错UnidentifiedImageError的原因及解决方法

问题:调用libcamera-still生成图像后PIL无法识别的错误

代码实现

from io import StringIO
import subprocess
import os
import time
from datetime import datetime
from PIL import Image
import subprocess


def captureTestImage(settings, width, height):
    command = "libcamera-still --width {} --height {} --autofocus-on-capture 1 -q 75 --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx708_wide.json -o DAY-AF1-q75--tuningfile-imx708_wide-06-21-2024-16-15-20.jpg".format(width, height)
    subprocess.run(command[0],shell=True,executable="/usr/bin/bash")
    imageData = StringIO()
    imageData.write(subprocess.check_output(command, shell=True))
    imageData.seek(0)
    im = Image.open(imageData)
    buffer = im.load()
    imageData.close()
    return im, buffer

报错信息

Still capture image received

    im = Image.open(imageData)
  File "/home/user/.local/lib/python3.9/site-packages/PIL/Image.py", line 3339, in open
    raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7f9df4db80>

问题原因

  1. 无效的subprocess调用:subprocess.run(command[0], ...)完全错误,command是字符串,command[0]仅取了第一个字符(比如'l'),执行的是无意义命令,属于冗余且错误的代码。
  2. 图像数据来源错误:你的libcamera-still命令带了-o参数,会直接把图像保存到指定文件,此时命令的标准输出(subprocess.check_output获取的内容)是程序日志(比如"Still capture image received"),而非图像二进制数据。把日志文本传给PIL,自然无法识别为图像。
  3. IO类型错误:图像是二进制数据,应该用BytesIO而非处理文本的StringIO,即便能拿到图像数据,用StringIO也会导致数据损坏。

修复方案

方案一:直接读取已生成的图像文件(最简单)

既然libcamera-still已经把图像保存到文件,直接用PIL打开该文件即可:

from PIL import Image
import subprocess
from datetime import datetime


def captureTestImage(settings, width, height):
    # 用datetime生成动态文件名,避免覆盖旧文件
    filename = "DAY-AF1-q75--tuningfile-imx708_wide-{}.jpg".format(datetime.now().strftime("%m-%d-%Y-%H-%M-%S"))
    command = f"libcamera-still --width {width} --height {height} --autofocus-on-capture 1 -q 75 --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx708_wide.json -o {filename}"
    
    # 执行捕获命令并检查结果
    result = subprocess.run(command, shell=True, executable="/usr/bin/bash", capture_output=True, text=True)
    if result.returncode != 0:
        raise Exception(f"捕获失败: {result.stderr}")
    
    # 直接从文件读取图像
    im = Image.open(filename)
    buffer = im.load()
    return im, buffer, filename  # 可选返回文件名,方便后续处理

方案二:从标准输出获取图像(不生成本地文件)

如果不想生成本地文件,修改libcamera-still命令,让它把图像输出到标准输出,再用BytesIO处理:

from io import BytesIO
import subprocess
from PIL import Image


def captureTestImage(settings, width, height):
    # -o - 表示将图像输出到标准输出
    command = f"libcamera-still --width {width} --height {height} --autofocus-on-capture 1 -q 75 --tuning-file /usr/share/libcamera/ipa/rpi/vc4/imx708_wide.json -o -"
    
    # 捕获二进制输出
    image_bytes = subprocess.check_output(command, shell=True, executable="/usr/bin/bash")
    
    # 用BytesIO包装二进制数据
    imageData = BytesIO(image_bytes)
    im = Image.open(imageData)
    buffer = im.load()
    imageData.close()
    return im, buffer

额外优化建议

  • 移除重复的import subprocess语句,保持代码整洁。
  • 执行subprocess命令时,添加capture_output=True和手动检查returncode,方便排查命令执行失败问题。
  • 动态生成文件名避免覆盖旧文件,便于后续追溯。

内容的提问来源于stack exchange,提问作者Jshee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:20:54