我从外部程序(无法控制它)将图像流保存到文件中(例如每 2 秒一次)。当我尝试读取该图像时,有时会在写入时读取该图像,因此我从 OpenCV 收到有关 JPEG 结尾的消息。有没有办法测试文件是否损坏,如果是则等待一段时间然后尝试重新读取它?
谢谢...
我对这个“错误”进行了一些研究,它似乎是 C 语言中的一个警告,Python 无法正确检测到。这是一个非常棘手的问题,发生的原因是图像不完整。检测图像是否正确结束(带有 b'\xff\xd9' 字符)似乎有效:
with open(os.path.join(path, file), 'rb') as f:
check_chars = f.read()[-2:]
if check_chars != b'\xff\xd9':
print('Not complete image')
else:
imrgb = cv2.imread(os.path.join(path, file), 1)
对我有用的解决方案是将文件作为二进制数据读取,然后将其转换为 numpy.array:
img = None
while True:
with open(image_path, 'rb') as img_bin:
buff = StringIO.StringIO()
buff.write(img_bin.read())
buff.seek(0)
temp_img = numpy.array(PIL.Image.open(buff), dtype=numpy.uint8)
img = cv2.cvtColor(temp_img, cv2.COLOR_RGB2BGR)
if img is not None:
break
我发现下面的解决方案更加优雅且不那么冗长。尽管如此,它需要 skimage 包。
from skimage import io
try:
_ = io.imread(path)
img = cv2.imread(path)
# Do stuff with img
except Exception as e:
print(e)
return False
结果 skimage 捕获了异常,而 opencv 没有。因此,在 opencv 之前使用 skimage.io 读取图像应该可以解决问题。
来源:此媒体帖子。
此代码片段可能会帮助您检测和修复具有过早结束错误的图像。
简而言之,它检查图像是否以十六进制“D9”结尾。如果不是,使用opencv读取然后保存图像将恢复适当的格式。
with open( img_path, 'rb') as im :
im.seek(-2,2)
if im.read() == b'\xff\xd9':
print('Image OK :', img_name)
else:
# fix image
img = cv2.imread(img_path)
cv2.imwrite( img_path, img)
print('FIXED corrupted image :', img_name)
来源:此存储库
另一个对我有用的解决方案是使用
pillow
库。
例如,我已将以下
OpenCV
代码更改为 pillow
,所有与 JPEG 相关的警告都消失了:
# img = cv2.imread(img_file_path)
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = PIL.Image.open(img_file_path).convert("RGB")
img = np.asarray(img) # OpenCV RGB image