图像分类模型 - 基于 VGG16 微调
Image Classification
<form method="POST" enctype="multipart/form-data" action="/predict">
<input type="file" name="image">
<input type="submit" value="Upload">
</form>
<h2>Results:</h2>
{% if prediction %}
<p>Predicted Label: {{ prediction }}</p>
<img src="{{ image }}" alt="Uploaded Image" width="300">
{% endif %}
import os
import random
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D, BatchNormalization, GlobalAveragePooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import VGG16
from sklearn.metrics import accuracy_score
# 设置参数
train_dir = 'D:/BS/class/archive/seg_train/seg_train' # 训练集目录
val_dir = 'D:/BS/class/archive/seg_test/seg_test' #目录
classes = os.listdir(train_dir) # 获取类别列表
batch_size = 64 # 批大小
IMG_HEIGHT = 150 # 图像高度
IMG_WIDTH = 150 # 图像宽度
epochs = 10 # 训练轮数
# 创建图像生成器
train_image_generator = ImageDataGenerator(
rescale=1./255, # 归一化
horizontal_flip=True # 水平翻转
)
val_image_generator = ImageDataGenerator(
rescale=1./255 # 归一化
)
train_data_gen = train_image_generator.flow_from_directory(
batch_size=batch_size, # 批大小
directory=train_dir, # 训练集目录
shuffle=True, # 是否打乱数据
target_size=(IMG_HEIGHT, IMG_WIDTH), # 图像大小
class_mode='categorical' # 分类方式
)
val_data_gen = val_image_generator.flow_from_directory(
batch_size=batch_size, # 批大小
directory=val_dir, # 验证集目录
shuffle=True, # 是否打乱数据
target_size=(IMG_HEIGHT, IMG_WIDTH), # 图像大小
class_mode='categorical' # 分类方式
)
total_train = len(train_data_gen) # 训练集样本数
total_val = len(val_data_gen) # 验证集样本数
print("总训练数据批次数:", total_train)
print("总验证数据批次数: ", total_val)
# 加载 VGG16 模型并进行微调
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(IMG_HEIGHT, IMG_WIDTH, 3))
for layer in base_model.layers:
layer.trainable = False
model = Sequential()
model.add(base_model)
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(64, activation='relu'))
model.add(Dense(len(classes), activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
# 训练模型
history = model.fit(
train_data_gen, # 训练集数据生成器
steps_per_epoch=total_train, # 每轮迭代的步数
epochs=epochs, # 训练轮数
validation_data=val_data_gen, # 验证集数据生成器
validation_steps=total_val # 验证集每轮迭代的步数
)
# 绘制训练过程中的准确率和损失值
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.ylabel('Accuracy')
plt.ylim([min(plt.ylim()), 1])
plt.title('Training and Validation Accuracy')
plt.subplot(2, 1, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.ylabel('Cross Entropy')
plt.ylim([0, 1.0])
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()
# 设置图像目录和类别
img_dir = 'D:/BS/class/archive/seg_train/seg_train'
classes = os.listdir(img_dir)
# 构建图像路径列表
img_paths = []
for class_name in classes:
class_dir = os.path.join(img_dir, class_name)
img_names = [img_name for img_name in os.listdir(class_dir) if img_name.endswith('.jpg')]
class_paths = [os.path.join(class_dir, img_name) for img_name in img_names]
img_paths.extend(class_paths)
# 随机选择一部分图像路径
selected_img_paths = random.sample(img_paths, 10)
# 加载测试集数据生成器
test_image_generator = ImageDataGenerator(rescale=1. / 255)
test_data_gen = test_image_generator.flow_from_directory(
batch_size=1,
directory=val_dir,
shuffle=False,
target_size=(IMG_HEIGHT, IMG_WIDTH),
class_mode='categorical'
)
# 获取测试集样本数
total_test = len(test_data_gen)
print("Total testing data batches: ", total_test)
# 进行预测并计算准确率
y_pred = model.predict(test_data_gen)
y_pred_class = np.argmax(y_pred, axis=1)
y_true_class = test_data_gen.classes
class_names = list(test_data_gen.class_indices.keys())
accuracy = accuracy_score(y_true_class, y_pred_class)
print('Accuracy: {:.2f}%'.format(accuracy * 100))
# 随机选择一些测试样本进行展示
for i in range(5):
rand_num = random.randint(0, total_test - 1)
img, label = test_data_gen[rand_num]
img = img[0]
label_name = class_names[np.argmax(label)]
pred_name = class_names[y_pred_class[rand_num]]
plt.title('True Label: {}, Predicted Label: {}'.format(label_name, pred_name))
plt.imshow(img)
plt.show()
# 保存模型
model.save('image_classification_model.h5')
# 加载模型
loaded_model = tf.keras.models.load_model('image_classification_model.h5')
# 预测新图片
def predict_image(image_path):
img = image.load_img(image_path, target_size=(IMG_HEIGHT, IMG_WIDTH))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = x / 255.0
prediction = loaded_model.predict(x)
predicted_class = class_names[np.argmax(prediction)]
return predicted_class
# Flask 框架示例 (需要安装 Flask 库)
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/'
@app.route('/predict', methods=['GET', 'POST'])
def upload_and_predict():
if request.method == 'POST':
file = request.files['image']
if file.filename != '':
file.save(os.path.join('uploads', file.filename))
prediction = predict_image(os.path.join('uploads', file.filename))
return render_template('index.html', prediction=prediction, image=file.filename)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
原文地址: https://www.cveoy.top/t/topic/piBN 著作权归作者所有。请勿转载和采集!