猫狗识别简介(附带源码)

目录

项目背景与目的

数据来源

1. 准备工作:环境设置与数据加载

 2.数据加载

3.数据预处理

3.1 图片处理

3.2 生成器

4.模型构建

5.模型编译与训练

训练过程:

6.模型评估

7. 预测与模型保存

训练模型总结

8.构建基于PyQt5与TensorFlow的猫狗图像分类应用实现

1. 环境准备与库导入

2. 模型加载

3. 图像处理与分类逻辑

4. 用户界面设计

5. 程序入口点

猫狗图像分类应用实现总结


项目背景与目的

在本文中,我们将通过一个实战项目介绍如何使用TensorFlow和Keras构建一个简单的卷积神经网络(CNN),以实现对猫和狗图像的分类任务。这个过程不仅涵盖了数据预处理、模型构建、训练与评估,还包括了模型的保存与预测,旨在为初学者提供一个完整的机器学习项目实践指南。

数据来源

本项目使用的数据集来源于CSDN博主分享的已经分类好的猫狗图片,分为训练集和测试集。

1. 准备工作:环境设置

首先,确保安装了TensorFlow库(没下载在cmd运行下面的pip)。

pip install tensorflow==2.13.0

 2.数据加载

 接下来,导入必要的库和模块,我们定义了图像的大小为150x150像素,以及每次训练的批量大小为64张图片。训练和测试数据分别存储在指定的目录下。

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 参数设置
image_size = (150, 150)
batch_size = 64
train_dir = r"输入你的训练集的路径"
test_dir = r"输入你的测试集的路径"

3.数据预处理

3.1 图片处理

使用ImageDataGenerator进行预处理,包括图像的缩放至150x150像素、归一化(像素值除以255使其位于0-1之间)、以及对训练集进行数据增强(如剪切、缩放、水平翻转等),以增加模型的泛化能力。测试集仅进行归一化处理,保持数据的真实性。

# 创建数据增强器,用于在训练过程中随机变换图像,提升模型泛化能力
# 数据增强器,用于提升模型的泛化能力
train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True
)

# 测试数据集只进行图像大小调整
test_datagen = ImageDataGenerator(rescale=1./255)

3.2 生成器

根据目录生成训练和测试数据的生成器

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=image_size,
    batch_size=batch_size,
    class_mode='binary'
)

test_generator = test_datagen.flow_from_directory(
    test_dir,
    target_size=image_size,
    batch_size=batch_size,
    class_mode='binary'
)

4.模型构建

构建一个基本的CNN模型,包括卷积层、池化层、全连接层以及Dropout层,以防止过拟合。

model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
    MaxPooling2D(2, 2),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Conv2D(128, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Flatten(),
    Dense(512, activation='relu'),
    Dropout(0.5),
    Dense(1, activation='sigmoid')
])

5.模型编译与训练

编译模型后,使用训练数据进行训练,并在每个epoch后使用测试数据进行验证。

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

history = model.fit(
    train_generator,
    steps_per_epoch=len(train_generator),
    epochs=25,
    validation_data=test_generator,
    validation_steps=len(test_generator)
)
  1. 训练过程

  2. 接下来的输出显示了25个训练周期(epochs)中的每一个的训练情况,包括:

  3. 损失(loss):模型在训练集上的平均预测错误,数值越小通常表示模型越好。

  4. 准确率(accuracy):模型在训练集上的正确预测百分比。

  5. 验证损失(val_loss):模型在验证集上的平均预测错误,用于评估模型的泛化能力。

  6. 验证准确率(val_accuracy):模型在验证集上的正确预测百分比,也是评估泛化能力的重要指标。

  7. 随着训练的进行,可以看到训练损失和验证损失逐渐降低,同时训练准确率和验证准确率逐渐提高,表明模型正在学习并泛化到未见过的数据。

 

6.模型评估

loss, accuracy = model.evaluate(test_generator, steps=len(test_generator))
print("Test Accuracy: {:.2f}%".format(accuracy * 100))

训练结束后,模型在测试集上进行最终评估,报告了测试损失和测试准确率。在这个案例中,测试准确率为84.97%,意味着模型在未参与训练和验证的独立数据集上能够正确分类约84.97%的图像。

7. 预测与模型保存

对测试数据进行预测,并保存训练好的模型以便后续使用。

predictions = model.predict(test_generator, steps=len(test_generator))
model.save("catdog_model.h5")

训练模型总结

