
简介这是一套基于YOLOv8的陶瓷器鉴定系统完整项目面向计算机视觉、人工智能方向的毕业设计或课程设计场景。项目围绕目标检测任务展开提供可运行的Python源码、完整数据集、可视化交互界面和部署教程开箱即用。系统支持模型训练、视频检测与结果可视化可输出混淆矩阵、F1曲线、精确率-召回率曲线、验证集预测结果及标签分布图等核心评估图表方便在答辩环节直观展示实验过程与精度表现。同时内置多种预训练权重和训练/检测脚本可切换不同模型进行对比实验也便于二次开发。资料包共97个文件以Python脚本为主包含少量配置文件、模型权重和演示视频整体仅24.21MB轻量紧凑。当前已有29人学习非常适合深度学习初学者进阶也可直接作为本科毕设、课程设计或大作业的完整方案按README指引即可快速搭建运行环境并复现结果。1. 一个毕设级 YOLOv8 陶瓷器鉴定系统到底要打通哪几件事陶瓷器鉴定通常是靠专家肉眼观察器型、釉色、纹饰和底足主观性强而且需要长期经验积累。如果把这个过程换成一个基于 YOLOv8 的陶瓷器鉴定系统本质上是用目标检测算法完成两件事在图片里定位陶瓷器物再对器物进行分类或属性判定。这类系统最常见的落地场景是毕业设计和课程设计图片数量不大、类别不多但要求把训练、推理、可视化界面和部署串成完整链路。适合有一定 Python 基础、了解卷积神经网络但对 YOLO 不熟的人。下面从环境配置、数据集组织、模型训练、界面部署和最终验证五条线展开每一步都给出可以照搬的命令和参数也标注了毕设答辩时最容易翻车的位置。2. 先把地基打牢YOLOv8 环境配置与陶瓷数据集组织方式2.1 YOLOv8 环境配置要走到哪一步才算成功很多同学在跑 YOLOv8 时卡在第一步不是代码不会写而是环境里 torch、CUDA 和 numpy 的版本互相不对付。这里给出我一般会做的最简配置流程尽量不牵扯发行版。首先建一个干净虚拟环境避免把系统 Python 搞乱python -m venv yolo-env source yolo-env/bin/activate # Windows 下用 yolo-env\Scripts\activate pip install --upgrade pip pip install ultralytics安装完成后不要急着训练先用一行代码验证模型能不能加载。modelyolov8n.pt会从官方地址下载权重如果下载超时可以手动把权重文件放到当前目录再执行。这个命令同时完成权重下载、推理和结果保存能跑通就说明基础依赖没有大问题。yolo predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg接着检查 GPU 是否真的被 PyTorch 识别这一步比看显卡型号更可靠。很多环境里pip install ultralytics会顺手装一个 CPU 版 torch代码能跑但训练慢到让人怀疑人生。import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU only)如果显示False先别急着找代码问题回去重装 torch。常见做法是到 PyTorch 官网选一个和你的 CUDA 版本匹配的命令重新安装torch和torchvision。我不建议自己编译源码除非你对构建系统很熟。对 GTX 1660 Ti 这类 6G 显存级别的卡跑 YOLOv8n 和 8s 都足够8m 需要把 batch 调小才能塞进去。提示虚拟环境装好 ultralytics 和 torch 后用pip freeze requirements.txt固定版本。答辩时换一台机器pip install -r requirements.txt就能复现能省掉大量环境排查时间。2.2 陶瓷器数据集怎么做成 YOLO 格式YOLOv8 官方训练接口只认images和labels分开的目录结构。拿到一套陶瓷器数据集后你最先要做的是确认它是否长这样datasets/ceramic/ ├── data.yaml ├── train │ ├── images/ # 图片jpg/png │ └── labels/ # 对应的txt同名 └── val ├── images/ └── labels/YOLO 的标签文件是纯文本每行一个目标格式为class_id x_center y_center width height坐标和宽高都是相对图片尺寸归一化到 0~1 的小数。举例一张 800x600 的图中某个陶瓷器边界框左上角是 (200, 150)右下角是 (600, 450)类别 id 为 2那么标签行是2 0.5 0.5 0.5 0.5因为中心点是 ((200600)/2/800, (150450)/2/600) (0.5, 0.5)宽是 (600-200)/8000.5高是 (450-150)/6000.5。如果数据集只有图片没有标签需要人工标注。我一般用 labelImg安装很直接打开图形界面后指定图片目录和标签保存目录即可。它的快捷键不多但足够完成陶瓷器框选任务。pip install labelImg labelImg标注陶瓷器时有个小技巧不要只框“器物主体”口沿、底足、裂纹这些局部特征如果在同类图片里差异很大可以单独做类别也可以统一作为整体目标取决于你的鉴定目标。如果做“年代分类”那么一整个器物就是目标框如果做“真伪鉴别”局部胎釉特征更有信息量建议把口沿和底足也标注出来模型通常能学到那些纹理差异。同时要写好data.yaml这是 YOLOv8 训练的唯一数据入口path: D:/datasets/ceramic # 或相对路径 train: train/images val: val/images names: 0: celadon # 青瓷 1: blue_white # 青花 2: enamel # 粉彩 3: zisha # 紫砂注意names的 id 必须和标签文件第一列保持一致顺序错一个类别整个训练就等于在学错误映射。类别名最好用英文或拼音中文类别名在部分版本 Ultralytics 绘图和部署时容易出编码问题。2.3 数据集不足时先别急着 train陶瓷器数据集很难像 COCO 那样动辄几万张一般课程设计能有一两千张带标注图片已经很不错了。在这个量级下直接开始训练容易过拟合。我会先做一个数据统计脚本看看每个类别有多少目标框判断是否严重不均衡from pathlib import Path from collections import Counter def count_labels(label_dir: str) - dict: counter Counter() for txt in Path(label_dir).glob(*.txt): for line in txt.read_text(encodingutf-8).splitlines(): if line.strip(): counter[int(line.split()[0])] 1 return dict(counter) print(count_labels(datasets/ceramic/train/labels))如果某个类别只有几十个目标而另一个有几千训练出来的模型大概率偏向多数类。处理方法有几种对少数类图片做平移、旋转、镜像注意陶瓷器如果带朝代字样翻转后字会反这类样本不能镜像。用 YOLOv8 自带的数据增强在训练时调高hsv_h、hsv_s、degrees等参数模拟不同光线和角度。如果少数类之间形态差异很大优先补充该类别的新样本而不是靠重采样硬凑。下表是陶瓷器数据增强里值得优先调整的几项YOLOv8 都支持在data.yaml里配置参数默认值说明hsv_h0.015色相扰动模拟不同釉色偏色hsv_s0.7饱和度扰动适应器物表面光泽变化degrees0.0旋转角度陶瓷器照片常存在轻微倾斜translate0.1平移增强器物在画面中的位置泛化fliplr0.5水平翻转注意文字和不对称纹饰这里不推荐直接复制同一张图一百遍去“平衡数据集”模型记住的是噪声不是特征。增强参数也不是越大越好翻转和旋转太狠会让模型学到错误的形变反而把釉面反光当成关键特征。3. 训练自己的 YOLOv8 陶瓷器模型从默认参数到损失曲线诊断3.1 选哪个 YOLOv8 变体n/s/m/l 与硬件匹配YOLOv8 官方提供五个尺度参数量和推理速度差异很大。陶瓷器鉴定场景有一个特点图片通常是正面、侧面的器物照片背景可控目标数量少精度上限往往取决于数据标注质量而不是模型容量。YOLOv8 的 backbone 用 C2f 结构相比老一代 CSP 结构梯度分流到更多的子层对釉面纹理和器物边缘这类细节特征更友好这也是它在陶瓷器小数据集上仍然能取得不错效果的原因之一。我一般按显存和部署目标选型。如果是在 16G 以上的 GPU 上做实验直接用 8m 或 8l 训练再蒸馏到 8s 部署如果只有 6G 到 8G 显存8s 是性价比最好的选择如果最终要部署到 CPU 或老机器上8n 值得先跑一版。模型参数量(约)输入尺寸典型显存占用适用场景YOLOv8n3.2M640约 1~2 GBCPU 可推理快速验证YOLOv8s11.2M640约 2~4 GB6G 显存训练友好YOLOv8m25.9M640约 4~6 GB追求精度需调小 batchYOLOv8l43.7M640约 8~10 GB数据集大、精度优先YOLOv8x68.2M640约 12 GB较少用于毕设表里的显存占用是 batch 为 1 的粗略估计实际训练时要看batch大小。如果出现CUDA out of memory先把 batch 减半不要一上来就换小模型。陶瓷器类别通常只有几个到十几个8n 都不至于欠拟合关键是标签质量。官方网络结构图里能看到 C2f 后面接的是 SPPF 和 PAN-FPN这部分决定了多尺度特征融合而陶瓷器口沿和底足往往是多尺度目标所以训练时imgsz不要压到 320建议 640 起步。3.2 一份可以直接训练陶瓷器数据的命令与参数以 8s 为例在数据集目录准备完成后用命令行训练yolo train modelyolov8s.pt dataceramic.yaml epochs150 imgsz640 batch8 device0 workers4 optimizerauto projectruns nameceramic_s这段命令里的参数对结果影响很大imgsz640是内部缩放尺寸不是输入原图必须 640x640YOLOv8 会自动 letterbox。batch8建议按显存调整显存小的减到 4。workers4在 Windows 上不要设太高容易报 DataLoader worker 错误。optimizerauto会让 Ultralytics 自动选择优化器省去手动调 SGD/AdamW 的麻烦。如果你想在训练过程中动态观察还可以加上plotsTrue这样每个 epoch 结束后会自动生成标签图、预测图、混淆矩阵和损失曲线全部存在runs/ceramic_s下。用 Python 脚本训练的好处是方便在训练前后做额外处理比如按验证集表现自动换初始权重from ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( dataceramic.yaml, epochs150, imgsz640, batch8, device0, workers4, optimizerauto, projectruns, nameceramic_s, patience30, )patience30表示如果连续 30 个 epoch mAP 没有提升自动停止训练避免无意义地烧显卡。对课程设计来说patience设成 20 到 30 是合理的因为训练时间有限。C2f 结构和optimizerauto配合时PyTorch 会默认给不同层设置不同的学习率权重这一点不需要手动调但要注意如果自己改了lr0最好同时看一下results.csv里的学习率变化曲线。训练结束后在runs/ceramic_s/weights/下会有last.pt和best.pt。无论最后效果如何部署时只用best.ptlast.pt只用于断点续训。3.3 从 results.csv 读训练状态loss 曲线、mAP、过拟合Ultralytics 在训练过程中会把每个 epoch 的指标写到runs/ceramic_s/results.csv比直接跑 TensorBoard 更直观。列名基本包含train/box_loss、train/cls_loss、train/dfl_loss、val/box_loss、val/cls_loss、val/dfl_loss、metrics/precision(B)、metrics/recall(B)、metrics/mAP50(B)、metrics/mAP50-95(B)。我习惯写个小脚本把 val 的 box_loss 和 mAP50 画在一张图上判断训练是否健康import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/ceramic_s/results.csv) plt.figure(figsize(10, 4)) plt.subplot(1, 2, 1) plt.plot(df[epoch], df[val/box_loss], labelval box loss) plt.plot(df[epoch], df[train/box_loss], labeltrain box loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.title(box loss curve) plt.subplot(1, 2, 2) plt.plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) plt.xlabel(epoch) plt.ylabel(mAP) plt.legend() plt.title(mAP50 curve) plt.tight_layout() plt.savefig(loss_curve.png, dpi150)典型的情况有三种train/box_loss一直下降val/box_loss在某个 epoch 后回升说明过拟合需要减小模型尺寸、增加数据增强或提前用patience停止。val/cls_loss下降缓慢但box_loss很低说明模型对“器物质感”的定位没问题但要更关注类别区分可以检查分类分支或者增加判别性强的局部标签。mAP50 高但 mAP50-95 低说明检测框对精准边缘和 IoU 阈值敏感常见于标注框不够贴边需要回头修数据集。很多人只看 mAP50忽略了 mAP50-95。在陶瓷器检测里如果后续要接尺寸测量或口沿位置评估mAP50-95 更能反映框的贴合程度应该把它的变化也纳入验收标准。4. 给陶瓷器鉴定接上可视化界面从结果解析到简单部署4.1 一个可运行的推理封装类训练好的模型要进界面先封装成独立的预测类这样不管后面接 Gradio、Flask 还是 PyQt调用方式都一样。下面是我常用的写法from ultralytics import YOLO class CeramicDetector: def __init__(self, weights: str best.pt, conf: float 0.35, iou: float 0.45): self.model YOLO(weights) self.conf conf self.iou iou self.class_names self.model.names def predict(self, image_input): result self.model.predict( sourceimage_input, confself.conf, iouself.iou, verboseFalse, )[0] boxes result.boxes.xyxy.cpu().numpy() # 左上右下坐标 labels result.boxes.cls.int().cpu().tolist() scores result.boxes.conf.cpu().tolist() return boxes, labels, scores def result_table(self, image_input, class_names: list): boxes, labels, scores self.predict(image_input) rows [] for box, label, score in zip(boxes, labels, scores): rows.append({ class: class_names[label], score: f{score:.2f}, x_min: int(box[0]), y_min: int(box[1]), x_max: int(box[2]), y_max: int(box[3]), }) return rowsresult.boxes.xyxy返回的是像素坐标不是归一化坐标界面上直接画框很方便。后续如果要计算陶瓷器的长宽比、面积占比也是在这个坐标基础上算。conf和iou从初始化就暴露出来方便在界面里加两个滑块现场调节。如果一张图里有多个陶瓷器遍历labels时要注意类别索引和class_names对齐否则展示出来会张冠李戴。推理封装类里尽量不要混入图像解码逻辑因为 Gradio 传进来是 numpy 数组Flask 传进来是文件流PyQt 传进来是 QPixmap解码应该由界面层负责。4.2 用 Gradio 快速搭建可视化鉴定页面Gradio 是最快的做法几十行就能把“上传图片 显示结果”变成网页应用。对于毕设答辩操作简单是硬指标现场不需要安装任何客户端浏览器打开就能用。import gradio as gr from detector import CeramicDetector class_names [celadon, blue_white, enamel, zisha] detector CeramicDetector(best.pt) def process(image, conf): import cv2 img cv2.cvtColor(image, cv2.COLOR_RGB2BGR) rows detector.result_table(img, class_names) result detector.model.predict( sourceimg, confconf, imgsz640, device0, verboseFalse )[0] annotated result.plot()[:, :, ::-1] # BGR转RGB return annotated, rows gr.Interface( fnprocess, inputs[ gr.Image(label上传陶瓷器图片), gr.Slider(minimum0.1, maximum0.9, value0.35, step0.05, label置信度阈值), ], outputs[ gr.Image(label鉴定结果), gr.Dataframe(label检测详情, headers[class, score, x_min, y_min, x_max, y_max]), ], title基于YOLOv8的陶瓷器鉴定系统, ).launch()gr.Image默认传进来的图片是 RGB 的 numpy 数组我用cv2.cvtColor转成 BGR 再走 Ultralytics 推理因为 YOLO 在 OpenCV 约定下训练输入 BGR 才能保证颜色空间一致。result.plot()返回的是带标注框的 BGR 图像输出给 Gradio 前再转回 RGB否则颜色会整体偏蓝。这个细节是很多界面“颜色不对”的元凶。launch()不加参数时默认监听本机7860端口。如果要在服务器上展示可以传server_name0.0.0.0注意先检查防火墙。下表是几种常见可视化方案的取舍毕设通常选前两个之一方案优点缺点适用场景Gradio代码量少自带滑块和表格页面定制性差快速演示和答辩Flask前后端分离可套 HTML 模板需要写更多后端代码更像完整系统PyQt桌面应用离线可用打包体积大跨平台成本高课程设计要求本地界面4.3 如果想用 Web 页面部署Flask 的最小实现Gradio 方便但定制性差有些指导老师希望界面看起来更像“系统”。这时候用一个 Flask 应用更合适前端可以套现成的 HTML 模板后端只暴露两个接口上传图片、返回 JSON。import base64 from io import BytesIO from flask import Flask, request, jsonify from PIL import Image from detector import CeramicDetector app Flask(__name__) detector CeramicDetector(best.pt) app.route(/detect, methods[POST]) def detect(): file request.files.get(image) if not file: return jsonify({code: 400, msg: no image}), 400 image Image.open(file.stream).convert(RGB) rows detector.result_table(image, detector.class_names) # 结果缩略图也可以返回base64方便前端直接展示 annotated detector.model.predict( sourceimage, verboseFalse )[0].plot()[:, :, ::-1] buf BytesIO() Image.fromarray(annotated).save(buf, formatJPEG) img_str base64.b64encode(buf.getvalue()).decode(ascii) return jsonify({code: 0, rows: rows, annotated: img_str}) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)这里的关键点是request.files.get(image)拿到的是临时文件对象不要直接读全文再PIL.open用file.stream可以避免大图撑爆内存。debugFalse一定要保持关闭否则 Flask 的代码热重载会在训练模型时反复加载两次直接把显存打满。Flask 方案的部署成本也很低本地演示直接python app.py。正式一点可以托管到 Linux 服务器上用gunicorn -w 1 -b 0.0.0.0:5000 app:app启动。注意 worker 数量在这里不能大每一个 worker 都会加载一份完整模型权重4G 内存跑 4 个 worker 很容易 OOM。5. 最后再补三道防线陶瓷器检测的验证指标、ONNX 导出与边界样本5.1 用yolo val得到 mAP 与混淆矩阵训练完不要急着交。先在验证集上跑一次官方验证拿到没有“界面背景干扰”的客观指标yolo val modelruns/ceramic_s/weights/best.pt dataceramic.yaml projectfinal_eval nameceramic_val运行结束后final_eval/ceramic_val/下会有confusion_matrix.png、PR_curve.png、F1_curve.png。陶瓷器领域最常见的混淆是青瓷和天青釉、粉彩和五彩这类釉色接近的类别如果混淆矩阵里这两类互相污染说明需要补充能区分釉料质感的细节标注而不是继续堆叠训练轮数。我通常会把同一器物在不同角度、不同背景下的照片全部放进同一组确保验证集没有出现过训练集中的同一器物否则泛化性会被高估。5.2 导出 ONNX让部署环境不依赖 Python 版本Ultralytics 的.pt权重依赖 PyTorch 环境答辩或交付时如果对方的 GPU 驱动和 CUDA 版本不同很容易跑不起来。把best.pt导出成 ONNX 是更稳妥的交付方式yolo export modelruns/ceramic_s/weights/best.pt formatonnx opset12 dynamicFalse imgsz640导出成功后会生成best.onnx。ONNX 格式可以用onnxruntime在只有 CPU 的机器上推理也不需要安装 torch。如果目标机器是 NVIDIA 显卡且版本匹配再考虑 TensorRT 导出不匹配时反而容易因为算子不兼容折腾半天我一般把 TensorRT 当作可选优化不作为交付前提。5.3 三类最容易翻车的边界样本这里是我在跑分类检测系统时最常遇到的三类问题提前写进排查清单里比最后出问题再查代码快得多。第一类是背景反射光。陶瓷器表面反光会在照片上形成高光区域模型可能把高光当成器物边缘而框出一个错误区域。训练时加入光照扰动或者推理时用带 alpha 的高光抑制预处理都会有效果。第二类是遮挡和叠放。博物馆或考古现场照片里一个器物经常被另一个挡住一部分。YOLOv8 的框无法区分前景和背景如果标注时把被遮挡的器物也完整框进去box_loss会一直偏高。建议对遮挡目标只框可见部分标签语义是“我能看到的部分”。第三类是conf阈值设置过低。演示时如果用默认conf0.25模型会把很多低置信度背景框画出来让界面看起来很不可靠。把界面里置信度滑块的默认值设为 0.4 或 0.45再让用户在演示现场手动调低到 0.25 对比效果反而能体现系统对阈值的敏感性。记住这个细节比临时改模型代码更能在答辩现场救场。本文还有配套的精品资源点击获取