圖像分類:input圖像——>output每個類別的概率
數(shù)據集的質量直接決定算法的質量
訓練集和測試集文件夾數(shù)相同溺健,并且圖片沒有交集
1. 安裝配置環(huán)境
pip install numpy pandas matplotlib requests tqdm opencv-python
2. 圖像采集
B1栗弟、B2代碼用來獲取網絡圖像
若使用手機或者單反拍照活逆,則不需要B1驱犹、B2代碼
注:刪除無關圖片;類別均衡钦铺;圖片要具有多樣性张漂、代表性、一致性读存;刪除系統(tǒng)自動生成的多余文件和文件夾(B4)(最好在linux中運行)为流;刪除GIF文件(B4)
3. 刪除多余文件
find . -iname '__MACOSX' #當前根目錄
find . -iname '.DS_Store'
find . -iname '.ipynb_checkpoints'
for i in `find . -iname '__MACOSX'`; do rm -rf $i;done
for i in `find . -iname '.DS_Store'`; do rm -rf $i;done
for i in `find . -iname '.ipynb_checkpoints'`; do rm -rf $i;done
4. 下載數(shù)據集
wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/fruit81/fruit81_full.zip
unzip fruit81_full.zip >> /dev/null
# 刪除文件
rm -rf fruit81_full.zip
5. 統(tǒng)計圖像尺寸窜醉、比例分布
import os
import numpy as np
import pandas as pd
import cv2
from tqdm import tqdm
import matplotlib.pyplot as plt
%matplotlib inline
# 指定數(shù)據集路徑
dataset_path = 'fruit81_full'
os.chdir(dataset_path)
os.listdir()
df = pd.DataFrame()
for fruit in tqdm(os.listdir()): # 遍歷每個類別
os.chdir(fruit)
for file in os.listdir(): # 遍歷每張圖像
try:
img = cv2.imread(file)
df = df.append({'類別':fruit, '文件名':file, '圖像寬':img.shape[1], '圖像高':img.shape[0]}, ignore_index=True)
except:
print(os.path.join(fruit, file), '讀取錯誤')
os.chdir('../')
os.chdir('../')
df
#可視化圖像尺寸分布
from scipy.stats import gaussian_kde
from matplotlib.colors import LogNorm
x = df['圖像寬']
y = df['圖像高']
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
# Sort the points by density, so that the densest points are plotted last
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
plt.figure(figsize=(10,10))
# plt.figure(figsize=(12,12))
plt.scatter(x, y, c=z, s=5, cmap='Spectral_r')
# plt.colorbar()
# plt.xticks([])
# plt.yticks([])
plt.tick_params(labelsize=15)
xy_max = max(max(df['圖像寬']), max(df['圖像高']))
plt.xlim(xmin=0, xmax=xy_max)
plt.ylim(ymin=0, ymax=xy_max)
plt.ylabel('height', fontsize=25)
plt.xlabel('width', fontsize=25)
plt.savefig('圖像尺寸分布.pdf', dpi=120, bbox_inches='tight')
plt.show()
圖像尺寸分布
6. 劃分訓練集和測試集
import os
import shutil
import random
import pandas as pd
# 指定數(shù)據集路徑
dataset_path = 'fruit81_full'
dataset_name = dataset_path.split('_')[0]
print('數(shù)據集', dataset_name)
classes = os.listdir(dataset_path)
len(classes)
# 創(chuàng)建 train 文件夾
os.mkdir(os.path.join(dataset_path, 'train'))
# 創(chuàng)建 test 文件夾
os.mkdir(os.path.join(dataset_path, 'val'))
# 在 train 和 test 文件夾中創(chuàng)建各類別子文件夾
for fruit in classes:
os.mkdir(os.path.join(dataset_path, 'train', fruit))
os.mkdir(os.path.join(dataset_path, 'val', fruit))
test_frac = 0.2 # 測試集比例
random.seed(123) # 隨機數(shù)種子,便于復現(xiàn)
df = pd.DataFrame()
print('{:^18} {:^18} {:^18}'.format('類別', '訓練集數(shù)據個數(shù)', '測試集數(shù)據個數(shù)'))
for fruit in classes: # 遍歷每個類別
# 讀取該類別的所有圖像文件名
old_dir = os.path.join(dataset_path, fruit)
images_filename = os.listdir(old_dir)
random.shuffle(images_filename) # 隨機打亂
# 劃分訓練集和測試集
testset_numer = int(len(images_filename) * test_frac) # 測試集圖像個數(shù)
testset_images = images_filename[:testset_numer] # 獲取擬移動至 test 目錄的測試集圖像文件名
trainset_images = images_filename[testset_numer:] # 獲取擬移動至 train 目錄的訓練集圖像文件名
# 移動圖像至 test 目錄
for image in testset_images:
old_img_path = os.path.join(dataset_path, fruit, image) # 獲取原始文件路徑
new_test_path = os.path.join(dataset_path, 'val', fruit, image) # 獲取 test 目錄的新文件路徑
shutil.move(old_img_path, new_test_path) # 移動文件
# 移動圖像至 train 目錄
for image in trainset_images:
old_img_path = os.path.join(dataset_path, fruit, image) # 獲取原始文件路徑
new_train_path = os.path.join(dataset_path, 'train', fruit, image) # 獲取 train 目錄的新文件路徑
shutil.move(old_img_path, new_train_path) # 移動文件
# 刪除舊文件夾
assert len(os.listdir(old_dir)) == 0 # 確保舊文件夾中的所有圖像都被移動走
shutil.rmtree(old_dir) # 刪除文件夾
# 工整地輸出每一類別的數(shù)據個數(shù)
print('{:^18} {:^18} {:^18}'.format(fruit, len(trainset_images), len(testset_images)))
# 保存到表格中
df = df.append({'class':fruit, 'trainset':len(trainset_images), 'testset':len(testset_images)}, ignore_index=True)
# 重命名數(shù)據集文件夾
shutil.move(dataset_path, dataset_name+'_split')
# 數(shù)據集各類別數(shù)量統(tǒng)計表格艺谆,導出為 csv 文件
df['total'] = df['trainset'] + df['testset']
df.to_csv('數(shù)據量統(tǒng)計.csv', index=False)
7. 可視化文件夾中的圖片
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from mpl_toolkits.axes_grid1 import ImageGrid
%matplotlib inline
import numpy as np
import math
import os
import cv2
from tqdm import tqdm
#可視化的文件夾
folder_path = 'fruit81_split/train/西瓜'
# 可視化圖像的個數(shù)
N = 36
# n 行 n 列
n = math.floor(np.sqrt(N))
n
#讀取文件夾中的所有圖像
images = []
for each_img in os.listdir(folder_path)[:N]:
img_path = os.path.join(folder_path, each_img)
img_bgr = cv2.imread(img_path)
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
images.append(img_rgb)
len(images)
#畫圖
fig = plt.figure(figsize=(10, 10))
grid = ImageGrid(fig, 111, # 類似繪制子圖 subplot(111)
nrows_ncols=(n, n), # 創(chuàng)建 n 行 m 列的 axes 網格
axes_pad=0.02, # 網格間距
share_all=True
)
# 遍歷每張圖像
for ax, im in zip(grid, images):
ax.imshow(im)
ax.axis('off')
plt.tight_layout()
plt.show()
8. 圖像分類數(shù)據集探索統(tǒng)計
#各類別數(shù)據個數(shù)柱狀圖
#package
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
#設置中文字體
# # windows操作系統(tǒng)
# plt.rcParams['font.sans-serif']=['SimHei'] # 用來正常顯示中文標簽
# plt.rcParams['axes.unicode_minus']=False # 用來正常顯示負號
# Mac操作系統(tǒng)榨惰,參考 https://www.ngui.cc/51cto/show-727683.html
# 下載 simhei.ttf 字體文件
# !wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf
# Linux操作系統(tǒng),例如 云GPU平臺:https://featurize.cn/?s=d7ce99f842414bfcaea5662a97581bd1
# 運行完畢后重啟 kernel静汤,再從頭運行一次
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf -O /environment/miniconda3/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/SimHei.ttf
!rm -rf /home/featurize/.cache/matplotlib
import matplotlib
matplotlib.rc("font",family='SimHei') # 中文字體
# plt.rcParams['font.sans-serif']=['SimHei'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus']=False # 用來正常顯示負號
#導入數(shù)據集統(tǒng)計表格
df = pd.read_csv('數(shù)據量統(tǒng)計.csv')
df.shape
df
#圖像數(shù)量柱狀圖可視化
# 指定可視化的特征
feature = 'total'
# feature = 'trainset'
# feature = 'testset'
df = df.sort_values(by=feature, ascending=False)
df.head()
plt.figure(figsize=(22, 7))
x = df['class']
y = df[feature]
plt.bar(x, y, facecolor='#1f77b4', edgecolor='k')
plt.xticks(rotation=90)
plt.tick_params(labelsize=15)
plt.xlabel('類別', fontsize=20)
plt.ylabel('圖像數(shù)量', fontsize=20)
# plt.savefig('各類別圖片數(shù)量.pdf', dpi=120, bbox_inches='tight')
plt.show()
plt.figure(figsize=(22, 7))
x = df['class']
y1 = df['testset']
y2 = df['trainset']
width = 0.55 # 柱狀圖寬度
plt.xticks(rotation=90) # 橫軸文字旋轉
plt.bar(x, y1, width, label='測試集')
plt.bar(x, y2, width, label='訓練集', bottom=y1)
plt.xlabel('類別', fontsize=20)
plt.ylabel('圖像數(shù)量', fontsize=20)
plt.tick_params(labelsize=13) # 設置坐標文字大小
plt.legend(fontsize=16) # 圖例
# 保存為高清的 pdf 文件
plt.savefig('各類別圖像數(shù)量.pdf', dpi=120, bbox_inches='tight')
plt.show()
8. 訓練圖像分類模型的方法
Pytorch琅催、MMClassification、fast.ai虫给、Tensorflow藤抡、Keras