图片分类从数据采集、数据预处理、训练、预测

本文详细介绍了一个基于深度学习的衣物识别系统构建过程,包括数据集的准备、使用VGG16和AlexNet模型的训练及预测流程。涵盖数据预处理、模型搭建、训练策略与评估,以及最终模型的部署。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 1、数据采集
    在这里插入图片描述
    这是数据集的目录,里面放着各类衣服图片。
    下面是这个工程的目录。
    在这里插入图片描述
  • 2.编写代码
    mydata_provider.py:这个是数据处理,将数据编程模型想要的格式。
import numpy as np 
import os 
from PIL import Image
from sklearn.model_selection import train_test_split
label_index = {'yurongfu':7,'maozi': 6, 'weiyi': 5, 'waitao': 4, 'chenshan': 3, 'kuzi': 2, 'qunzi': 1, 'duanxiu': 0};

def loadsample(filename_path, train_x_shape):
    # (220, 220, 3)
    img = Image.open(filename_path).convert("RGB")
    # print(train_x_shape[0], train_x_shape[1], train_x_shape[2], train_x_shape[3]) 17670 32 32 3
    img = img.resize((train_x_shape[1], train_x_shape[2]), Image.ANTIALIAS)
    img = np.array(img)
    if img.shape != tuple(train_x_shape[1:]):
        print(img.shape, filename_path)
    # print("filename_path:", filename_path)
    filename_path_split = filename_path.split("/")
    # print("filename_path_split:", filename_path_split)['..', 'data', 'kuzi', 'img_02024.jpg']
    segment = filename_path_split[-2]
    label = label_index[segment]
    return (img, label)

def load_data(datadir, input_shape, rate = 0.95):
    num_train_examples = 17670 # 样本的总数量
    examples = []
    classNums_dict = {}
    train_x_shape = (num_train_examples,  ) + input_shape
    train_y_shape = (num_train_examples, )
    # print("train_x_shape:", train_x_shape)
    # print("train_y_shape:", train_y_shape)
    train_x = np.empty(train_x_shape, dtype = "uint8") # 这是训练集的train_x
    train_y = np.empty(train_y_shape, dtype = "uint8") # 这是训练集train_y 
    print("train_x_shape:", train_x_shape)
    print("train_y_shape:", train_y_shape)
    # 遍历所有文件,加入到train_x,train_y中。
    samples_index = 0
    dir_list = os.listdir(datadir)
    # print("dir_list:", dir_list) dir_list: ['chenshan', 'kuzi', 'waitao',
    count = 0
    for dir in dir_list:
        # print("dir:", dir)
        classNums_dict[dir] = 0
        classPath = os.path.join(datadir, dir)
        # print("classPath:", classPath) classPath: ../data/maozi
        classNums_dict[dir] = 0
        if os.path.exists(classPath):
            filename_list = os.listdir(classPath)
            # print("filename_list:", filename_list)
            # print("len(filename_list)",len(filename_list))
            for filename in filename_list:
                # 这里获取标签和样本
                if filename.endswith(".jpg"):
                    filename_path = os.path.join(classPath, filename)
                    # print("filename_path:", filename_path)
                    count = count + 1 
                    print("count:", count)
                    classNums_dict[dir] = classNums_dict[dir] + 1
                    (img, label) = loadsample(filename_path, train_x_shape)
                    train_x[samples_index] = img 
                    train_y[samples_index] = label 
                    samples_index = samples_index + 1
                    # test 2
                    examples.append((img, label))
        else:
             print("不存在目录:", (classPath))
       
    train_y = np.reshape(train_y, (len(train_y), 1))
    print(len(train_x), len(train_y))
    print("class distrubtion:", classNums_dict)
    train_x, test_x, train_y,test_y = train_test_split(train_x, train_y, test_size = 1 - rate, stratify = train_y)
    print('part-train-%d,part-test-%d;total:%d'%(len(train_x),len(test_x),len(train_x)+len(test_x)));
    return train_x, train_y, test_x, test_y



if __name__ == "__main__":
    datadir = "../data"
    print("datadir:", datadir)
    load_data(datadir, input_shape = (224, 224, 3))

model.py 这是网络:AleNet,VGG19

