比賽連結:
- accv官網:https://sites.google.com/view/webfg2020
- 比賽網站:https://www.cvmart.net/race/9917/base
資料下載:
- Baidu / 百度雲盤:
連結: https://pan.baidu.com/s/1P0rpg0J34IUL5bvuA5f-pg
提取碼: cg9z- Google / 谷歌雲盤
https://drive.google.com/drive/folders/1ruvJow2Srp3wuqG1sYd_unG1EHBxYvI-?usp=sharing
Linux下合併解壓:cat train.tar.gz.* | tar -zxv
訓練集:5000類,557,169張圖片
測試集:5000類,100,000張圖片
由於資料來源於網路,可以視為直接從網站上爬蟲下來且字尾全部改成了jpg
格式,而從實際情況來看圖片原本包含的格式有jpg、png、gif、tiff
等,這就會導致使用程式碼讀取的時候報錯(Error)或者警告(Warning),因此需要先對資料進行清洗。Warning由於不會對程式執行造成影響,需要轉換成可報錯的Error,程式碼如下。
import warnings
warnings.filterwarnings('error')
根據實際情況清理出的報錯主要有以下幾種
corrupt EXIF
和Possibly corrupt EXIF
,這種是EXIF資訊缺失導致的,篩選出來再去掉其EXIF頭就可以了
# Refer: https://blog.csdn.net/a19990412/article/details/105940446
# pip install piexif -i https://pypi.tuna.tsinghua.edu.cn/simple/
import piexif
piexif.remove(img_path)
Palette images with Transparency
是在PIL呼叫convert('RGB')
的時候丟擲的,大概是說alpha通道的轉換問題,暫時沒有解決,先把非RGB(通道數不為3)的圖篩選出來,因為後來發現不止4通道圖,還有單通道和雙連結的圖,再單獨對這部分資料篩選報錯的,發現數量較少,直接從資料集中剔除處理。
image file could not be identified because WEBP
,這是由於有的資料原本是webp格式,PIL讀取有問題,而且好像是conda環境下才存在,解決方案有幾種:
pip install Pillow==5.4.1
未知錯誤,在一開始排查沒有查出來,所幸用了screen儲存歷史log,未知錯誤也只有幾張,直接篩選出來了,錯誤資訊如下:
Image size (117762898 pixels) exceeds limit of 89478485 pixels
Metadata Warning, tag 296 had too many entries
Image appears to be a malformed MPO file
完整程式碼:
step1: 遍歷所有圖片,篩選有問題的
import os
from PIL import Image
import cv2
import warnings
warnings.filterwarnings('error')
root = './train'
f1 = open('pExifError.txt', 'w')
f2 = open('rgbaError.txt', 'w')
f3 = open('ExifError.txt', 'w')
f4 = open('4chImg.txt', 'w')
f5 = open('WebpError.txt', 'w')
f6 = open('UnknownError.txt', 'w')
idx = 0
for r, d, files in os.walk(root):
if files != []:
for i in files:
fp = os.path.join(r, i)
try:
img = Image.open(fp)
if(len(img.split()) != 3):
# print('4CH:', fp)
f4.write('{}\n'.format(fp))
except Exception as e:
print('Error:', str(e))
print(fp)
if 'Possibly corrupt EXIF data' in str(e):
print('Exif error')
f1.write('{}\n'.format(fp))
elif 'Palette images with Transparency' in str(e):
print('rgba error')
f2.write('{}\n'.format(fp))
elif 'Corrupt EXIF data' in str(e):
print('pExif error')
f3.write('{}\n'.format(fp))
elif 'image file could not be identified because WEBP' in str(e):
print('Webp error')
f5.write('{}\n'.format(fp))
else:
print('Unknown error')
f6.write('{}\n'.format(fp))
if idx % 5000 == 0:
print('='*20, idx)
idx += 1
f1.close()
f2.close()
f3.close()
f4.close()
f5.close()
f6.close()
step2: 篩選不可轉換的圖片
import warnings
from PIL import Image
warnings.filterwarnings('error')
f1 = open('rgbaError.txt', 'w')
f2 = open('rgbaOK.txt', 'w')
with open('4chImg.txt', 'r')as f:
for i in f.readlines():
i = i.strip()
try:
img = Image.open(i).convert('RGB')
f2.write('{}\n'.format(i))
except Exception as e:
print('Error:', str(e))
print(i)
f1.write('{}\n'.format(i))
f1.close()
f2.close()
step3: 修改和再測試
import os
import piexif
import warnings
from PIL import Image
warnings.filterwarnings('error')
files = ['ExifError.txt', 'pExifError.txt']
for file in files:
with open(file, 'r')as f:
for i in f.readlines():
i = i.strip()
print(i.strip())
piexif.remove(i.strip())
# try:
# img = Image.open(i)
# except Exception as e:
# print('Error:', str(e))
# print(i)
個人習慣把路徑存到txt再在dataset載入。
from sklearn.model_selection import train_test_split
import os
if __name__ == '__main__':
root = './train'
fpath = []
labels = []
for d in os.listdir(root):
fd = os.path.join(root, d)
label = int(d)
for i in os.listdir(fd):
fp = os.path.join(fd, i)
fpath.append(fp)
labels.append(label)
print(len(fpath), len(labels))
x_train, x_val, y_train, y_val = train_test_split(fpath, labels, random_state=999, test_size=0.2)
print(len(x_train), len(x_val))
with open('train.txt', 'w')as f:
for fn, l in zip(x_train, y_train):
f.write('{},{}\n'.format(fn, l))
with open('val.txt', 'w')as f:
for fn, l in zip(x_val, y_val):
f.write('{},{}\n'.format(fn, l))
原資料由於尺寸不一,多數是高清圖片,訓練時resize會很耗時,因此先resize到一個小尺寸儲存起來。Image.thumbnail()
可以起到過濾的作用,如果hw在範圍內就不會resize,超過就會按比例放縮。影象品質和JPG壓縮問題參考部落格1,部落格2。
import os
from PIL import Image
import cv2
import shutil
root = './train'
save_path = './thumbnail'
for r, d, files in os.walk(root):
if files != []:
for i in files:
fp = os.path.join(r, i)
label = i.split('_')[0]
dst = os.path.join(save_path, label)
if not os.path.exists(dst):
os.makedirs(dst)
img = Image.open(fp).convert('RGB')
w, h = img.size
if max(w, h) > 1080:
img.thumbnail((1080, 1080), Image.ANTIALIAS)
img.save(os.path.join(dst, i), quality=95, subsampling=0)
else:
shutil.copy(fp, os.path.join(dst, i))
處理前資料集大小為114G,處理後為86G。
在 Tesla V100 32GB*2
硬體環境下,訓練Baseline,處理前訓練時間一個epoch約為2400s(40min),處理後一個epoch約1400s(23min),極大縮小了訓練時間,精度應該沒有什麼影響,調小判別尺寸應該還能更快,畢竟訓練資料尺寸是224x224。
# ls: labelsmooth
# cat: cat(gmp, gap)
{
model: resnet50,
pool: cat,
init_lr: 0.01,
schedule: cos(warm: 5),
epochs: <60,
loss: ls 0.2,
result: 41.497
}
{
model: resnext50,
pool: cat,
init_lr: 0.01,
shcedule: step(step: 8, gamma: 0.5),
epochs: 60,
loss: ls 0.2,
result: 42.748
}
_(:з」∠)_佛系參賽,等大佬們分享高分solution。