当前位置: 首页 > news >正文

YOLO自动标注工具软件

智慧标注:-YOLO自动标注工具软件

,功能全,响应快,操作简单!
选择模型检测你的数据集,支持导出为不同格式的标签(txt,json,xml)。
其他附加功能如:调节标注阈值,日志记录,检测结果预览等。
配合labelimg等标注工具能够快速的帮助你进行数据标注,节省人力成本。
1

1

这个 YOLO 自动标注工具,利用训练好的 YOLO 模型对未标注的图片进行推理,然后将推理得到的边界框坐标转换成标注文件(如 YOLO 格式的.txt),从而替代人工进行初步标注。

界面搭建(PyQt5)模型推理标签转换三个关键部分。

核心代码实现

环境依赖

你需要安装以下库来运行代码:

pipinstallPyQt5 ultralytics opencv-python torch numpy
完整代码 (auto_labeling_tool.py)

这是一个精简但功能完整的单文件版本,涵盖了你截图中的主要功能:模型加载、图片浏览、参数调节、自动推理和 YOLO 格式保存。

importsysimportosfromPyQt5.QtWidgetsimport(QApplication,QMainWindow,QWidget,QVBoxLayout,QHBoxLayout,QPushButton,QLabel,QSlider,QFileDialog,QProgressBar,QMessageBox,QGroupBox,QFormLayout)fromPyQt5.QtGuiimportQPixmap,QImagefromPyQt5.QtCoreimportQt,QThread,pyqtSignalimportcv2importnumpyasnpfromultralyticsimportYOLO# --- 后台推理线程 ---classInferenceThread(QThread):progress=pyqtSignal(int,str)# 进度值, 日志信息finished=pyqtSignal()image_updated=pyqtSignal(np.ndarray)# 发送处理后的图像用于预览def__init__(self):super().__init__()self.image_paths=[]self.model=Noneself.conf_thres=0.3self.iou_thres=0.45self.save_dir=""self.is_running=Falsedefrun(self):self.is_running=Truetotal=len(self.image_paths)fori,img_pathinenumerate(self.image_paths):ifnotself.is_running:break# 1. 推理results=self.model(img_path,conf=self.conf_thres,iou=self.iou_thres)result=results[0]# 2. 生成 YOLO 格式标签 (.txt)img_name=os.path.basename(img_path)name_without_ext=os.path.splitext(img_name)[0]txt_path=os.path.join(self.save_dir,f"{name_without_ext}.txt")h,w=result.orig_img.shape[:2]withopen(txt_path,'w')asf:forboxinresult.boxes:cls_id=int(box.cls[0])conf=box.conf[0]# xyxy 转 xywh (归一化)x1,y1,x2,y2=box.xyxy[0]x_center=((x1+x2)/2)/w y_center=((y1+y2)/2)/h width=(x2-x1)/w height=(y2-y1)/h f.write(f"{cls_id}{x_center:.6f}{y_center:.6f}{width:.6f}{height:.6f}\n")# 3. 绘制图像用于预览 (在图片上画框)annotated_img=result.plot()# 发送信号self.progress.emit(int((i+1)/total*100),f"已处理:{img_name}")ifi==0:# 只预览第一张或最后一张,避免界面卡顿self.image_updated.emit(annotated_img)self.finished.emit()defstop(self):self.is_running=False# --- 主窗口界面 ---classAutoLabelingTool(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle("YOLO自动标注工具")self.setGeometry(100,100,1200,800)self.model=Noneself.image_paths=[]self.current_idx=0self.init_ui()self.thread=InferenceThread()definit_ui(self):main_layout=QHBoxLayout()# --- 左侧控制面板 ---left_panel=QWidget()left_layout=QVBoxLayout()# 1. 模型设置model_group=QGroupBox("模型设置")model_layout=QFormLayout()self.btn_load_model=QPushButton("加载模型")self.btn_load_model.clicked.connect(self.load_model)model_layout.addRow(self.btn_load_model)model_group.setLayout(model_layout)# 2. 参数设置param_group=QGroupBox("检测参数")param_layout=QFormLayout()self.slider_conf=QSlider(Qt.Horizontal)self.slider_conf.setRange(0,100)self.slider_conf.setValue(30)self.lbl_conf=QLabel("0.30")self.slider_conf.valueChanged.connect(lambda:self.lbl_conf.setText(f"{self.slider_conf.value()/100:.2f}"))self.slider_iou=QSlider(Qt.Horizontal)self.slider_iou.setRange(0,100)self.slider_iou.setValue(45)self.lbl_iou=QLabel("0.45")self.slider_iou.valueChanged.connect(lambda:self.lbl_iou.setText(f"{self.slider_iou.value()/100:.2f}"))param_layout.addRow(QLabel("置信度:"),self.slider_conf)param_layout.addRow(self.lbl_conf,QLabel(""))param_layout.addRow(QLabel("IOU阈值:"),self.slider_iou)param_layout.addRow(self.lbl_iou,QLabel(""))param_group.setLayout(param_layout)# 3. 文件设置file_group=QGroupBox("文件设置")file_layout=QFormLayout()self.btn_select_input=QPushButton("选择输入文件夹")self.btn_select_input.clicked.connect(self.select_input)self.btn_select_output=QPushButton("选择输出文件夹")self.btn_select_output.clicked.connect(self.select_output)file_layout.addRow(self.btn_select_input)file_layout.addRow(self.btn_select_output)file_group.setLayout(file_layout)# 4. 操作按钮self.btn_start=QPushButton("开始标注")self.btn_start.setStyleSheet("background-color: #4CAF50; color: white; height: 40px;")self.btn_start.clicked.connect(self.start_labeling)self.btn_stop=QPushButton("停止标注")self.btn_stop.setStyleSheet("background-color: #F44336; color: white; height: 40px;")self.btn_stop.clicked.connect(self.stop_labeling)self.btn_stop.setEnabled(False)# 5. 进度条self.progress_bar=QProgressBar()self.progress_bar.setValue(0)left_layout.addWidget(model_group)left_layout.addWidget(param_group)left_layout.addWidget(file_group)left_layout.addWidget(self.btn_start)left_layout.addWidget(self.btn_stop)left_layout.addWidget(QLabel("处理进度:"))left_layout.addWidget(self.progress_bar)left_panel.setLayout(left_layout)# --- 右侧预览区域 ---right_panel=QWidget()right_layout=QVBoxLayout()self.lbl_image=QLabel("预览区域")self.lbl_image.setAlignment(Qt.AlignCenter)self.lbl_image.setStyleSheet("background-color: #222; color: #fff;")right_layout.addWidget(self.lbl_image)right_panel.setLayout(right_layout)main_layout.addWidget(left_panel,1)main_layout.addWidget(right_panel,3)container=QWidget()container.setLayout(main_layout)self.setCentralWidget(container)# 连接线程信号self.thread.progress.connect(self.update_progress)self.thread.finished.connect(self.labeling_finished)self.thread.image_updated.connect(self.show_image)defload_model(self):path,_=QFileDialog.getOpenFileName(self,"选择YOLO模型文件","","Model Files (*.pt)")ifpath:try:self.model=YOLO(path)QMessageBox.information(self,"成功","模型加载成功!")exceptExceptionase:QMessageBox.critical(self,"错误",f"加载失败:{str(e)}")defselect_input(self):folder=QFileDialog.getExistingDirectory(self,"选择图片文件夹")iffolder:# 支持常见的图片格式self.image_paths=[os.path.join(folder,f)forfinos.listdir(folder)iff.lower().endswith(('.png','.jpg','.jpeg','.bmp'))]QMessageBox.information(self,"提示",f"找到{len(self.image_paths)}张图片")defselect_output(self):folder=QFileDialog.getExistingDirectory(self,"选择保存标签的文件夹")iffolder:self.thread.save_dir=folderdefstart_labeling(self):ifnotself.model:QMessageBox.warning(self,"警告","请先加载模型")returnifnotself.image_paths:QMessageBox.warning(self,"警告","请先选择输入图片文件夹")returnifnotself.thread.save_dir:QMessageBox.warning(self,"警告","请先选择输出文件夹")returnself.btn_start.setEnabled(False)self.btn_stop.setEnabled(True)# 配置线程参数self.thread.image_paths=self.image_paths self.thread.conf_thres=self.slider_conf.value()/100self.thread.iou_thres=self.slider_iou.value()/100self.thread.model=self.model self.thread.start()defstop_labeling(self):self.thread.stop()self.btn_stop.setEnabled(False)defupdate_progress(self,val,log_msg):self.progress_bar.setValue(val)# 这里可以添加一个日志文本框来显示 log_msgdeflabeling_finished(self):self.btn_start.setEnabled(True)self.btn_stop.setEnabled(False)QMessageBox.information(self,"完成","所有图片处理完毕!")defshow_image(self,img_bgr):# BGR 转 RGBimg_rgb=cv2.cvtColor(img_bgr,cv2.COLOR_BGR2RGB)h,w,ch=img_rgb.shape bytes_per_line=ch*w qt_image=QImage(img_rgb.data,w,h,bytes_per_line,QImage.Format_RGB888)# 自动缩放以适应标签大小pixmap=QPixmap.fromImage(qt_image).scaled(self.lbl_image.size(),Qt.KeepAspectRatio)self.lbl_image.setPixmap(pixmap)if__name__=='__main__':app=QApplication(sys.argv)window=AutoLabelingTool()window.show()sys.exit(app.exec_())

