第一步:数据预处理
1.生成图片地址和对应标签
def get_files(file_dir):
image_list = []
label_list = []
class_list = []
cate = [file_dir + x for x in os.listdir(file_dir) if os.path.isdir(file_dir + x)] #图片地址
for x in os.listdir(file_dir):
class_list.append(x) # 类别
for index, name in enumerate(cate):
class_path = name + "/"
for file in os.listdir(class_path):
image_list.append(class_path + file) # 存放所有图片地址
label_list.append(index) # 存放所有图片标签
temp = np.array([image_list, label_list]) #将列表转化成数组,维数为(2,?)
temp = temp.transpose() # 转置
#np.random.shuffle(temp) #按第一维打乱数组,从而标签和图片一起被打乱
image_list = list(temp[:, 0]) #所有图片地址
label_list = list(temp[:, 1].astype(np.int)) #所有图片对应的标签并转化成int类型
return image_list, label_list, class_list
代码解释:
os.listdir(file_path):返回指定路径下包含的文件夹的名字列表,这个列表字母顺序排序,不包括‘.’和‘..’
os.path.isdir(path):用于判断对象是否为一个目录
enumerate(cate):获得索引和元素,索引用于标签
2.打乱图片并将标签转化成向量,如有两类,原标签为[1,0],转化后变为[0,1;1,0]
from keras.utils import to_categorical
from sklearn.utils import shuffle
def image_shuffle(image_list, label_list):
# 标签转化成列向量
label_one_hot = to_categorical(label_list)
#print(label_one_hot.shape)
#随机打乱样本
image_list_shuffled, label_one_hot_shuffled = shuffle(image_list, label_one_hot)
return image_list_shuffled, label_one_hot_shuffled
label_one_hot = to_categorical(label_list) # 用于将标签转化成向量,设原标签列表长度为100,5类,则返回标签数组维度为(100,5)
image_list_shuffled, label_one_hot_shuffled = shuffle(image_list, label_one_hot) #打乱图片和对应的标签
第二步:创建数据生成器
由于图片数量大,无法一次性读入内存,所以需要分批读入数据。
import numpy as np
import keras
from PIL import Image
import cv2
class My_Custom_Generator(keras.utils.Sequence):
def __init__(self, image_filenames, labels, batch_size):
self.image_filenames = image_filenames
self.labels = labels
self.batch_size = batch_size
def __len__(self):
return (np.ceil(len(self.image_filenames) / float(self.batch_size))).astype(np.int)
def __getitem__(self, idx):
batch_x = self.image_filenames[idx * self.batch_size: (idx + 1) * self.batch_size]
batch_y = self.labels[idx * self.batch_size: (idx + 1) * self.batch_size]
imgs = []
img_rows = 256
img_cols = 256
for path in batch_x:
img_obj = Image.open(path)
img_array = np.array(img_obj, dtype=np.uint8)
resized = cv2.resize(img_array, (img_rows, img_cols))
# if normalize:
# resized = resized.astype('float32')
# resized /= 127.5
# resized -= 1.
imgs.append(resized)
imgs = np.array(imgs).reshape(len(batch_x), img_rows, img_cols, 3)
# print(imgs.shape)
return imgs, np.array(batch_y)
定义完类后创建数据生成器
my_training_batch_generator = My_Custom_Generator(X_train, y_train, batch_size)
my_validation_batch_generator = My_Custom_Generator(X_val, y_val, batch_size)
第三步、定义训练模型并进行训练
1.定义darknet53中基本单元DarknetConv2D_BN_Leaky,由卷积层,归一化层,激活函数层组成,如图所示
from keras.layers import Conv2D, BatchNormalization, LeakyReLU
def DarknetConv2D_BN_Leaky(X,filters,kernel_size,strides=(1, 1)):
"""Darknet Convol