Keras+CNN+Opencv 深度学习初探:狗的品种识别

作者: 可乐还是百事好 | 来源:发表于2019-07-14 14:36 被阅读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()
    

    将上一个部分训练好的模型导入 ,再讲测试的数据图片导入并做好数据处理 ,进行预测


    偷来的金毛镇楼
    预测结果

    相关文章

      网友评论

        本文标题:Keras+CNN+Opencv 深度学习初探:狗的品种识别

        本文链接:https://www.haomeiwen.com/subject/ccgbkctx.html