代码核心功能解析

  1. 多线程处理

    • 使用QThread进行后台推理,防止在检测大量图片时 GUI 界面卡死(无响应)。
    • InferenceThread类负责循环读取图片、推理、保存标签。
  2. YOLO 格式转换

    • 代码中的核心算法部分是将result.boxes.xyxy(像素坐标)转换为 YOLO 标准的归一化xywh(中心点+宽高):
      xcenter=x1+x22×Wimgx_{center} = \frac{x_1 + x_2}{2 \times W_{img}}xcenter=2×Wimgx1+x2
      ycenter=y1+y22×Himgy_{center} = \frac{y_1 + y_2}{2 \times H_{img}}ycenter=2×Himgy1+y2
      width=x2−x1Wimgwidth = \frac{x_2 - x_1}{W_{img}}width=Wimgx2x1
      height=y2−y1Himgheight = \frac{y_2 - y_1}{H_{img}}height=Himgy2y1
  3. 参数动态调节

    • 通过QSlider实时获取置信度和 IOU 阈值,并在点击“开始”时传递给推理线程。
  4. 可视化预览

    • 利用result.plot()获取绘制好边框的图像,转换为QImage显示在 PyQt 界面上,让你直观看到自动标注的效果。

如何运行

  1. 将上述代码保存为main.py
  2. 准备一个.pt模型文件(如yolov8n.pt或你自己训练的模型)。
  3. 运行python main.py
  4. 在界面中加载模型,选择包含图片的文件夹和输出文件夹,点击“开始标注”即可。