通过以上步骤,我们成功创建并训练了一个猫狗图像分类器,模型在测试集上达到了约84.97%的准确率,显示了良好的泛化能力。此外,模型的损失值较低,意味着预测误差较小。此项目不仅展示了深度学习在图像分类任务中的应用,还涉及了数据预处理、模型构建与调优等重要概念,为后续的机器学习项目提供了宝贵的实践经验。

8.构建基于PyQt5与TensorFlow的猫狗图像分类应用实现

利用上面训练好的模型结合了PyQt5图形用户界面库与TensorFlow机器学习框架的简单应用,该应用旨在实现对猫狗图片的自动分类。通过以下关键步骤,我们将了解如何构建这样一个交互式图像识别系统。

1. 环境准备与库导入

  • 基础环境:使用Python作为开发语言,集成PyQt5用于创建GUI界面,以及TensorFlow进行深度学习模型的加载与预测。
  • 关键库导入:导入必要的系统、OS操作、线程管理、Qt库组件,以及图像处理和模型加载所需的库。
  • # 导入系统、操作系统、线程和Qt库相关模块,为图像处理和用户界面提供支持
    import sys
    import os
    import threading
    from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton, QFileDialog, QHBoxLayout, QScrollArea, QMessageBox
    from PyQt5.QtGui import QPixmap
    from PyQt5.QtCore import Qt, pyqtSignal, QObject
    import tensorflow as tf
    import numpy as np
    from tensorflow.keras.preprocessing import image
    

    2. 模型加载

  • 预训练模型:利用tf.keras.models.load_model加载一个预先训练好的猫狗分类模型(.h5文件),此模型应已学会区分猫和狗的图像特征。
# 加载预先训练的猫狗分类模型
# 加载模型
model = tf.keras.models.load_model(r"训练好的模型路径")

