Keras+CNN+Opencv 深度学习初探:狗的品种识别
2019-07-14 本文已影响38人
可乐还是百事好
1.jpg
偷来的金毛镇楼
预测结果
一 介绍:
通过卷积神经网络对哈士奇、拉布拉多、金毛、柯基犬的数据集进行学习 ,训练出一个可以识别出这四种狗的品种的模型 。本文适合有mnist手写数字识别基础的读者观看 ,如果你对深度学习只有一些模糊概念的话,建议你在阅读本文之尝试此篇文章:Keras入门数字手写识别
二 :数据集
数据集 提取码: 1ik1
通过爬虫自行构建的,共2700余张狗的品种图片 ,分别放置在分好类别HSQ、LBLD、JM、KJQ (文件夹之所以设置为英文是因为opencv在open图片时候不支持路径存在中文) 的四个文件夹内 。如果你需要爬虫源码请访问:Github
准备数据集:
图片预处理
class Datasets:
def __init__(self,filepath,fields,image_size):
self.images = []
self.labels = []
self.classs = []
self.rename = []
self.fields = fields
self.filepath = filepath
self.image_size=image_size
def Rename(self):
for field in self.fields:
label = self.fields.index(field)
count = 0
for file in os.listdir(self.filepath+field):
#print(self.filepath+field+'/'+str(label)+'_'+str(count)+field+'.jpg')
count += 1
os.rename(self.filepath+field+'/'+file,self.filepath+field+'/'+str(label+1)+'_'+str(count)+'.jpg')
def Load_img(self):
for field in self.fields:
index = self.fields.index(field)
for file in os.listdir(self.filepath+field):
try:
image = cv2.imread(self.filepath+field+'/'+file)
image = cv2.resize(image, (self.image_size, self.image_size), cv2.INTER_LINEAR)
image = image.astype(np.float32)
image = np.multiply(image, 1.0 / 255.0)
self.images.append(image)
label = np.zeros(len(self.fields))
label[index] = 1.0
self.labels.append(label)
self.classs.append(field)
self.rename.append(file)
except:
continue
images = np.array(self.images)
labels = np.array(self.labels)
fields = np.array(self.classs)
filenm = np.array(self.rename)
return images,labels,fields,filenm
构造一个图片预处理的类Datasets,主要功能就是把图片改名字、并且转为cnn需要的数据类型 。接受三个参数数据集文件夹(总文件夹)、类别(即为分类文件夹名字)以及调整的图像像素大小。
返回的参数为,包含所有图像像素信息的列表的array 、图像分类信息的列表的array ,这里的label的形式为[0,0,1,0]表示属于第三类即:JM(金毛)。fields为labels对应的说明 。
数据读取
def Read_datas(self,validation_size):
class Temp(object):
pass
data_sets = Temp()
images,labels,fields,filenm=self.Load_img()
images,labels,fields,filenm=shuffle(images,labels,fields,filenm)#随机打乱序列
if isinstance(validation_size, float):
validation_size = int(validation_size * images.shape[0])
train_images = images[validation_size:]
train_labels = labels[validation_size:]
train_fields = fields[validation_size:]
train_filenm = filenm[validation_size:]
validation_images = images[:validation_size]
validation_labels = labels[:validation_size]
validation_fields = fields[:validation_size]
validation_filenm = filenm[:validation_size]
data_sets.train = DataSet(train_images, train_labels, train_fields,train_filenm)
data_sets.valid = DataSet(validation_images, validation_labels, validation_fields,validation_filenm)
return data_sets
class DataSet(object):
def __init__(self, images, labels, fields, filenm):
self._num_examples = images.shape[0]
self._images = images
self._labels = labels
self._fields = fields
self._filenm = filenm
self._epochs_done = 0
self._index_in_epoch = 0
@property
def images(self):
return self._images
@property
def labels(self):
return self._labels
@property
def fields(self):
return self._fields
@property
def filenm(self):
return self._filenm
@property
def num_examples(self):
return self._num_examples
@property
def epochs_done(self):
return self._epochs_done
训练数据集
from Load_data import *
import numpy as np
from keras.optimizers import Adadelta
from keras.losses import categorical_crossentropy
from keras.datasets import mnist
from keras.utils import np_utils
from keras.layers import Activation,Conv2D,MaxPool2D,Flatten,Dense,Dropout
from keras.models import Sequential
class Train(object):
"""docstring for Train"""
def __init__(self,epoch,classes,batch_size):
self.epoch = epoch
self.classes = classes
self.batch_size = batch_size
def read_datas(self,filepath,fields,image_size,validation_size):
datasets = Datasets(filepath,fields,image_size).Read_datas(validation_size)
self.train = datasets.train
self.valid = datasets.valid
def train_datas(self):
X_train = self.train.images
Y_train = self.train.labels
X_valid = self.valid.images
Y_valie = self.valid.labels
model = Sequential([
Conv2D(filters=16,kernel_size=(5,5),padding='same',activation='relu',input_shape=(64,64,3)),
MaxPool2D(pool_size=(2,2),strides=(2,2),padding='same'),
Conv2D(filters=32,kernel_size=(5,5),padding='same',activation='relu'),
MaxPool2D(pool_size=(2,2),strides=(2,2),padding='same'),
Dropout(0.5),
Flatten(),
Dense(64,activation='relu'),
Dropout(0.25),
Dense(4,activation='softmax'),
])
model.compile(loss=categorical_crossentropy,
optimizer=Adadelta(),
metrics=['accuracy']
)
model.fit(X_train,Y_train,batch_size=self.batch_size,epochs=self.epoch,validation_data=(X_valid,Y_valie))#validation_data=(X_valid,Y_valie)
model.save("my_model.h6")
if __name__ == '__main__':
a=Train(30,4,64)
a.read_datas(filepath="H:/DogRaw/",fields=["HSQ","JM","LBLD","KJQ"],image_size=64,validation_size=0.1)
a.train_datas()
构造的数据训练类,传入三个参数:训练次数、输出层的分类数、以及batch_size 。
read_datas 函数功能是讲前一部分准备好的数据加载进来 。训练集(X_train,Y_train)验证集(X_valid,Y_valid)。
训练部分采用卷积神经网络隐藏层个数为64层,输出层4层 。
预测图片
import cv2
import numpy as np
from keras.models import load_model
class Pred(object):
"""docstring for Pred"""
def __init__(self,filepath,fileds,image_size,modelfile):
self.fileds = fileds
self.filepath = filepath
self.modelfile = modelfile
self.image_size = image_size
def read_data(self):
image = cv2.imread(self.filepath)
image = cv2.resize(image,(self.image_size,self.image_size))
self.image = np.array(image).reshape(-1,self.image_size,self.image_size,3).astype("float32")/255
def pred_data(self):
model = load_model(self.modelfile)
prediction = model.predict(self.image)
count = 0
for i in prediction[0]:
percent = '%.5f%%'%(i*100)
print(f"{self.fileds[count]}的概率:{percent}")
count += 1
if __name__ == '__main__':
pred = Pred(filepath="HSQ.jpg",fileds=["哈士奇","金毛","拉布拉多","柯基犬"],image_size=64,modelfile="my_model.h5")
pred.read_data()
pred.pred_data()
将上一个部分训练好的模型导入 ,再讲测试的数据图片导入并做好数据处理 ,进行预测
偷来的金毛镇楼
预测结果