keras入门系列(三)——实现卷积神经网络dog的分类识别

【参考视频网址:】https://space.bilibili.com/45151802/video
(老师讲的特别好,良心推荐)
【dog数据集下载:】https://download.csdn.net/download/weixin_41874898/11434095
【github代码下载:】https://github.com/Seasea77/keras_small_project_19_07_26

1 准备工作

1.1 文件目录

在这里插入图片描述

Raw_img存放收集的四种狗狗,分别放到不同的文件夹,每类180张。(事先创建好,并放好图片)

Resize_img存放Raw_img统一大小后的图片(不用创建,程序检测如果没有会自动创建)

test_img存放测试图片,用于测试训练模型(事先创建好,并放好图片(我放了4张))

dog.h5是生成的h5模型文件

keras_dog_cnn_train.py用于训练模型

keras_dog_cnn_train.py用于测试图片

1.2 continue
# image文件夹下面有:1.jpg 2.jpg 3.jpg 4.jpg 5.jpg
import os
for i in os.listdir("image"):
    if i == "3.jpg":
        continue  # 如果进入循环,跳过下面的步骤
    print(i)

# 1.jpg 2.jpg 4.jpg 5.jpg
1.3 读取和写入中文名图片
import cv2
import numpy as np
import os


# 写入中文名图片,路径和图片中只要包含中文都要用这个
def cv_imwrite(file_path, frame):
    cv2.imencode('.jpg', frame)[1].tofile(file_path)


# 读取中文名图片
def cv_imread(filePath):
    cv_img = cv2.imdecode(np.fromfile(filePath, dtype=np.uint8), -1)
    return cv_img

# img = cv2.imread("4.jpg")  # 读进来是None,文件有问题

# img = cv_imread("11_11_N_11_德国牧羊犬0.jpg")  # 读中文使用这个cv_imread

# img = cv_imread("images/Dog20/Dog20\史宾格犬/7_7_N_7_史宾格犬168.jpg")

# img = cv_imread("images/Dog20/Dog20\史宾格犬\7_7_N_7_史宾格犬168.jpg")
# 这样写会报错,但是用os.path.join()生成的不会报错

i = os.path.join("images/Dog20/Dog20\史宾格犬", "7_7_N_7_史宾格犬168.jpg")  # images\Dog20\Dog20\柯基犬\2_2_N_2_柯基犬125.jpg
img = cv_imread(i)  # 读中文使用这个

img_resize = cv2.resize(img, (100, 100), cv2.INTER_LINEAR)
cv2.imshow("img", img_resize)
cv2.waitKey(0)

2 代码实现

2.1 keras_dog_cnn_train.py

功能:

  • 对Raw_img文件里图片重命名
  • 改变Raw_img里的图片大小尺寸,保存到Resize_img文件夹里面(没有子目录)
  • 训练模型,生成dog.h5文件
import os
import numpy as np
from PIL import Image
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Convolution2D, Activation, MaxPool2D, Flatten, Dense
from keras.optimizers import Adam
import shutil

# 文件重命名
File_path = "Raw_img"
Width = 100
Height = 100
Save_path = "Resize_img"
Nb_class = 4
Nb_batch_size = 64
Nb_epochs = 20


class PreImage(object):
    """
    File_path是未处理照片路径
    Save_path是调整大小后导出照片路径
    """
    def __init__(self, File_path, Save_path, Width=100, Height=100):
        self.path = File_path
        self.width = Width
        self.height = Height
        self.save_path = Save_path

    # 1图片重命名
    def ImageRename(self):
        File_sub_path_list = os.listdir(self.path)
        path_counter = 0
        for File_sub_path in File_sub_path_list:
            file_counter = 0
            for image in os.listdir(os.path.join(self.path, File_sub_path)): #1****************************
                os.rename(os.path.join(self.path, File_sub_path) + "/" + image,
                          os.path.join(self.path, File_sub_path) + "/" + str(path_counter) + "_" + str(file_counter) + ".jpg")
                # 如果出现这次创建的文件名和rename之前的文件名名字相同,则会报错,提示文件已经存在无法创建该文件。
                # os.rename(name1, name2)注意这个地方的name1是要到子root目录
                file_counter = file_counter + 1
            path_counter = path_counter + 1
        print(">>>>>>>重命名成功>>>>>>>>")

    # 2图片大小改变
    def ImageResize(self):
        # if os.path.exists(self.resized_path):
        #     shutil.rmtree(self.resized_path)  # 删除文件夹,无论空不空
        #     # 不适用先删除文件夹指令也行,因为每一次会覆盖上一次5****************************
        #     # os.remove(path)  # 删除文件
        #     # os.removedirs(path)  # 删除空文件夹
        #     # shutil.rmtree(path)  # 递归删除文件夹2****************************

        for root, dirs, files in os.walk(self.path):  
            # root会变化,变化成图片所在的根目录,dirs是当前目录下包括的文件夹
            for filename in files:
                # print(os.path.join(root, filename))
                image = Image.open(os.path.join(root, filename))  # 可以多路径join
                image_RGB = image.convert("RGB")
                image_Resize = image_RGB.resize((self.width, self.height), Image.BILINEAR)
                if not os.path.exists(self.save_path):
                    os.mkdir(self.save_path)
                # print(filename)
                image_Resize.save(os.path.join(self.save_path, os.path.basename(filename)))
                # 保存图片时,必须先对图片进行灰度化或者RGB化3****************************
        print(">>>>>>>图片大小更改成功,保存到当前%s文件夹>>>>>>>>" % self.save_path)


