pyqt 分类标注工具:

import glob
import sys
import json
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableWidget, QTableWidgetItem,QSplitter, QVBoxLayout, QWidget, QPushButton, QRadioButton,QButtonGroup, QLabel, QHBoxLayout, QMessageBox
)
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtGui import QColor
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContentclass AudioAnnotator(QMainWindow):def __init__(self,base_dir):super().__init__()self.setWindowTitle("MP3标注工具 (单选标注)")self.setGeometry(100, 100, 1000, 600)  # 增大窗口尺寸# 初始化媒体播放器self.player = QMediaPlayer()# 主布局main_widget = QWidget()self.setCentralWidget(main_widget)layout = QVBoxLayout()main_widget.setLayout(layout)# 分割左右区域splitter = QSplitter(Qt.Horizontal)# 左侧:音频文件列表(表格)self.table = QTableWidget()self.table.setColumnCount(2)self.table.setHorizontalHeaderLabels(["音频文件", "标注状态"])self.table.setEditTriggers(QTableWidget.NoEditTriggers)self.table.cellClicked.connect(self.play_audio)self.table.setColumnWidth(0, 400)  # 文件名列宽self.table.setColumnWidth(1, 150)  # 状态列宽# 右侧:单选标注区域right_panel = QWidget()right_layout = QVBoxLayout()# 单选按钮组self.radio_group = QButtonGroup()self.radio_1 = QRadioButton("small (1)")self.radio_2 = QRadioButton("normal (2)")self.radio_3 = QRadioButton("3 (3)")self.radio_group.addButton(self.radio_1, 1)self.radio_group.addButton(self.radio_2, 2)self.radio_group.addButton(self.radio_3, 3)self.radio_group.buttonClicked[int].connect(self.on_radio_selected)right_layout.addWidget(QLabel("标注选项:"))right_layout.addWidget(self.radio_1)right_layout.addWidget(self.radio_2)right_layout.addWidget(self.radio_3)right_layout.addStretch()right_panel.setLayout(right_layout)# 底部按钮self.btn_save = QPushButton("保存标注")self.btn_save.clicked.connect(self.save_annotation)# 添加到布局splitter.addWidget(self.table)splitter.addWidget(right_panel)layout.addWidget(splitter)layout.addWidget(self.btn_save)self.json_path=os.path.basename(base_dir)+'.json'files = glob.glob(base_dir + "/*.mp3")self.audio_files = files# 加载历史标注self.annotations = {}self.load_annotations()self.load_audio_files()def on_radio_selected(self, checked_id):print(f"选中了按钮 ID: {checked_id}")current_row = self.table.currentRow()if current_row >= 0:audio_file = self.audio_files[current_row]checked_id = self.radio_group.checkedId()if checked_id == -1:QMessageBox.warning(self, "警告", "请选择标注选项!")return# 更新标注字典self.annotations[audio_file] = checked_id# 保存到JSON文件with open(self.json_path, "w", encoding="utf-8") as f:json.dump(self.annotations, f, ensure_ascii=False, indent=4)# 更新表格显示self.load_audio_files()def load_audio_files(self):"""加载音频文件到表格并显示标注状态"""self.table.setRowCount(len(self.audio_files))# 标注选项映射label_map = {1: "small", 2: "normal", 3: "3"}for i, file in enumerate(self.audio_files):# 文件名列file_item = QTableWidgetItem(file)self.table.setItem(i, 0, file_item)# 状态列status_item = QTableWidgetItem()if file in self.annotations:label_id = self.annotations[file]status_item.setText(f"已标注: {label_map.get(label_id, '未知')}")file_item.setBackground(QColor(200, 255, 200))  # 浅绿色背景status_item.setBackground(QColor(200, 255, 200))else:status_item.setText("未标注")file_item.setBackground(QColor(255, 200, 200))  # 浅红色背景status_item.setBackground(QColor(255, 200, 200))self.table.setItem(i, 1, status_item)def play_audio(self, row, column):if column > 0:  # 只在点击第一列时触发returnfile_path = self.audio_files[row]print('start play',file_path)media_content = QMediaContent(QUrl.fromLocalFile(file_path))self.player.setMedia(media_content)self.player.play()# 加载该音频的历史标注if file_path in self.annotations:checked_id = self.annotations[file_path]self.radio_group.button(checked_id).setChecked(True)else:self.radio_group.setExclusive(False)for btn in self.radio_group.buttons():btn.setChecked(False)self.radio_group.setExclusive(True)def save_annotation(self):"""保存标注到JSON文件"""current_row = self.table.currentRow()if current_row >= 0:audio_file = self.audio_files[current_row]checked_id = self.radio_group.checkedId()if checked_id == -1:QMessageBox.warning(self, "警告", "请选择标注选项!")return# 更新标注字典self.annotations[audio_file] = checked_id# 保存到JSON文件with open(self.json_path, "w", encoding="utf-8") as f:json.dump(self.annotations, f, ensure_ascii=False, indent=4)# 更新表格显示self.load_audio_files()QMessageBox.information(self, "成功", f"标注已保存:{os.path.basename(audio_file)} -> {checked_id}")else:QMessageBox.warning(self, "警告", "请先选中音频文件!")def load_annotations(self):"""加载历史标注文件"""if os.path.exists(self.json_path):try:with open(self.json_path, "r", encoding="utf-8") as f:self.annotations = json.load(f)# 转换键为绝对路径(如果保存的是相对路径)base_dir = os.path.dirname(os.path.abspath(self.json_path))fixed_annotations = {}for k, v in self.annotations.items():if not os.path.isabs(k):fixed_path = os.path.join(base_dir, k)if os.path.exists(fixed_path):fixed_annotations[fixed_path] = velse:fixed_annotations[k] = velse:fixed_annotations[k] = vself.annotations = fixed_annotationsexcept Exception as e:QMessageBox.warning(self, "警告", f"加载标注文件出错: {str(e)}")self.annotations = {}if __name__ == "__main__":base_dir = r"/Users/lbg/Documents/data/audio_0817_low"app = QApplication(sys.argv)window = AudioAnnotator(base_dir)window.show()sys.exit(app.exec_())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95843.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95843.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95843.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算-Kubernetes+Istio 实现金丝雀发布:流量管理、熔断、流量镜像、ingreess、污点及pv案例实战

