数据准备:需要自己找一张背景图(.png)、导入需要的系膜图片资源(这里我上传了)
1、建立虹膜预测MobileNetV2模型
1.1 设计思路
-
导入必要的库:
- 使用TensorFlow和Keras库来构建、训练和评估模型。
- 导入MobileNetV2作为预训练模型,它在ImageNet数据集上进行了预训练,能够提取图像特征。
-
加载预训练模型 (In[5]):
- 加载MobileNetV2模型,不包括顶层分类器,以便在此基础上添加自定义的分类层。
- 创建Sequential模型,并添加全局平均池化层和两个全连接层,最后一个全连接层使用softmax激活函数来进行多类分类。
-
模型编译 (In[6]):
- 冻结预训练模型的权重,这样在训练过程中,预训练模型的权重不会更新。
- 使用Adam优化器编译模型,并添加权重衰减来减少过拟合。
-
数据准备 (In[7]):
- 定义ImageDataGenerator来对图像进行预处理和增强。
- 从原始数据目录中分离出训练集和验证集,确保每个类别的图像都被适当地分配。
-
创建数据生成器 (In[8] 和 In[9]):
- 使用ImageDataGenerator创建训练和验证数据的生成器,这些生成器能够实时地对图像进行预处理并生成批次。
-
设置模型检查点 (In[21]):
- 定义ModelCheckpoint回调,以便在每个epoch结束后,如果验证集准确度提升,则保存当前最佳模型。
-
模型训练 (In[22]):
- 使用fit方法训练模型,指定训练轮数、训练集生成器、验证集生成器和回调函数。
-
加载和评估最佳模型 (In[23]):
- 加载保存的最佳模型,并使用验证集评估其性能。
-
可视化预测结果 (In[14]):
- 使用matplotlib库展示模型对验证集图像的预测结果,并将真实标签与预测标签进行对比。
-
保存模型 (In[24]):
- 可选步骤,将训练好的模型保存为HDF5文件,以便后续使用或部署。
-
中文显示支持 (In[10]):
- 设置matplotlib的参数以支持中文字符显示,避免在绘制图像时中文乱码。
-
获取类别标签顺序 (In[15]):
- 加载训练数据集,并获取类别标签的顺序,这对于理解模型预测的类别很重要。
1.2 代码的实践
In[1]:
这部分是脚本的开始,导入了必要的库。
import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras import regularizers
tensorflow
和tf.keras
是用于构建和训练深度学习模型的主要库。MobileNetV2
是一个预训练的深度学习模型,用于图像分类任务。Sequential
是Keras中用来构建模型的容器。Dense
、Dropout
和GlobalAveragePooling2D
是Keras中的层类型,分别用于添加全连接层、dropout正则化和全局平均池化。Adam
是一种优化器,用于模型训练中调整权重。ImageDataGenerator
是用于图像数据增强的类。regularizers
用于添加正则化项,以防止模型过拟合。
In[5]:
定义了基于MobileNetV2的模型,不包含顶层分类器,然后添加了新的顶层分类器。
base_model = MobileNetV2(weights='imagenet', alpha=1.0, include_top=False, input_shape=(224, 224, 3))
model = Sequential()
model.add(base_model)
model.add(GlobalAveragePooling2D())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.6))
model.add(Dense(3, activation='softmax'))
model.summary()
MobileNetV2
被加载并使用ImageNet的预训练权重进行初始化。- 新的Sequential模型创建,并添加了全局平均池化层和两个全连接层,最后一个全连接层使用softmax激活函数进行多类分类。
In[6]:
冻结了预训练模型的权重,并编译了整个模型。
base_model.trainable = False
model.compile(optimizer=Adam(lr=0.001, decay=1e-6), loss='categorical_crossentropy', metrics=['accuracy'])
- 冻结权重意味着在训练过程中,预训练模型的权重不会更新。
- 使用Adam优化器和交叉熵损失函数编译模型。
In[7]:
准备数据集,将原始数据集分为训练集和验证集。
original_data_dir = '深度学习——系膜部分'
train_data_dir = 'train_data'
validation_data_dir = 'validation_data'
# ... 数据集划分和复制代码 ...
- 创建了训练和验证数据目录。
- 从原始数据集中复制图像到相应的训练和验证目录。
In[8]:
使用ImageDataGenerator生成训练和验证数据的流。
train_generator = train_datagen.flow_from_directory('train_data', ... )
validation_generator = test_datagen.flow_from_directory('validation_data', ... )
flow_from_directory
方法从指定目录中读取图像,进行数据增强,并生成批次。
In[21]:
定义了模型检查点,以便在验证集准确度提升时保存模型。
checkpoint_path = "best_model"
checkpoint = ModelCheckpoint(checkpoint_path, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
In[22]:
训练模型,并使用检查点。
model.fit(train_generator, steps_per_epoch=len(train_generator), epochs=12, ... )
- 使用
fit
方法训练模型指定的轮数(epochs),并在每个epoch后使用验证集评估模型。
In[23]:
加载最佳模型并评估其在验证集上的性能。
best_model = tf.keras.models.load_model(checkpoint_path)
test_loss, test_acc = best_model.evaluate(validation_generator, steps=9)
In[24]:
保存模型到HDF5文件。
model.save('your_model.h5')
2.运用保存的最优模型并创建界面
2.1 设计思路
设计思路是创建一个基于PyQt5的图形用户界面(GUI)应用程序,用于图像识别任务。以下是详细的设计思路:
-
项目目标:开发一个用户友好的图像识别系统,该系统允许用户选择图像文件,然后对图像进行分析并显示识别结果。
-
技术选择:使用PyQt5作为GUI框架,因为它提供了丰富的组件和良好的跨平台支持。同时,使用TensorFlow和Keras库进行图像处理和模型预测。
-
用户界面设计:
- 主窗口:包含标题栏、工具栏、状态栏以及必要的布局控件。
- 按钮:提供一个按钮让用户选择图像文件。
- 图像显示区域:用于展示用户选择的图像。
- 结果显示区:以文本框形式展示预测结果和相关信息。
-
功能实现:
- 图像选择:通过
QFileDialog.getOpenFileName
方法打开文件对话框,让用户选择图像文件。 - 图像显示:使用
QLabel
控件结合QPixmap
类加载和展示用户选择的图像。 - 模型加载与预测:加载训练好的模型,对用户选择的图像进行预处理后进行预测。
- 结果展示:将预测结果以文本形式展示在界面上,并根据结果设置不同的文本颜色。
- 图像选择:通过
-
图像预处理:将用户选择的图像转换为模型所需的格式,包括调整图像大小、转换为数组、添加批次维度和归一化。
-
模型预测:使用加载的模型对预处理后的图像进行预测,获取预测结果。
-
结果映射:将模型输出的概率映射到具体的类别名称。
-
界面美化:使用
setStyleSheet
方法美化界面元素,如按钮、文本框和标签的样式。 -
交互反馈:通过改变文本颜色来直观地反馈预测结果的置信度(如正常、轻度增生、重度增生)。
-
应用启动:编写主程序代码,初始化应用程序实例,创建主窗口对象,并进入事件循环。
整个设计思路围绕创建一个交互性强、反馈直观的GUI应用程序,使用户能够轻松地进行图像识别操作,并获取清晰的结果反馈。
2.2 设计代码
1.导入必要的库:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QFileDialog, QPixmap, QTextEdit
from PyQt5.QtGui import QIcon, QFont
import tensorflow as tf
import numpy as np
MainWindow
是继承自 QMainWindow
的类,它定义了主窗口的布局和行为。
2.定义 MainWindow
类:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# ... 窗口初始化代码 ...
super().__init__()
: 调用父类QMainWindow
的构造函数,初始化窗口。self.setWindowTitle("系膜识别系统")
: 设置窗口的标题。self.setGeometry(100, 100, 600, 400)
: 设置窗口的位置和大小。self.setStyleSheet("background-color: lightblue;")
: 设置窗口的背景颜色。
3.设置窗口标题、大小和背景颜色:
self.setWindowTitle("系膜识别系统")
self.setGeometry(100, 100, 600, 400)
self.setStyleSheet("background-color: lightblue;")
- 创建
QPixmap
对象,加载背景图片。 - 使用
QLabel
显示背景图片,并调整其大小以适应窗口。
4.设置窗口背景图片:
pixmap = QPixmap("放大镜.png")
self.label = QLabel(self)
self.label.setPixmap(pixmap)
self.label.resize(self.size())
- 创建一个
QPushButton
对象,设置其文本、位置、大小和样式。 - 通过
clicked.connect
将按钮的点击事件与open_image
方法关联。
5.创建“图像选择”按钮并绑定事件:
self.button = QPushButton("图像选择", self)
self.button.setGeometry(125, 20, 150, 30)
self.button.clicked.connect(self.open_image)
- 创建一个
QLabel
对象用于显示选中的图像。 - 设置其位置和大小。
6.创建图像显示标签:
self.image_label = QLabel(self)
self.image_label.setGeometry(50, 60, 300, 300)
self.image_label.setStyleSheet("background-color: transparent;")
7.创建结果显示文本框:
self.result_text = QTextEdit(self)
self.result_text.setGeometry(400, 60, 150, 300)
self.result_text.setReadOnly(True)
- 创建一个
QTextEdit
对象,设置其位置、大小和样式。 - 设置文本框为只读。
8.open_image
方法:
def open_image(self):
# ... 文件对话框和图像加载代码 ...
- 显示文件对话框,让用户选择图像文件。
- 如果选择了文件,加载图像并显示在
image_label
中。 - 对图像进行预处理,然后使用加载的模型进行预测。
- 根据预测结果,设置结果显示在
QTextEdit
中,并改变文本颜色。
9.主程序:
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
icon = QIcon("系膜判别图标.png")
window.setWindowIcon(icon)
window.show()
sys.exit(app.exec())
- 创建
QApplication
实例,初始化PyQt应用。 - 创建
MainWindow
的实例window
。 - 设置应用程序图标。
- 显示窗口并启动事件循环。
3、效果展示及总代码
3.1 效果图
3.2 完整代码
1.模型代码:
import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout,GlobalAveragePooling2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras import regularizers
# # 加载预训练的MobileNetV2模型,并且不包括顶层分类器
base_model = MobileNetV2(weights='imagenet', alpha=1.0, include_top=False, input_shape=(224, 224, 3))
#from keras.applications import VGG16 # 模型名称
#base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
# 创建一个新的顶层分类器
model = Sequential()
model.add(base_model)
model.add(GlobalAveragePooling2D())
model.add(Dense(512, activation='relu')) # 增加神经元数量
model.add(Dropout(0.6))
model.add(Dense(3, activation='softmax')) # 替换num_classes为你的新任务的类别数
# 打印模型结构
model.summary()
# 冻结预训练模型的权重
base_model.trainable = False
# 编译模型
#model.compile(optimizer=Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
# 编译模型,使用Adam优化器结合权重衰减来减少过拟合
model.compile(optimizer=Adam(lr=0.001, decay=1e-6),
loss='categorical_crossentropy',
metrics=['accuracy'])
# 准备数据
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
import os
import shutil
from sklearn.model_selection import train_test_split
# 原始数据目录
original_data_dir = '深度学习——系膜部分'
# 新的训练数据目录和验证数据目录
train_data_dir = 'train_data'
validation_data_dir = 'validation_data'
# 创建训练数据目录和验证数据目录
os.makedirs(train_data_dir, exist_ok=True)
os.makedirs(validation_data_dir, exist_ok=True)
if os.path.exists(train_data_dir):
shutil.rmtree(train_data_dir)
if os.path.exists(validation_data_dir):
shutil.rmtree(validation_data_dir)
os.makedirs(train_data_dir, exist_ok=True)
os.makedirs(validation_data_dir, exist_ok=True)
# 遍历每个类别的文件夹
for class_name in os.listdir(original_data_dir):
class_dir = os.path.join(original_data_dir, class_name)
# 创建类别对应的训练集和验证集目录
os.makedirs(os.path.join(train_data_dir, class_name), exist_ok=True)
os.makedirs(os.path.join(validation_data_dir, class_name), exist_ok=True)
# 获取该类别下的所有图像文件
images = os.listdir(class_dir)
# 将图像数据划分为训练集和验证集
train_images, validation_images = train_test_split(images, test_size=0.3, random_state=42)
# 复制训练集图像到训练集目录
for image in train_images:
src = os.path.join(class_dir, image)
dst = os.path.join(train_data_dir, class_name, image)
if not os.path.exists(dst):
shutil.copy(src, dst)
# 复制验证集图像到验证集目录
for image in validation_images:
src = os.path.join(class_dir, image)
dst = os.path.join(validation_data_dir, class_name, image)
if not os.path.exists(dst):
shutil.copy(src, dst)
# 从目录中获取增强后的训练数据和验证数据
train_generator = train_datagen.flow_from_directory(
'train_data',
target_size=(224, 224),
batch_size=3,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
'validation_data',
target_size=(224, 224),
batch_size=3,
class_mode='categorical')
from tensorflow.keras.callbacks import ModelCheckpoint
# 设置模型保存路径和保存条件
checkpoint_path = "best_model"
checkpoint = ModelCheckpoint(checkpoint_path, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
# 训练模型
model.fit(train_generator,
steps_per_epoch=len(train_generator),
epochs=12,
validation_data=validation_generator,
validation_steps=len(validation_generator),
callbacks=[checkpoint])
# 加载最佳模型
best_model = tf.keras.models.load_model(checkpoint_path)
# 评估模型
test_loss, test_acc = best_model.evaluate(validation_generator, steps=9)
print('Test accuracy:', test_acc)
# 保存为HDF5文件格式
model.save('your_model.h5')
import matplotlib
matplotlib.rcParams['font.family'] = 'SimHei'
best_model = tf.keras.models.load_model('best_model')
import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
for i in range(10):
# 从验证集生成器中获取一个批量的图像数据
batch = next(validation_generator)
# 选择其中一张图像进行预测和展示
image = batch[0][0]
# 显示图像
plt.subplot(2, 5, i+1)
plt.axis('off')
plt.imshow(image)
# 调整图像形状以符合模型预测要求
image = np.expand_dims(image, axis=0)
# 进行预测
y_pred = np.argmax(best_model.predict(image))
# 显示真实标签值和预测值
plt.title(f'标签值:{np.argmax(batch[1][0])}\n预测值:{y_pred}')
plt.show()
import tensorflow as tf
# 加载数据集
train_dataset = tf.keras.preprocessing.image_dataset_from_directory(
'train_data',
labels='inferred',
label_mode='int'
)
# 获取类别标签顺序
class_names = train_dataset.class_names
print("类别标签顺序:", class_names)
2.建模代码
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QTextEdit, QFileDialog
from PyQt6.QtGui import QPixmap,QFont
import tensorflow as tf
import numpy as np
from PyQt6.QtGui import QIcon # 导入QIcon类
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("系膜识别系统")
self.setGeometry(100, 100, 600, 400)#页面总大小
# 设置窗口背景颜色
self.setStyleSheet("background-color: lightblue;")
# 设置窗口背景
pixmap = QPixmap("放大镜.png")
self.label = QLabel(self)
self.label.setPixmap(pixmap)
self.label.resize(self.size())
self.button = QPushButton("图像选择", self)
self.button.setGeometry(125, 20, 150, 30)#按钮大小
self.button.clicked.connect(self.open_image)
self.button.setStyleSheet("font-size: 16px;") # 设置按钮字体大小为16px
self.image_label = QLabel(self)
self.image_label.setGeometry(50, 60, 300, 300)#显示图片的大小
self.image_label.setStyleSheet("background-color: transparent;") # 将背景颜色设置为透明
self.result_text = QTextEdit(self)
self.result_text.setGeometry(400, 60, 150, 300)
self.result_text.setReadOnly(True)
self.result_text.setStyleSheet("border: 2px dashed lightred;") # 将外框样式设置为浅绿色的虚线
def open_image(self):
filename, _ = QFileDialog.getOpenFileName(self, "图像选择", r"C:\Users\11506\Desktop\计算机\大三下实训\深度学习——系膜部分", "Image Files (*.png *.jpg *.jpeg *.bmp)")
if filename:
pixmap = QPixmap(filename)
self.image_label.setPixmap(pixmap)
self.image_label.setScaledContents(True)
# 预处理图像
image = tf.keras.preprocessing.image.load_img(filename, target_size=(224, 224))
image = tf.keras.preprocessing.image.img_to_array(image)
image = np.expand_dims(image, axis=0)
image = image / 255.0
# 使用模型进行预测
# 加载训练好的模型
model = tf.keras.models.load_model('best_model')
predictions = model.predict(image)
class_names = [ '正常','轻度系膜增生', '重度系膜增生'] # 替换为你的类别名称
result = class_names[np.argmax(predictions)]
# 根据预测结果设置文本颜色
color_map = { '正常': 'green','轻度系膜增生': 'yellow', '重度系膜增生': 'red'}
color = color_map.get(result, 'black')
# 设置预测结果显示在 QTextEdit 中,并设置字体样式、大小、颜色以及文本居中
font = QFont()
font.setFamily('Brush Script')
font.setPointSize(50)
self.result_text.setFont(font)
self.result_text.setStyleSheet(f"color: {color}; background-color: lightblue; text-align: center;border: 2px dashed lightred;")
self.result_text.setPlainText(result)
if __name__ == "__main__":
app = QApplication(sys.argv)
# 创建主窗口对象
window = MainWindow()
# 设置图标
icon = QIcon("系膜判别图标.png") # 替换为你的图标文件路径
window.setWindowIcon(icon)
# 显示窗口并启动应用程序事件循环
window.show()
sys.exit(app.exec())