尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

YOLOv8+PyQt5皮肤病检测系统:从训练到自适应界面落地

发布时间:2026/9/28 23:54:05

资讯中心
01
ARTICLE

YOLOv8+PyQt5皮肤病检测系统:从训练到自适应界面落地

YOLOv8+PyQt5皮肤病检测系统:从训练到自适应界面落地
简介这份毕设参考资源面向计算机视觉方向的本科与研究生毕业生提供一套基于YOLOv8与PyQt5的常见皮肤病辅助检测系统完整实现可用于毕业设计选题、课程项目或算法落地练习。压缩包共85个文件约34.32MB包含20个py源码文件、26个pyc编译文件、15张png界面素材、3个pt模型权重以及ui、qrc、css、ttf等界面与字体资源覆盖模型推理、界面布局、样式美化与配置管理等模块。项目以YOLOv8完成皮肤病图像中病变区域的识别与分类借助PyQt5实现自适应不同屏幕尺寸的交互界面支持摄像头实时采集与本地图片导入并配有训练脚本、检测工具与运行说明文档。目前已有183人学习下载读者可据此理清从数据准备、模型训练到界面集成的完整链路快速搭建可演示的辅助检测原型并参考其目录组织与排错思路完成自己的毕设开发。1. 从一份毕设压缩包说起yolov8pyqt5 皮肤病辅助检测系统到底在做什么很多同学拿到「基于yolov8pyqt5自适应界面设计的常见皮肤病辅助检测系统」这个题目时第一反应是去搜 yolov8下载、pyqt5安装然后卡在环境上三天。我当年帮人看这类毕设最常见的翻车现场不是模型训不出来而是训练脚本跑通了界面却连图片都传不进去。这套系统的本质其实很朴素用 YOLOv8 做皮肤病灶区域的检测与分类用 PyQt5 做一个能自适应窗口大小的桌面端界面把「选图—推理—显示结果」这条链路串起来。它适合两类人一类是需要一个能跑通、能答辩、能写论文的完整毕设另一类是想练手「模型落地到桌面应用」这条工程链路的开发者。核心难点从来不在 YOLOv8 本身而在于数据集标注质量、界面与推理线程的配合、以及自适应布局这三个容易被忽略的地方。下面我按自己实际搭过一遍的顺序把选型、训练、界面、踩坑讲清楚。2. 数据集与模型选型为什么是 YOLOv8 而不是分类网络2.1 皮肤病检测任务的本质是「定位分类」而不是纯分类很多人第一反应是用 ResNet 做图像分类输入一张皮肤图输出是哪种病。这个思路在毕设里能跑但答辩时老师一句「病灶在图片哪个位置」就把你问住了。皮肤病的实际场景里一张图可能有多个病灶或者病灶只占画面一小块纯分类网络会把整张图的背景噪声也学进去。YOLOv8 是单阶段目标检测一次前向就输出边界框和类别天然适合「一张图里找病灶并判断类型」这个需求。常见皮肤病数据集一般包含带状疱疹、湿疹、银屑病、痤疮、荨麻疹等几类每类几十到几百张不等。我一般建议至少每类 150 张以上否则 YOLOv8 的 mAP 会很难看。选 YOLOv8 而不是 YOLOv5 的理由也很实际Ultralytics 这套库把训练、验证、导出、推理全封装成一行命令对毕设这种「时间紧、要出图、要写论文」的场景非常友好。yolov8n 权重只有 6MB 左右gtx1660ti 这种老卡也能跑甚至 ubuntu20.04 搭建 yolov8 环境 cpu 版本也能勉强推理。如果你只是做毕设演示yolov8n 或 yolov8s 足够想冲论文指标再上 yolov8m。2.2 用 labelme 标注后转 YOLO 格式的完整流程热词里 labelme 无法安装 pyqt5 是个高频问题因为 labelme 本身依赖 PyQt5版本冲突很常见。我的做法是给 labelme 单独建一个虚拟环境别和主项目混在一起。# 给标注工具单独建环境避免和主项目 PyQt5 版本打架 conda create -n labelme_env python3.9 -y conda activate labelme_env pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple # 启动标注 labelme标注时选「创建矩形」框住病灶标签名用英文如 eczema、psoriasis别用中文否则后面转换脚本容易出编码问题。标完每张图会生成一个同名 .json 文件。接下来要转成 YOLO 需要的 txt 格式每行是类别id 中心x 中心y 宽 高且都是归一化到 0-1 的值。import json import os from pathlib import Path # 类别映射顺序要和 data.yaml 里的 names 完全一致 class_map {eczema: 0, psoriasis: 1, acne: 2, urticaria: 3} json_dir Path(labels_json) out_dir Path(labels_txt) out_dir.mkdir(exist_okTrue) for jf in json_dir.glob(*.json): data json.loads(jf.read_text(encodingutf-8)) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue pts shape[points] xs [p[0] for p in pts] ys [p[1] for p in pts] # 转成中心点宽高的归一化格式 cx (min(xs) max(xs)) / 2 / img_w cy (min(ys) max(ys)) / 2 / img_h w (max(xs) - min(xs)) / img_w h (max(ys) - min(ys)) / img_h lines.append(f{class_map[label]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) (out_dir / (jf.stem .txt)).write_text(\n.join(lines), encodingutf-8)这段脚本的关键参数是class_map它必须和后面 data.yaml 里的names顺序严格对应错一位整个训练标签就全乱了。cx/cy/w/h都除以了图像宽高做归一化这是 YOLO 格式的硬性要求不归一化训练时 loss 会直接爆炸。转换完记得抽查几个 txt用cat看一眼数值是不是都在 0-1 之间。2.3 data.yaml 与目录结构一个字母错就白训YOLOv8 要求的数据集目录结构是固定的我见过太多人因为路径写错导致训练时提示「no labels found」。# data.yaml path: /home/user/skin_dataset # 数据集根目录绝对路径最稳 train: images/train val: images/val nc: 4 # 类别数必须和 class_map 数量一致 names: [eczema, psoriasis, acne, urticaria]目录长这样skin_dataset/images/train、skin_dataset/images/val、skin_dataset/labels/train、skin_dataset/labels/val。注意 images 和 labels 是平级的两棵子树YOLO 会自动去 labels 下找同名 txt。常见错误是把 txt 和图片放同一个文件夹或者 train/val 划分比例失衡。我一般按 8:2 划分验证集至少留 30 张否则 val 的 mAP 波动大得没法写进论文。3. 训练、验证与损失曲线把 yolov8 训到能答辩3.1 环境搭建与预训练权重下载yolov8环境配置其实不复杂但版本要对。我的组合是 Python 3.9 torch 2.0 ultralytics 8.x。如果你只有 CPUubuntu20.04 搭建 yolov8 环境 cpu 版本也能跑只是训练慢建议直接用预训练权重做推理演示。conda create -n skin_yolo python3.9 -y conda activate skin_yolo # 装 pytorch有显卡的按自己 cuda 版本去官网选命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple # 验证安装 yolo checksyolo checks会打印出你的 torch 版本、cuda 是否可用、以及 ultralytics 版本。如果 cuda 显示 False 但你明明有显卡八成是 torch 装成了 cpu 版重装即可。yolov8预训练权重下载不用手动找第一次训练时 ultralytics 会自动从官方源拉 yolov8n.pt网络不好就手动下载后放到项目根目录训练时用modelyolov8n.pt指定本地路径。3.2 训练命令与关键参数含义yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ patience30 \ projectruns/skin \ nameexp1逐个说参数epochs150是训练轮数皮肤病数据集小100-200 之间比较合适太多会过拟合。imgsz640是输入分辨率显存不够就降到 416 或 320但小病灶会漏检。batch16看显存gtx1660ti 6G 跑 640 大概能到 16爆显存就减半。lr00.01是初始学习率YOLOv8 默认带余弦退火一般不用大改。patience30是早停30 轮没提升就停省时间。训练完权重在runs/skin/exp1/weights/best.pt。3.3 画损失函数曲线论文里必须有的一张图yolov8画损失函数曲线图不用自己写训练完results.csv就在 exp1 目录下里面记录了每轮的 box_loss、cls_loss、dfl_loss 和 mAP。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/skin/exp1/results.csv) df.columns [c.strip() for c in df.columns] # 列名可能带空格先清理 fig, ax1 plt.subplots(figsize(10, 6)) ax1.plot(df[epoch], df[train/box_loss], labelbox_loss) ax1.plot(df[epoch], df[train/cls_loss], labelcls_loss) ax1.set_xlabel(epoch) ax1.set_ylabel(loss) ax1.legend(locupper right) ax2 ax1.twinx() ax2.plot(df[epoch], df[metrics/mAP50(B)], colorred, labelmAP50) ax2.set_ylabel(mAP50) ax2.legend(loclower right) plt.title(YOLOv8 training curve) plt.savefig(loss_curve.png, dpi200)这段代码把 loss 和 mAP 画在同一张图上双 y 轴。判断训练好坏的土办法box_loss 和 cls_loss 应该整体下降并趋于平缓如果 cls_loss 一直震荡不降多半是标签类别不平衡或者标注框画得太随意。mAP50 能到 0.7 以上毕设答辩就稳了。4. PyQt5 自适应界面把模型塞进桌面应用4.1 自适应布局的核心是 QLayout 而不是固定坐标pyqt5界面设计新手最容易犯的错是用setGeometry写死每个控件的位置结果换个分辨率界面就散架。自适应界面的正确做法是用布局管理器主窗口用 QVBoxLayout 竖着分三块顶部工具栏、中间图像区、底部结果区中间图像区用 QHBoxLayout 横着放原图和结果图。这样窗口拉伸时控件自动跟着变。from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog) from PyQt5.QtGui import QPixmap from PyQt5.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(皮肤病辅助检测系统) self.resize(1000, 700) central QWidget() self.setCentralWidget(central) root QVBoxLayout(central) # 顶部按钮栏 top QHBoxLayout() self.btn_open QPushButton(选择图片) self.btn_detect QPushButton(开始检测) top.addWidget(self.btn_open) top.addWidget(self.btn_detect) top.addStretch() # 弹簧把按钮推到左边 root.addLayout(top) # 中间图像区左右两张图 mid QHBoxLayout() self.lbl_src QLabel(原图) self.lbl_res QLabel(检测结果) for lbl in (self.lbl_src, self.lbl_res): lbl.setAlignment(Qt.AlignCenter) lbl.setMinimumSize(300, 300) lbl.setStyleSheet(border: 1px solid #ccc;) mid.addWidget(lbl) root.addLayout(mid, stretch1) # stretch1 让图像区占满剩余空间 # 底部结果文字 self.lbl_info QLabel(等待检测) root.addWidget(self.lbl_info) self.btn_open.clicked.connect(self.open_image) def open_image(self): path, _ QFileDialog.getOpenFileName(self, 选图, , Images (*.png *.jpg *.jpeg)) if path: self.current_path path pix QPixmap(path).scaled(self.lbl_src.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) self.lbl_src.setPixmap(pix) if __name__ __main__: app QApplication([]) w MainWindow() w.show() app.exec_()关键点是root.addLayout(mid, stretch1)这个 stretch 让图像区吃掉所有多余空间窗口拉大时图片区跟着变大这就是「自适应」的本质。Qt.KeepAspectRatio保证图片缩放不变形。top.addStretch()是弹簧把按钮挤到左边不加的话按钮会平均分布很难看。4.2 推理线程与界面刷新别让界面卡死直接在按钮回调里跑model.predict()会让界面卡住几秒用户体验极差答辩时老师会以为你程序崩了。正确做法是把推理放到 QThread 里通过信号把结果传回主线程。from PyQt5.QtCore import QThread, pyqtSignal from ultralytics import YOLO class DetectThread(QThread): finished pyqtSignal(object, list) # 传回绘制后的图 检测信息 def __init__(self, model, img_path): super().__init__() self.model model self.img_path img_path def run(self): results self.model.predict(self.img_path, conf0.25, imgsz640) r results[0] # plot() 返回带框的 numpy 图BGR 格式 annotated r.plot() infos [] for box in r.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) infos.append(f{self.model.names[cls_id]}: {conf:.2f}) self.finished.emit(annotated, infos)conf0.25是置信度阈值低于这个的框不显示皮肤病场景建议 0.25-0.4太低会框出一堆误检。r.plot()是 ultralytics 自带的绘图函数直接返回画好框的图省得自己写 cv2.rectangle。信号finished用object类型传 numpy 数组主线程收到后转成 QImage 再显示。这样推理在后台跑界面不卡进度条也能正常转。4.3 结果图从 numpy 到 QLabel 的转换numpy 数组不能直接塞给 QLabel中间要过一道 QImage。import cv2 from PyQt5.QtGui import QImage, QPixmap def show_result(self, annotated, infos): # ultralytics 返回的是 BGR转成 RGB rgb cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qimg QImage(rgb.data, w, h, ch * w, QImage.Format_RGB888) pix QPixmap.fromImage(qimg).scaled(self.lbl_res.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) self.lbl_res.setPixmap(pix) self.lbl_info.setText( | .join(infos) if infos else 未检测到病灶)ch * w是每行字节数这个参数写错图会花屏是血泪经验。Format_RGB888对应三通道 RGB别用 Format_BGR888Qt 没这个格式。检测信息拼成字符串显示在底部答辩时一眼能看到类别和置信度。5. 避坑与排查那些让我熬夜的翻车现场5.1 训练时提示 no labels found现象yolo detect train跑起来后警告一堆图片找不到标签mAP 全程为 0。原因data.yaml 里的 path 和实际目录对不上或者 labels 文件夹名拼错写成 label 少个 s。解决用ls skin_dataset/labels/train | head确认 txt 存在再检查 data.yaml 的 path 是不是绝对路径。相对路径在不同工作目录下启动会失效一律用绝对路径最稳。5.2 pyqt5 界面显示中文乱码或方框现象按钮上的中文变成方块。原因系统缺中文字体或者代码文件编码不是 utf-8。解决文件头加# -*- coding: utf-8 -*-并在 QApplication 创建前设置字体app.setFont(QFont(Microsoft YaHei, 10))Linux 下换成WenQuanYi Micro Hei。别用默认字体跨平台必翻车。5.3 labelme 装不上或和主项目 PyQt5 冲突现象pip install labelme后主项目的 PyQt5 报版本错误或者 labelme 启动闪退。原因labelme 依赖的 PyQt5 版本和你主项目不一致装在一起互相覆盖。解决给 labelme 单独建 conda 环境标注和训练用两个环境互不干扰。这是最省心的做法别想着一个环境走天下。5.4 推理时显存不足 CUDA out of memory现象训练能跑推理时爆显存。原因PyQt5 主进程已经占了一部分显存模型加载又占一块。解决推理时把imgsz降到 416或者用model.predict(..., devicecpu)强制走 CPU。毕设演示对速度要求不高CPU 推理一张图一两秒也能接受稳定性优先。5.5 自适应界面拉伸后图片变形现象窗口拉大图片被拉扁。原因QLabel 的 scaled 没加Qt.KeepAspectRatio或者 QLabel 本身没设 minimumSize 导致布局算不出比例。解决scaled 一定带 KeepAspectRatioQLabel 设 minimumSize 给布局一个下界再配合 stretch 分配空间。三个一起用才稳。6. 进阶技巧把检测结果导出成可写进论文的结构化数据毕设答辩时老师常问「你这系统除了显示框还能输出什么」。我一般会加一个导出功能把每张图的检测结果存成 CSV包含文件名、类别、置信度、边界框坐标。这样论文里的「实验结果分析」章节就有真实数据支撑而不是只贴几张截图。import csv from pathlib import Path def export_results(model, img_dir, out_csvdetect_results.csv): img_dir Path(img_dir) rows [] for img in img_dir.glob(*.jpg): r model.predict(str(img), conf0.25, verboseFalse)[0] for box in r.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) x1, y1, x2, y2 [round(float(v), 2) for v in box.xyxy[0]] rows.append([img.name, model.names[cls_id], round(conf, 4), x1, y1, x2, y2]) with open(out_csv, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([image, class, confidence, x1, y1, x2, y2]) writer.writerows(rows) print(f导出 {len(rows)} 条检测记录到 {out_csv})encodingutf-8-sig是为了 Excel 打开不乱码这个细节很多人不知道。verboseFalse关掉 predict 的进度打印批量跑的时候日志干净。导出后你可以用 pandas 统计每类的平均置信度、检出数量直接做成论文里的表格。验证系统是否真的可用我的习惯是拿 10 张训练集里没出现过的图跑一遍人工核对框的位置和类别对不对。如果 10 张里错 3 张以上说明数据集标注质量有问题回去重新标别急着调模型参数。模型改进比如加协调注意力机制是锦上添花数据质量才是地基。我踩过最大的坑就是一开始贪快标注框画得比病灶大一圈结果模型学出来的框全是虚的mAP 死活上不去回头重标花了两倍时间。所以宁可标注慢一点也别糊弄。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。