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)
参考链接:
https://www.zhihu.com/question/30372655
https://www.cnblogs.com/haifwu/archive/2020/05/07/12846774.html