http://www.cnnetsun.cn/news/2036502.html

相关文章:

  • 从GitHub到百度云:手把手教你备份和整理吴恩达机器学习全套资源(笔记+代码+视频)
  • 别再手动对齐了!用Creo的骨架模型做装配,效率提升不止一点点
  • 每日一Go-55、分布式 ID 生成(雪花算法 / Segment / Redis / DB)
  • 线性判别分析LDA
  • 保姆级教程:用Image2Lcd和PCtoLCD2002给STM32的OLED屏显示自定义图片(附完整代码)
  • STC8单片机驱动ESP-01S联网实战:从AT指令到GET请求获取苏宁时间(附完整源码)
  • MLOps资源管理优化:从GPU虚拟化到智能调度
  • 手把手教你用LabVIEW驱动Zebra GX420d串口打印机(附完整源码与模板文件)
  • AI与IoT融合:智能边缘计算的应用与挑战
  • 告别链接错误:手把手教你为GCC工具链配置LTO插件(以Nuclei RISC-V GCC 9.2.0为例)
  • 多任务级联CNN:MTCNN人脸检测与关键点对齐全解析
  • PyTorch 2.8镜像惊艳案例:SVD视频生成中运动一致性与画质细节实测
  • 裸金属服务器部署RKE2 Kubernetes集群构建MLOps平台实战
  • 5块钱的2N3819 JFET到手实测:从真假辨别到搭建简易非接触验电笔
  • 初始化联合(union)
  • 030、开源与闭源模型微调生态对比:选择最适合的基座模型
  • Unity 2021.3.8f1 WebGL打包发布到Nginx服务器的完整避坑指南(含Brotli/Gzip配置)
  • 计算机毕业设计:Python股票智能分析与LSTM股价预测平台 Flask框架 LSTM Keras 数据分析 可视化 深度学习 大数据 爬虫(建议收藏)✅
  • 汽车诊断开发避坑指南:ISO14229协议中那些容易忽略的NRC响应规则(附实战代码片段)
  • Less如何优化CSS文件大小_利用压缩配置去除冗余样式
  • 海上目标检测数据集2051张VOC+YOLO
  • 用Python和OpenFAST模拟漂浮式风机:从JONSWAP波浪谱到Morison方程实战
  • 如何解锁8大网盘全速下载:3分钟掌握网盘直链下载助手的完整指南
  • RadiantViewer64bit试用期重置技巧:30天后如何继续免费使用(附详细步骤)
  • 如何快速上手OpenMV IDE:从零开始构建机器视觉项目
  • 从 0 到 1 构建供应链 AI Agent Harness Engineering:需求预测、库存优化与物流调度实战
  • 在Ubuntu 16.04上为全志A40i定制Android 7.1系统镜像:一次完整的构建环境搭建与编译之旅
  • EdgeRemover:彻底告别Windows系统中顽固的Microsoft Edge浏览器
  • 从System.Numerics.Tensors到Microsoft.ML.OnnxRuntime.Managed——.NET原生AI栈的5层性能断层分析(含各层CPU/GPU/内存瓶颈对照表)
  • 告别脚本!Win11 22H2新版WSL2静态IP配置全攻略(含DNS避坑)