介绍 在微服务架构中,如何安全、高效地实现服务发布与流量管理是保障业务稳定性的核心挑战。金丝雀发布(Canary Release)、灰度发布等策略通过精细化的流量控制,可有效降低新版本上线风险, Istio 作为主流的服务网格(Service Mesh)工具。 此次Istio 在 Kubernetes 集群…

12.web api 3

定时器-间歇函数

ComfyUI进阶:EchoMimic插件全解析,让静态肖像实现音频驱动的精准口型动画

在数字内容创作中,让静态肖像“开口说话”并做出自然表情,是提升交互感与沉浸感的关键。传统动画制作需专业人员逐帧调整口型与表情,成本高且效率低。ComfyUI的EchoMimic插件通过音频驱动技术,实现了“输入音频→自动生成匹配口型…

链式前向星、vector存图

场景设定 想象你是一个社交达人,要记录你和所有朋友的关系(这就是“图”)。每个朋友是一个节点,关系是一条边。你需要快速回答:“我有哪些朋友?”(遍历邻居)。方式1:链式…

YAML 中定义 List 的几种方式

在 YAML 配置文件中定义 List 并在 Spring 应用中注入是非常常见的操作,下面详细介绍具体写法和注入方式。一、YAML 中定义 List 的几种方式1. 缩进式写法(推荐)最常用的方式,通过短横线 - 加空格表示列表项:yaml# app…

C# 反射和特性(自定义特性)

自定义特性 你或许已经注意到了,应用特性的语法和之前见过的其他语法有很大不同。你可能会觉得特 性是一种完全不同的结构类型,其实不是,特性只是一种特殊的类。 有关特性类的一些要点如下。 用户自定义的特性类叫作自定义特性。所有特性类都…

科目二的四个电路

一.K21电动机单连续运转接线(带点动控制)1.电路图2.主线路这可很明了,是一条直线,从上接到下就OK了,然后从热继电器出来,接到SB3按钮的常闭触点上接着往下走一端接到SB2的常闭触点上,接着往下走,走到接触器的线圈上,从L2借一条火线出来,从熔断器的上端接入,另一端接…

【位运算】查询子数组最大异或值|2693