class Training(object):
    """
    File_path:待训练图片路径
    图片输入大小固定100*100,图片种类数量可变.
    """
    def __init__(self, Save_path, Nb_class, Nb_batch_size, Nb_epochs, Width=100, Height=100):
        self.path = Save_path
        self.nb_class = Nb_class
        self.nb_batch_size = Nb_batch_size
        self.nb_epochs = Nb_epochs
        self.width = Width
        self.height = Height

    # 1提取图片矩阵
    def Train(self):
        # 类里面函数之间的调用,也是需要self.Train(),也是需要使用self来实现的.
        Train_img_list = []
        Train_label_list = []
        for image in os.listdir(self.path):
            img = Image.open(os.path.join(self.path, image))
            image_array = np.array(img)
            Train_img_list.append(image_array)
            Train_label_list.append(int(image.split("_")[0]))  # 此处加上一个int
        Train_label_array = np.array(Train_label_list)  # 网络需要传入的是numpy数组而不是list
        Train_img_array = np.array(Train_img_list)
        print(Train_label_array.shape)
        print(Train_img_array.shape)
        # Train_img_array = Train_img_array.reshape(-1, self.width, self.height, 1)  # 这步骤多余.
        Train_img_array = Train_img_array / 255.
        print(type(Train_label_array))
        Train_label_array = np_utils.to_categorical(Train_label_array, 4)

        # IndexError: index 4 is out of bounds for axis 1 with size 4
        # 类标号要从0开始.所以图片rename的时候应该是0开头

        # 模型建立
        model = Sequential()
        model.add(Convolution2D(
            input_shape=(100, 100, 3),
            filters=32,
            kernel_size=(5, 5),
            padding="same"
        ))
        model.add(Activation("relu"))
        model.add(MaxPool2D(
            pool_size=(2, 2),
            strides=(2, 2),
            padding="same"
        ))
        model.add(Convolution2D(
            filters=64,
            kernel_size=(5, 5),
            padding="same"
        ))
        model.add(Activation("relu"))
        model.add(MaxPool2D(
            pool_size=(2, 2),
            strides=(2, 2),
            padding="same"
        ))
        model.add(Flatten())
        model.add(Dense(1024))
        model.add(Activation("relu"))
        model.add(Dense(512))
        model.add(Activation("relu"))
        model.add(Dense(256))
        model.add(Activation("relu"))
        model.add(Dense(self.nb_class))
        model.add(Activation("softmax"))

        # 模型编译
        adam = Adam(lr=0.001)
        model.compile(
            loss="categorical_crossentropy",
            optimizer=adam,
            metrics=["accuracy"]
        )

        # 模型启动
        model.fit(
            x=Train_img_array,
            y=Train_label_array,
            batch_size=self.nb_batch_size,
            epochs=self.nb_epochs,
            verbose=1
        )
        model.save("./dog.h5")


if __name__ == "__main__":

    """第一个类:预处理图片"""
    DogProcess = PreImage(File_path, Save_path, Width, Height)
    # # 图片重命名
    DogProcess.ImageRename()
    # # 图片大小尺寸改变
    DogProcess.ImageResize()

    """第二个类:训练模型"""
    DogTraining = Training(Save_path, Nb_class, Nb_batch_size, Nb_epochs)
    DogTraining.Train()
2.2 keras_dog_cnn_predict.py

功能:加载模型,预测test_img的图片

from keras.models import load_model
from PIL import Image
import numpy as np
import os


class PredImage(object):
    def __init__(self, Model_name, Test_image):
        self.model_name = Model_name
        self.test_image = Test_image

    def Class_dog(self, prediction):
        Final_prediction = np.argmax(prediction)
        dog_name_list = ["哈士奇", "柯基犬", "藏獒", "金毛"]
        for i in range(4):
            if Final_prediction == i:
                print("输出结果为:", dog_name_list[i])

    def Predict(self):
        model = load_model(self.model_name)
        img = Image.open(self.test_image)
        img_rgb = img.convert("RGB")
        img_resize = img_rgb.resize((100, 100), Image.BILINEAR)
        img_array = np.array(img_resize)
        img_array = img_array / 255.
        img_array = img_array.reshape(-1, 100, 100, 3)
        prediction = model.predict(img_array)
        print(prediction)
        self.Class_dog(prediction)


test_dir = "./test_img"
for img in os.listdir(test_dir):
    PredictImage = PredImage("dog.h5", os.path.join(test_dir, img))
    PredictImage.Predict()

2.3 识别结果

(1)test_img内容为:在这里插入图片描述
(2)测试结果为:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值