news 2026/9/13 1:47:54

PyQt5+YOLOv5/v8本地自动标注工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyQt5+YOLOv5/v8本地自动标注工具

简介:这是一套面向计算机视觉初学者与课程设计学生的可视化自动标注工具实战项目,基于PyQt5开发,支持YOLOv5、YOLOv8及自定义模型接入,解决图像标注效率低、模型适配难等实际痛点,适用于AI课程大作业、毕业设计原型开发及小规模数据集预处理场景。压缩包共141个文件,含53个核心Python源码(含GUI逻辑、模型加载与推理模块)、54张示例PNG图像、6个配置与说明文本、3个YAML/YML模型配置文件,以及UI资源(.ui/.qrc)、国际化文件(.ts/.qm)和打包脚本(.spec),整体8.07MB,结构完整、开箱即用。已有368人学习下载。项目经导师指导获评97分高分课程设计,包含可直接运行的完整工程、清晰README与settings.json参数说明、screenshot.png界面示意及CITATION.cff学术引用规范,无需修改即可部署调试,显著降低CV项目落地门槛。

1. 这不是又一个“点选+框选”的标注工具,而是一套能真正把YOLOv5/YOLOv8模型嵌进GUI里跑推理、实时回填边界框的闭环系统

你手头有一批新采集的工业零件图像,想快速生成带标签的YOLO格式数据集——但打开LabelImg,发现每张图都要手动拖框、打标、保存,200张图干完天都黑了;再试AutoLabeling插件,结果模型一换(比如从YOLOv5切到YOLOv8),整个流程就报错中断。而这个基于PyQt5实现可视化自动标注工具,核心突破在于:它把模型加载、预处理、推理、坐标映射、JSON/YOLO格式写入全部封装进GUI线程安全的调用链中,支持在界面上一键切换YOLOv5.pt、YOLOv8n.pt或任意onnx/torchscript模型,点击“自动标注”后,3秒内完成单图推理并高亮显示所有检测框,双击框可编辑类别,拖动顶点可微调,Ctrl+S直接导出标准labels/目录结构。课程设计97分不是因为界面漂亮,而是它真实解决了“模型迭代→标注同步→格式兼容”这一链条中最卡脖子的环节。适合需要高频更新小样本数据集的CV初学者、课程设计学生、产线视觉工程师——尤其当你手头已有训练好的YOLO权重,却苦于没有轻量级本地标注入口时,这套方案比部署Web端标注平台更可控、比命令行脚本更直观。

2. PyQt5 GUI架构与多模型推理引擎的协同设计原理

2.1 为什么选PyQt5而非PySide6或Streamlit?——轻量、可控、无服务依赖的底层逻辑

项目放弃PySide6,核心在于对Qt5.15.x ABI兼容性的强依赖:anylabeling.desktop文件明确指定Exec=python -m anylabeling,且.flake8配置中禁用E501(行长限制)和W503(二元运算符换行),说明开发环境锁定在Python 3.8+ + PyQt5 5.15.19(对应Qt5.15.2)。这种选择并非技术保守,而是工程权衡——PyQt5对QThread信号槽机制的成熟封装,使得模型推理(耗时操作)与GUI渲染(主线程)能严格隔离:当用户点击“自动标注”时,GUI不冻结,进度条实时更新,背后是QThreadPool管理的QRunnable子类执行InferenceWorker,其run()方法调用self.model.predict()并emit结果信号。若换成Streamlit,需额外维护Flask服务、处理跨域、管理session状态;若用PySide6,则需重写icon.icns(macOS图标)和icon.ico(Windows图标)的资源加载逻辑——而本项目已通过QApplication.setWindowIcon(QIcon("icon.ico"))QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)实现开箱即用的多平台图标适配与高DPI支持。实测在GTX 1660 Ti上,PyQt5+YOLOv8n的单图推理延迟稳定在210±15ms(含图像缩放、NMS、坐标反算),比Streamlit方案快3.2倍(后者因HTTP往返+JSON序列化引入额外120ms开销)。

2.2 模型抽象层设计:统一接口适配YOLOv5/YOLOv8/自定义ONNX

项目未采用硬编码模型路径,而是通过settings.json动态加载配置:

{ "model": { "type": "yolov8", "path": "./models/yolov8n.pt", "conf_threshold": 0.25, "iou_threshold": 0.45 } }

关键在于inference/engine.py中的BaseModel抽象基类:

class BaseModel(ABC): @abstractmethod def preprocess(self, image: np.ndarray) -> torch.Tensor: pass @abstractmethod def postprocess(self, outputs: torch.Tensor, orig_shape: tuple) -> List[Dict]: pass @abstractmethod def predict(self, image: np.ndarray) -> List[Dict]: pass

YOLOv5实现继承该类,重写preprocessletterbox缩放(保持宽高比)+ BGR2RGB + 归一化;postprocess调用non_max_suppression并映射回原始坐标;YOLOv8则复用Ultralytics官方YOLO类,但重写predict方法注入verbose=Falseagnostic_nms=True参数以关闭日志输出并启用类别无关NMS。自定义ONNX模型通过onnxruntime.InferenceSession加载,preprocess统一转为CHW格式,postprocess解析output0(boxes)、output1(scores)、output2(classes)三输出张量。这种设计使新增模型仅需实现3个方法,无需改动GUI逻辑——实测替换为自定义YOLOv5s-OpenVINO IR模型时,仅修改model_type"openvino"并在__init__中加载.xml/.bin,其余流程零侵入。

2.3 标注数据流:从模型输出到YOLO TXT文件的坐标转换精要

YOLO格式要求归一化坐标(cx,cy,w,h),而模型输出为像素坐标(x1,y1,x2,y2)。项目在utils/label_converter.py中实现精准转换:

def yolo_bbox_to_cv2(bbox: List[float], img_shape: tuple) -> List[int]: """Convert YOLO format (cx,cy,w,h) to OpenCV (x1,y1,x2,y2)""" h, w = img_shape[:2] x1 = int((bbox[0] - bbox[2]/2) * w) y1 = int((bbox[1] - bbox[3]/2) * h) x2 = int((bbox[0] + bbox[2]/2) * w) y2 = int((bbox[1] + bbox[3]/2) * h) return [max(0, x1), max(0, y1), min(w, x2), min(h, y2)] def cv2_bbox_to_yolo(bbox: List[int], img_shape: tuple) -> List[float]: """Convert OpenCV format (x1,y1,x2,y2) to YOLO format (cx,cy,w,h)""" h, w = img_shape[:2] cx = (bbox[0] + bbox[2]) / 2 / w cy = (bbox[1] + bbox[3]) / 2 / h w_norm = (bbox[2] - bbox[0]) / w h_norm = (bbox[3] - bbox[1]) / h return [round(cx, 6), round(cy, 6), round(w_norm, 6), round(h_norm, 6)]

提示:round(..., 6)非冗余操作——YOLOv5训练时若TXT文件存在超6位小数,部分版本会因浮点精度溢出导致loss nan。实测某次导入标注后训练崩溃,定位到labels/001.txt第3行0 0.5000001 0.33333333 0.2 0.4,修正为0 0.500000 0.333333 0.200000 0.400000后恢复正常。

3. 从解压到标注:完整可复现的本地运行流程

3.1 环境构建与依赖验证(含CUDA加速关键步骤)

项目使用uv替代pip安装(见README.mduv pip install -r requirements.txt),因其依赖解析速度比pip快4.7倍(实测127个包平均耗时8.3s vs 39.1s)。但需注意CUDA版本匹配:

# 验证NVIDIA驱动与CUDA Toolkit兼容性 nvidia-smi # 输出Driver Version: 535.104.05 → 对应CUDA 12.2 nvcc --version # 若未安装,需下载CUDA 12.2 Toolkit # 创建conda环境(推荐,避免系统Python污染) conda create -n anylabeling python=3.9 conda activate anylabeling # 使用uv安装(比pip install更快且解决依赖冲突) curl -LsSf https://astral.sh/uv/install.sh | sh uv pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 uv pip install -r requirements.txt

requirements.txt关键项解析:

包名版本约束作用说明
pyqt5==5.15.19锁定版本避免PyQt5 6.x破坏Qt5.15 API(如QFileDialog.getOpenFileName返回值变更)
ultralytics==8.0.200YOLOv8专用提供YOLO类及model.export(format="onnx")能力,低于8.0.180则task="detect"参数失效
onnxruntime-gpu==1.16.3CUDA 12.1适配若用CUDA 12.2,需pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/

注意:若import torch报错libcudnn.so.8: cannot open shared object file,说明cuDNN未安装。Ubuntu 22.04需下载cudnn-linux-x86_64-8.9.2.26_cuda12-archive.tar.xz并解压到/usr/local/,执行sudo cp cuda/include/cudnn*.h /usr/local/cuda/includesudo cp cuda/lib/libcudnn* /usr/local/cuda/lib

3.2 模型准备与配置文件修改实操

项目默认提供models/yolov8n.pt,但YOLOv5需自行下载。不要直接用Ultralytics官网yolov5s.pt——因项目inference/yolov5.py中硬编码了self.stride = 32,而YOLOv5s实际stride为32,但YOLOv5m/l/x为32/16/8,需同步修改:

# 修改 inference/yolov5.py 第42行 # 原代码:self.stride = 32 # 改为(以YOLOv5m为例): self.stride = 16 # 必须与模型实际下采样倍率一致,否则坐标映射偏移

YOLOv5权重下载与校验:

wget https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5m.pt sha256sum yolov5m.pt # 应输出 9e5a1e5b...(与release页面checksum比对) # 更新 settings.json sed -i 's/"type": "yolov8"/"type": "yolov5"/' settings.json sed -i 's/"path": ".*"/"path": ".\/models\/yolov5m.pt"/' settings.json

3.3 启动GUI并执行首次自动标注全流程

# 启动应用(Linux/macOS) python -m anylabeling # Windows下若报错找不到模块,改用 python -c "import sys; sys.path.insert(0, '.'); import anylabeling.app; anylabeling.app.main()"

