OSError: image file is truncated (X bytes not processed)解決方案(無需刪資料)
阿新 • • 發佈:2021-07-11
問題的原因:沒弄懂,畢竟我找到問題圖片檢視後,也沒發現啥問題.....
我的當前環境:資料集圖片為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