from keras.layers import Input
from keras.layers import Conv2D, MaxPool2D, Dense, Flatten, Dropout, Lambda
from keras.models import Model
from keras import optimizers
from keras.utils import plot_model
from keras import backend as K

# VGG16
import tensorflow as tf 
from keras import Model, Sequential
from keras.layers import Flatten, Dense, Conv2D, GlobalAveragePooling2D
from keras.layers import Input, MaxPooling2D, GlobalMaxPooling2D

def VGG16(input_shape=(224,224,3), nclass=8):
    input_ = Input(shape=input_shape)
    # block1
    x = Conv2D(64, (3, 3), activation = "relu", padding = "same", name = "block1_conv1")(input_)
    x = Conv2D(64, (3, 3), activation = "relu", padding = "same", name = "block1_conv2")(x)
    x = MaxPooling2D((2,2), strides = (2, 2), name="block1_pool")(x)
    # block2 
    x = Conv2D(128, (3, 3),activation="relu",padding="same", name="block2_conv1")(x)
    x = Conv2D(128, (3, 3),activation ="relu", padding ="same", name = "block2_conv2")(x)
    x = MaxPooling2D((2,2), strides=(2,2), name="block2_pool")(x)
    # block3
    x = Conv2D(256,(3,3), activation="relu",padding="same", name="block3_conv1")(x)
    x = Conv2D(256,(3,3),activation="relu",padding="same",name="block3_conv2")(x)
    x = Conv2D(256,(3,3),activation="relu", padding="same", name="block3_conv3")(x)
    x = MaxPooling2D((2,2),strides=(2,2), name = "block3_pool")(x)
    # block4
    x = Conv2D(512,(3,3),activation="relu",padding="same",name="block4_conv1")(x)
    x = Conv2D(512,(3,3),activation="relu",padding="same",name="block4_conv2")(x)
    x = Conv2D(512,(3,3),activation="relu",padding="same",name="block4_conv3")(x)
    x = MaxPooling2D((2,2), strides=(2,2),name="block4_pool")(x)
    # block5
    x = Conv2D(512,(3,3),activation="relu",padding="same", name="block5_conv1")(x)
    x = Conv2D(512,(3,3),activation="relu",padding="same",name="block5_conv2")(x)
    x = Conv2D(512,(3,3),activation="relu",padding="same",name="block5_conv3")(x)
    x = MaxPooling2D((2,2), strides=(2,2),name="block5_pool")(x)
    #Classification block
    x = Flatten(name = 'flatten')(x)
    x = Dense(4096,activation = 'relu',name = 'fc1')(x)
    x = Dropout(0.5)(x)
    x = Dense(4096,activation = 'relu',name = 'fc2')(x)
    x = Dropout(0.5)(x)
    output_ = Dense(nclass, activation = 'softmax',name = 'fc3')(x)
    model = Model(inputs=input_, outputs=output_)
    model.summary()
    opti_sgd = optimizers.sgd(lr=0.01, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=opti_sgd, metrics=['accuracy'])
    return model


    
def LRN(alpha=1e-4, k=2, beta=0.75, n=5):
    """
    LRN for cross channel normalization in the original Alexnet
    parameters default as original paper.
    """
    def f(X):
        b, r, c, ch = X.shape
        half = n // 2
        square = K.square(X)
        extra_channels = K.spatial_2d_padding(square, ((0, 0), (half, half)), data_format='channels_first')
        scale = k 
        for i in range(n):
            scale += alpha * extra_channels[:,:,:,i:i+int(ch)]
        scale = scale ** beta
        return X / scale
    return Lambda(f, output_shape=lambda input_shape: input_shape)