3. 图像处理与分类逻辑

  • ImageProcessor:定义一个继承自QObject的类,用于异步处理图像文件。它通过信号result_signal向主线程传递文件名和分类结果,确保UI更新与后台处理线程分离,避免界面卡顿。
    # 定义一个QObject子类,用于处理图像分类任务
    class ImageProcessor(QObject):
        # 定义一个信号,用于发送文件名和分类结果到UI进行更新
        result_signal = pyqtSignal(str, str)  # 发送文件名和识别结果的信号
    
        # 初始化函数,接收待处理的图像文件名
        def __init__(self, filename):
            super().__init__()
            self.filename = filename
  • 处理流程:加载图像、调整尺寸至模型所需输入尺寸、归一化、模型预测,并根据预测概率判断类别。
    # 实现图像处理逻辑,包括加载图像、预处理和模型预测
        def process_image(self):
            try:
                img = image.load_img(self.filename, target_size=(150, 150))
                img_array = image.img_to_array(img)
                img_array = np.expand_dims(img_array, axis=0) / 255.0
                prediction = model.predict(img_array)
                result = "狗" if prediction[0][0] > 0.5 else "猫"
                self.result_signal.emit(self.filename, result)
            except Exception as e:
                print(f"图像处理异常:{e}")

    4. 用户界面设计

  • CatDogClassifierApp:继承自QWidget,负责构建整个应用的界面和逻辑。
    # 定义主应用程序类,继承自QWidget,实现猫狗分类的用户界面
    class CatDogClassifierApp(QWidget):
        # 初始化函数,设置窗口标题
        def __init__(self):
            super().__init__()
            self.setWindowTitle("猫狗识别系统")
            self.initUI()
            self.image_processors = []
  • 初始化UI:设置窗口标题,初始化布局,包括图像预览区、上传按钮、批量处理按钮。
    # 初始化用户界面布局
        def initUI(self):
            layout = QVBoxLayout()
    
            self.preview_area = QScrollArea()
            self.preview_area.setWidgetResizable(True)
            layout.addWidget(self.preview_area)
    
            self.preview_widget = QWidget()
            self.preview_layout = QHBoxLayout()
            self.preview_widget.setLayout(self.preview_layout)
            self.preview_area.setWidget(self.preview_widget)
    
            self.upload_button = QPushButton("上传图像")
            self.upload_button.clicked.connect(self.uploadImage)
            layout.addWidget(self.upload_button)
    
            self.batch_process_button = QPushButton("批量处理")
            self.batch_process_button.clicked.connect(self.batchProcess)
            layout.addWidget(self.batch_process_button)
    
            self.setLayout(layout)
  • 图像上传与展示:通过uploadImage方法实现单图上传,batchProcess方法实现多图批量处理。
    # 实现上传单个图像的功能,选择图像后显示在界面中
        def uploadImage(self):
            filename, _ = QFileDialog.getOpenFileName(self, "选择图像", "", "图像文件 (*.png *.jpg *.jpeg)")
            if filename:
                self.displayImage(filename)
    
        # 实现批量处理功能,选择多个图像后依次处理并显示
        def batchProcess(self):
            filenames, _ = QFileDialog.getOpenFileNames(self, "选择图像", "", "图像文件 (*.png *.jpg *.jpeg)")
            if filenames:
                for filename in filenames:
                    self.displayImage(filename)
  • 结果显示displayImage方法不仅显示图片,还动态添加每个图片的容器,包含图片、结果标签及删除按钮。同时,启动一个新的ImageProcessor线程处理图像,并监听处理结果更新UI
    # 显示图像及其分类结果在用户界面中 - 修正后的布局逻辑
        def displayImage(self, filename):
            
            if not os.path.isfile(filename):
                QMessageBox.warning(self, "警告", "文件路径不安全或文件不存在")
                return
            
            # 查找并移除可能存在的旧容器(如果之前已经添加过)
            for i in reversed(range(self.preview_layout.count())):
                item = self.preview_layout.itemAt(i)
                if item.widget() and item.widget().objectName().startswith(f"container_{filename}"):
                    widget_to_remove = item.widget()
                    self.preview_layout.removeWidget(widget_to_remove)
                    widget_to_remove.deleteLater()
            
            # 创建一个包含图片和删除按钮的垂直布局容器
            container = QWidget()
            container.setObjectName(f"container_{filename}")  # 为容器设置唯一标识
            container_layout = QVBoxLayout(container)
            container_layout.setContentsMargins(0, 0, 0, 0)  # 移除内边距
    
             # 图片显示
            pixmap = QPixmap(filename)
            preview_label = QLabel(container)
            preview_label.setPixmap(pixmap)
            preview_label.setAlignment(Qt.AlignCenter)
            container_layout.addWidget(preview_label)
    
            # 删除按钮
            delete_button = QPushButton("删除", container)
            delete_button.setObjectName(f"button_{filename}")
            delete_button.clicked.connect(lambda _, fn=filename: self.deleteImage(fn))
            container_layout.addWidget(delete_button)
    
            result_label = QLabel("", container)
            result_label.setObjectName(f"result_{filename}")
            result_label.setAlignment(Qt.AlignCenter)
            container_layout.addWidget(result_label)
            
            # 将包含图片和删除按钮的容器加入到主布局中
            self.preview_layout.addWidget(container)
    
            processor = ImageProcessor(filename)
            processor.result_signal.connect(self.updateUIWithResult)
            threading.Thread(target=processor.process_image).start()
            self.image_processors.append(processor)
    
            #可更改处理图片数量
            if self.preview_layout.count() > 20:
                QMessageBox.warning(self, "警告", "最多只能同时处理20张图像")
                self.image_processors.clear()
        
        # 从用户界面中删除指定的图像及其相关信息
        # 调整deleteImage方法以确保正确删除
        def deleteImage(self, filename):
            container_name = f"container_{filename}"
            container = self.findChild(QWidget, container_name)
            if container:
                self.preview_layout.removeWidget(container)
                container.deleteLater()
            else:
                print(f"Container for {filename} not found to delete.")
  • 结果更新与错误处理:通过updateUIWithResult方法更新图像下方的结果标签,展示预测结果。
    # 修改updateUIWithResult方法
        def updateUIWithResult(self, filename, result):
            container_name = f"container_{filename}"
            container = self.findChild(QWidget, container_name)
            if container:
                # 找到并更新结果标签的文本
                result_label = container.findChild(QLabel, f"result_{filename}")
                if result_label:
                    result_label.setText(f"这是一只{result}!")
                    result_label.setVisible(True)  # 确保结果标签可见
            else:
                print(f"Container for {filename} not found.")

    5. 程序入口点

  • 主循环:使用标准的PyQt5应用启动流程,创建QApplication实例,实例化CatDogClassifierApp,显示窗口,并执行应用事件循环。

  • # 程序入口点
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        window = CatDogClassifierApp()
        window.show()
        sys.exit(app.exec_())

    附上运行出来的程序图片

猫狗图像分类应用实现总结

通过上述步骤,我们构建了一个既具有用户友好界面又具备强大图像识别功能的应用程序。用户可以轻松上传单张或多张猫狗图片,应用将异步处理这些图片,并实时显示分类结果。此项目展示了如何将深度学习模型无缝集成到桌面应用中,提升了用户体验并展示了AI技术的实际应用潜力

  • 29
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值