启动后界面包含:左侧图像列表、中央画布、右侧属性面板、底部状态栏。首次标注必做三步

  1. 加载图像目录:点击左上角File → Open Dir,选择datasets/images/(项目自带示例图存于screenshot.png同级目录)
  2. 加载模型:右键图像列表任一图片 →Auto Label→ 弹窗确认模型路径(自动读取settings.json
  3. 执行标注:选中一张图 → 点击工具栏Auto Label按钮(闪电图标)→ 观察状态栏Inference: 1/12→ 完成后画布显示绿色矩形框

标注结果实时写入datasets/labels/同名TXT文件。验证是否成功:

# 查看首张图标注 head -n 3 datasets/labels/000001.txt # 输出示例:0 0.421875 0.531250 0.125000 0.250000 (class_id cx cy w h) # 检查坐标合法性(cx,cy,w,h均在0~1之间) awk '{print $2,$3,$4,$5}' datasets/labels/000001.txt | \ awk '$1<0||$1>1||$2<0||$2>1||$3<0||$3>1||$4<0||$4>1 {print "ERROR"}' # 无输出即合规

4. 多模型切换与标注质量调优的关键参数控制

4.1 conf_threshold与iou_threshold的协同调节策略

settings.jsonconf_threshold(置信度阈值)和iou_threshold(NMS IoU阈值)共同决定标注召回率与精度平衡。实测在工业螺丝检测场景下的调节规律:

conf_thresholdiou_threshold效果适用场景
0.30.45检出12个螺丝,2个漏检(遮挡),0个误检标准作业
0.150.3检出18个螺丝,含4个虚警(反光伪影)高召回需求
0.50.6检出8个螺丝,全为真阳性,但漏检5个高精度质检

调节原则:先固定iou_threshold=0.45,将conf_threshold从0.5逐步下调至0.2,观察画布中框的数量变化;若出现密集重叠框(如多个框套同一物体),再降低iou_threshold至0.3~0.4。禁止将conf_threshold设为0.01——YOLOv8在极低置信度下会输出大量噪声框,导致后续训练时loss震荡。

4.2 自定义模型接入:ONNX格式转换与输入尺寸对齐

当使用自定义YOLOv5模型时,必须确保ONNX输入尺寸与PyQt5图像加载逻辑一致:

# 在 inference/custom_onnx.py 中,preprocess方法必须匹配 def preprocess(self, image: np.ndarray) -> torch.Tensor: # 项目默认图像缩放为640x640(YOLOv8n),若模型训练用416x416,此处必须对齐 img_resized = cv2.resize(image, (416, 416)) # 关键!否则坐标映射错误 img_rgb = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) img_norm = img_rgb.astype(np.float32) / 255.0 return torch.from_numpy(img_norm).permute(2, 0, 1).unsqueeze(0)

ONNX导出命令(YOLOv5):

# 在yolov5目录下执行 python export.py --weights yolov5s_custom.pt --include onnx --img 416 --batch 1 # 生成yolov5s_custom.onnx,将其复制到models/目录并修改settings.json

提示:ONNX模型若含Resize算子(常见于动态shape导出),PyQt5中onnxruntime.InferenceSession可能报错This is an invalid model. Type Error: Type 'tensor(float)' of input parameter ...。解决方案:用onnx-simplifier简化模型——pip install onnx-simplifier && python -m onnxsim yolov5s_custom.onnx yolov5s_custom_sim.onnx

4.3 标注后数据集验证:自动化检查脚本编写

项目未提供数据集校验工具,但可快速编写validate_labels.py

import os import cv2 from pathlib import Path def validate_yolo_dataset(img_dir: str, label_dir: str): img_paths = list(Path(img_dir).glob("*.jpg")) + list(Path(img_dir).glob("*.png")) for img_path in img_paths: label_path = Path(label_dir) / f"{img_path.stem}.txt" if not label_path.exists(): print(f"MISSING LABEL: {img_path.name}") continue img = cv2.imread(str(img_path)) h, w = img.shape[:2] with open(label_path) as f: for i, line in enumerate(f): parts = line.strip().split() if len(parts) != 5: print(f"INVALID FORMAT {label_path}:{i+1} - {line.strip()}") continue try: cx, cy, bw, bh = map(float, parts[1:]) # 检查归一化坐标越界 if not (0<=cx<=1 and 0<=cy<=1 and 0<=bw<=1 and 0<=bh<=1): print(f"COORD OUT OF RANGE {label_path}:{i+1} - {parts[1:]}") except ValueError: print(f"NON-NUMERIC {label_path}:{i+1}") if __name__ == "__main__": validate_yolo_dataset("datasets/images", "datasets/labels")

运行后输出MISSING LABEL: 000012.jpg即提示该图无对应TXT文件,需重新标注;输出COORD OUT OF RANGE则说明模型输出坐标异常,应检查cv2_bbox_to_yolo函数中max(0,min(w,...))边界处理是否生效。

5. 高效标注工作流优化:批量处理与错误恢复技巧

5.1 批量自动标注的静默模式实现

GUI界面一次只能处理单图,但实际项目常需标注数百张。项目预留了命令行接口,在anylabeling/cli.py中:

# 批量标注整个目录(无GUI,纯终端) python -m anylabeling.cli --input-dir datasets/images --output-dir datasets/labels --model-path models/yolov8n.pt --conf 0.25

该命令调用InferenceEngine批量加载图像,跳过GUI渲染,速度提升3.8倍(实测100张图耗时42s vs GUI模式161s)。关键参数说明

  • --input-dir:必须为绝对路径,相对路径会导致os.listdir()读取失败
  • --output-dir:自动创建目录,若存在同名TXT文件则覆盖(无警告)
  • --conf:等价于settings.json中的conf_threshold,优先级更高

提示:若批量处理中途崩溃(如显存不足),已生成的TXT文件不会被删除。可记录最后成功处理的文件名,用find datasets/images -name "*.jpg" | sed -n '/000087.jpg/,$p' | head -n 50 | xargs -I{} python -m anylabeling.cli --input-dir datasets/images --output-dir datasets/labels --model-path models/yolov8n.pt --conf 0.25 --image {}续跑。

5.2 标注错误的快速修正:ROI裁剪与局部重标

当某张图出现大面积误检(如背景纹理被识别为物体),不必整图重标。利用PyQt5画布的ROI功能:

  1. 按住Ctrl键 + 鼠标左键拖拽,框选疑似误检区域
  2. 右键 →Crop & Auto Label→ 弹窗提示“Crop region to 256x256 and run inference”
  3. 系统自动裁剪、缩放、推理,将结果坐标映射回原图位置并合并标注

此功能依赖utils/crop_utils.py中的crop_and_infer函数,其核心是计算裁剪区域在原图中的偏移量:

def crop_and_infer(image: np.ndarray, crop_bbox: List[int], model: BaseModel) -> List[Dict]: x1, y1, x2, y2 = crop_bbox cropped = image[y1:y2, x1:x2] # 注意numpy索引顺序 results = model.predict(cropped) # 将结果坐标平移回原图坐标系 for r in results: r['bbox'][0] += x1 # x1 r['bbox'][1] += y1 # y1 r['bbox'][2] += x1 # x2 r['bbox'][3] += y1 # y2 return results

实测对1920x1080图像中300x300的误检区域,局部重标耗时仅0.8s,比整图重标快12倍。

5.3 模型热更新:无需重启GUI的权重替换

当训练新模型后,传统做法需关闭GUI、替换.pt文件、重启程序。本项目支持热更新:

  1. 将新权重yolov8n_v2.pt放入models/目录
  2. 在GUI中点击Settings → Reload Model(齿轮图标旁刷新按钮)
  3. 状态栏显示Model reloaded: yolov8n_v2.pt (24.7MB),立即生效

该功能由app/main_window.pyreload_model_action触发,其本质是销毁旧InferenceEngine实例并新建:

def reload_model(self): if self.engine: self.engine.unload() # 显式释放GPU显存 self.engine = InferenceEngine(model_path=self.current_model_path) self.statusBar().showMessage(f"Model reloaded: {os.path.basename(self.current_model_path)} ({os.path.getsize(self.current_model_path)/1024/1024:.1f}MB)")

注意:engine.unload()调用torch.cuda.empty_cache(),若省略此步,连续热更新3次后显存占用会累积增长,最终OOM。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 1:46:51

OpenGL绘制Bezier曲面:法线计算、光照模型与纹理映射实践

简介&#xff1a;面向计算机图形学初学者与OpenGL开发者的Bezier曲面演示程序&#xff0c;基于Visual C工程完整实现了曲面建模、纹理映射与光照渲染的整合。源代码通过GLU函数库构建二维Bezier曲面&#xff0c;涵盖gluBeginSurface、gluEndSurface与gluBuild2DMultitexture等接…

作者头像 李华
网站建设 2026/9/13 1:46:38

字符串匹配算法:从KMP到AC自动机的实战优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 1:42:45

赤平投影软件计算全解析:从原理到抗滑桩设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 1:41:59

外贸GEO公司有哪些?怎么选才不踩坑?

文/林芳老师 先搞清楚&#xff1a;GEO服务商分哪几类&#xff1f; 2026年&#xff0c;GEO&#xff08;Generative Engine Optimization&#xff0c;生成式引擎优化&#xff09;成了外贸行业的热词。当海外采购商习惯用ChatGPT、Perplexity、Google AI Mode等AI工具找供应商时&a…

作者头像 李华
网站建设 2026/9/13 1:40:32

Renovate 调用 AWS 服务:AWS SDK 凭证与配置完整指南

Renovate 调用 AWS 服务&#xff1a;AWS SDK 凭证与配置完整指南 【免费下载链接】renovate Home of the Renovate CLI: Cross-platform Dependency Automation by Mend.io 项目地址: https://gitcode.com/GitHub_Trending/re/renovate 本篇技术指南围绕 Renovate 内置 …

作者头像 李华
网站建设 2026/9/13 1:39:51

果蔬识别系统:ResNet-18+PyQt5工业级边缘部署实战

简介&#xff1a;本资源是一套完整的基于卷积神经网络的果蔬图像识别系统实现方案&#xff0c;面向深度学习初学者、课程设计学生及嵌入式AI实践者&#xff0c;解决日常果蔬图像分类与轻量化部署的实际问题。项目采用TensorFlow构建CNN模型&#xff0c;结合PyQt5开发图形化交互…

作者头像 李华