def alexnet(input_shape=(224,224,3), nclass=8):
    """
    build Alexnet model using keras with TensorFlow backend.
    :param input_shape: input shape of network, default as (224,224,3)
    :param nclass: numbers of class(output shape of network), default as 1000
    :return: Alexnet model
    """
    # conv1
    input_ = Input(shape=input_shape)
    x = Conv2D(96, kernel_size=(11, 11), strides=(4, 4), activation='relu')(input_)
    x = LRN()(x)
    x = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(x)
    # conv2 
    x = Conv2D(256, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding='same')(x)
    x = LRN()(x)
    x = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(x)
    # conv3
    x = Conv2D(384, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same')(x)
    # conv4
    x = Conv2D(384, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same')(x)
    # conv5
    x = Conv2D(256, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same')(x)
    x = MaxPool2D(pool_size=(3, 3), strides=(2, 2))(x)
    x = Flatten()(x)
    # fc6 
    x = Dense(4096, activation='relu')(x)
    x = Dropout(0.5)(x)
    # fc7
    x = Dense(4096, activation='relu')(x)
    x = Dropout(0.5)(x)
    # fc8
    output_ = Dense(nclass, activation='softmax')(x)
    model = Model(inputs=input_, outputs= output_)
    model.summary()
    opti_sgd = optimizers.sgd(lr=0.01, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=opti_sgd, metrics=['accuracy'])
    return model 

if __name__ == "__main__":
    model = alexnet()
    plot_model(model, "Alexnet.png", show_shapes=True)# 保存模型图

train.py:这个是训练

import tensorflow as tf 
import numpy as np 
import keras
from mydata_provider import load_data
from mymodel import alexnet
def train():
    num_classes = 8
    batchsize = 64
    epochs = 20
    input_shape = (224, 224, 3)
    dir_root = "../data"
    save_path = "../model.h5"
    train_x, train_y, test_x, test_y = load_data(dir_root, input_shape=input_shape)

    train_y = keras.utils.to_categorical(train_y, num_classes)
    test_y = keras.utils.to_categorical(test_y, num_classes)

    train_x = train_x.astype("float32")
    test_x = test_x.astype("float32")

    train_x = train_x / 255.0 
    test_x = test_x / 255.0 
    model = alexnet(input_shape, num_classes)
    model.summary()
    
    History = model.fit(train_x, train_y, batch_size=batchsize,epochs=epochs, validation_data = (train_x, train_y), shuffle = True)
    print("History-Train:", History, History.history)
    metrics = model.evaluate(test_x, test_y)
    print("metrics:", metrics)
    # 保存模型
    model.save(save_path)


if __name__ == "__main__":
    train()

myinference.py这是预测

import os 
import tensorflow as tf 
import numpy as np 
from PIL import Image
import tensorflow.keras as keras
from tensorflow.keras.models import load_model
from tensorflow.keras.utils import plot_model

index_label = {1:'短袖',2:'裙子',3:'裤子',4:'衬衫',5:'外套',6:'卫衣',7:'帽子',8:'羽绒服'}
# 进行预测
def inference(path, model_path, visual=False):
    # load model 
    if not os.path.exists(model_path):
        print("No model is here:%s, try again~"%(model_path))
    model = load_model(model_path)
    if visual:
        model_plot = "./model.png"
        plot_model(model, to_file=model_plot, show_shapes=True)
    # 判断路径是目录还是路径
    if os.path.isdir(path):
        print("Direc:%s\n(only infer 4 imgs...)"%(path))
        fileName_list = os.listdir(path)
        img_paths = []
        results = []
        img_count = 0
        for fileName in fileName_list:
            if fileName.endswith(".jpg"):
                img_paths.append(os.path.join(path, fileName))
                img_count = img_count + 1
        x_predict = np.empty((img_count, 224, 224, 3), dtype="float32")
        for index in range(img_count):
            img = Image.open(img_paths[index]).convert('RGB')
            img = img.resize((224, 224), Image.ANTIALIAS)
            img = np.array(img)
            img = img / 255
            x_predict[index] = img 
        y_predict = model.predict(x_predict)
        print("Inference:")
        for index in range(img_count):
            res = np.argmax(y_predict[index]) + 1
            results.append(index_label[res])
            print(img_paths[index],'-->',results[index]);
    else:
        print("File:%s\n"%(path))
        if path.endswith(".jpg"):
            x_pre = np.empty((1, 224, 224, 3), dtype="float32")
            img = Image.open(path).convert("RGB")
            img = img / 255.0 
            x_pre[0] = img 
            y_pre = model.predict(x_pre)
            res = np.argmax(y_pre[0] + 1)
            print("单张预测res:\n %s -> %s"%(path, index_label[res]))
        else:
            print("just for jpg")
if __name__ == "__main__":
    print("--Inference--")
    # path = input("Please Input a path(相对路径):\n")
    path = "../someimgs"

    inference(path, "../model.h5")
    
            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值