OSError: image file is truncated (X bytes not processed)解决方案(无需删数据)

问题的原因:没弄懂,毕竟我找到问题图片查看后,也没发现啥问题.....

我的当前环境:数据集图片为jpg格式,图片的量级有点大,估计问题图片有点多,所以不能直接删除或者跳过,所以得找出来,再重新处理后放回原位。

解决方法:读取文件夹下找到异常图片,处理异常图片使之正常。

代码详细说明:

1.读取文件夹找到异常图片

先从数据集的根目录进入,一层一层保存文件夹信息,逐个文件夹的图片进行检查图片是否有问题,若存在问题,将图片重命名,按其一层一层的地址重命名,便于后期修复后移动回原位。为了问题图片统一处理,尤其是大数据集下,会将所有问题图片放到根目录的error文件夹下,error文件夹需要提前创建。

检查图片是否有问题的代码见下,来自参考链接1。

1 #  判断图片是否正常
2 def is_valid_jpg(jpg_file):
3     #  判断jpg文件下载是否完整
4     if jpg_file.split('.')[-1].lower() == 'jpg':
5         with open(jpg_file, 'rb') as f:
6             f.seek(-2, 2)
7             return f.read() == b'\xff\xd9'
8     else:
9         return "this file is not jpg"

2.修复异常图片

对error文件夹下的图片使用opencv读取并另存,另存后的图片应当是没有问题的,会重新异常检测,若无问题,将修复后的图片移动至根目录的ok文件夹下,该文件夹同样需要提前手动创建。这样你就可以看到是否所有图片都修复成功。修复后的图片请按照图片名手动放回原位吧!

以下是修复图片主要代码,同样来自于参考链接1。

 1 #  修复问题图片
 2 def repair_img(root_path):
 3     path = os.path.join(root_path, "error")
 4     _path = os.path.join(root_path, "ok")
 5     for fileName in os.listdir(path):
 6         file_path = os.path.join(path, fileName)
 7         img = cv2.imread(file_path)
 8         new_path = os.path.join(_path, fileName)
 9         cv2.imwrite(new_path, img)
10         if is_valid_jpg(new_path):  # 新存储的图片没有之前的问题了
11             print("OK")  #  这里的代码和完整代码有些许出入,完整代码里面执行的是图片移动到ok的文件夹

至此。

(若您知道以上原理还请在评论区大家一起讨论呀:>

完整代码参考(已带注释):

 1 import os
 2 import cv2
 3 import sys
 4 from random import randint
 5 import shutil
 6 
 7 #  判断图片是否正常
 8 def is_valid_jpg(jpg_file):
 9     #  判断jpg文件下载是否完整
10     if jpg_file.split('.')[-1].lower() == 'jpg':
11         with open(jpg_file, 'rb') as f:
12             f.seek(-2, 2)
13             return f.read() == b'\xff\xd9'
14     else:
15         return "this file is not jpg"
16 
17 #  找出文件夹下所有问题图片,重命名后移动到统一的文件夹,重命名是为了方便后期移动回原位置
18 def filter_jpg(root_path):
19     for package in os.listdir(root_path):  # Cyber
20         if package == 'error':  # 不进入error文件夹,这个文件夹单独存放问题图片
21             continue
22         sub1_path = os.path.join(root_path, package)
23         for pack in os.listdir(sub1_path):  # test
24             sub2_path = os.path.join(sub1_path, pack)  # /dataset/cyber/test
25             for direc in os.listdir(sub2_path):  # first
26                 sub3_path = os.path.join(sub2_path, direc)  # /dataset/cyber/test/first
27                 for filename in os.listdir(sub3_path):
28                     file_path = os.path.join(sub3_path, filename)
29                     ans = is_valid_jpg(file_path)
30                     if ans != True:  # 若图片有问题
31                         newName = package + '_' + pack + '_' + direc + '_' + str(randint(0, 1000))
32                         src = os.path.join(os.path.abspath(sub3_path), filename)
33                         dst = os.path.join(os.path.abspath(sub3_path), newName + '.jpg')
34                         try:
35                             os.rename(src, dst)  # 重命名
36                             shutil.move(dst, os.path.join(root_path, 'error', newName + '.jpg'))  # 移动图片
37                         except:
38                             print("falure")
39                             sys.exit(0)
40                         print(sub3_path)
41                         print(filename)
42 
43 #  修复问题图片后,保存至ok文件夹(这个文件夹要提前创建),后面需要手动移动一下修复后的图片
44 def repair_img(root_path):
45     path = os.path.join(root_path, "error")
46     _path = os.path.join(root_path, "ok")
47     for fileName in os.listdir(path):
48         file_path = os.path.join(path, fileName)
49         img = cv2.imread(file_path)
50         new_path = os.path.join(_path, fileName)
51         cv2.imwrite(new_path, img)
52         if is_valid_jpg(new_path):  # 新存储的图片是ok的
53             os.remove(file_path)
54 
55 
56 if __name__ == '__main__':
57     root_path = "./dataset"
58     filter_jpg(root_path)
59     repair_img(root_path)
View Code

 

参考链接:

https://www.zhihu.com/question/30372655

https://www.cnblogs.com/haifwu/archive/2020/05/07/12846774.html

posted @ 2021-07-11 20:03  achived  阅读(2167)  评论(0编辑  收藏  举报