本文涉及知识点 位运算、状态压缩、枚举子集汇总 3277. 查询子数组最大异或值 给你一个由 n 个整数组成的数组 nums,以及一个大小为 q 的二维整数数组 queries,其中 queries[i] [li, ri]。 对于每一个查询,你需要找出 nums[li…ri] 中任…

HTML DOM 方法

HTML DOM 方法 引言 HTML DOM(文档对象模型)是HTML文档的编程接口,它允许开发者通过JavaScript来操作HTML文档中的元素。DOM 方法是DOM编程的核心,它提供了丰富的操作手段来改变网页的结构、样式和行为。本文将详细介绍HTML DOM中…

w嵌入式分享合集68

自己的原文哦~ https://blog.51cto.com/whaosoft/14133002 一、一键开关机电路的设计方案 方案一:电路图 一键开关机电路分析如下: 电路工作流程如下: Key按下瞬间,Q2、Q1导通,7805输入电压在8.9V左右&…

FFmpeg QoS 处理

FFmpeg 中的 QoS (服务质量) 处理主要关注于实时流媒体传输中的时序控制、丢帧策略和网络适应等方面。以下是 FFmpeg 中 QoS 相关的关键机制和配置方法。1. 基本 QoS 机制丢帧策略 (Frame Dropping)cAVDictionary *options NULL; av_dict_set(&options, "framedrop&q…

TexStudio中的Latex,PDFLatex,XeLatex和LuaLatex的区别

多种LaTeX编译器一、多种LaTeX编译器 1.1 PDFLaTeX(1994年) 默认、最常用的引擎。 输入文件通常是 ASCII 或 UTF-8 编码(但中文需要 CJK 宏包或 ctex 宏包支持)。 字体选择受限:只能使用 TeX 自带的字体或者 Type 1…

容器化部署:用Docker封装机器翻译模型与服务详解

文章目录一、机器翻译容器化的技术栈选型1.1 为什么需要容器化MT模型?1.2 基础镜像选择对比1.3 典型依赖分层方案1.4 性能对比(容器化 vs 原生部署)二、关键部署模式2.1 轻量级API服务封装2.2 模型热更新策略三、Docker镜像构建3.1 编写Docke…

leetcode_42 接雨水

1. 题意 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 2. 题解 这个题不会做,全部是看得题解捏。 不过能看懂题解感觉自己也很棒了! 看完题解后感觉最难的是如何求出有多少…

Spring Boot 整合 Thymeleaf 模板引擎:从零开始的完整指南

引言:为什么选择 Thymeleaf? Thymeleaf 是一个现代化的服务器端 Java 模板引擎,专为 Web 开发而设计。与 JSP 不同,Thymeleaf 模板是纯 HTML 文件,可以直接在浏览器中预览,无需后端服务器支持。这种"…

pytest介绍(python测试框架)(@pytest.mark.parametrize、@pytest.fixtures)

文章目录**1. 核心特点**- **简洁易用**:无需复杂的配置,只需编写简单的函数或类即可进行测试。- **丰富的断言**:直接使用 Python 内置的 assert 语句,失败时提供详细的错误信息。- **自动发现测试**:通过约定的命名规…

[Python 基础课程]继承

在 Python 的面向对象编程(OOP)中,继承(Inheritance) 是一种重要的机制,它允许一个类(称为子类或派生类)从另一个类(称为父类、基类或超类)中继承属性和方法。…

QT之设计器组件功能(8大类55个组件)

组件名称 功能描述关键属性1. Layouts(布局组件)(1) Vertical Layout(垂直布局)将子控件按垂直方向依次排列layoutSpacing:控件之间的间距layoutMargin:布局边缘的边距layoutStretch:设置各控件…

java中list的api详细使用

在Java中,List是集合框架中最常用的接口之一,继承自Collection,代表有序、可重复的元素集合(允许null元素)。其核心实现类有ArrayList(数组实现,随机访问高效)、LinkedList&#xff…

Azure AI Search 探索总结

Azure AI Search 原名 Azure Cognitive Service,是Azure中用来给AI项目构建知识库的组件。知识库本质和数据库很像,但是内部的存储结构和检索算法不一样。比如并不是知识库的每一列都可以用来过滤、检索或group by,而是要根据实际情况配置。A…