Commit 46f8dd34 by Yuhaibo

merge: 保留YHBdebug分支版本解决冲突

parents 8b8517af 9385bbba
...@@ -66,4 +66,8 @@ build/ ...@@ -66,4 +66,8 @@ build/
# 忽略配置文件中的敏感信息 # 忽略配置文件中的敏感信息
config/secrets.yaml config/secrets.yaml
config/private.yaml config/private.yaml
\ No newline at end of file
# 忽略特定的处理器文件(不上传)
handlers/modelpage/model_training_handler.py
handlers/videopage/detection.py
\ No newline at end of file
...@@ -785,7 +785,7 @@ class MainWindow( ...@@ -785,7 +785,7 @@ class MainWindow(
# 保存第一个面板的引用(兼容现有代码) # 保存第一个面板的引用(兼容现有代码)
self.channelPanel = self.channelPanels[0] if self.channelPanels else None self.channelPanel = self.channelPanels[0] if self.channelPanels else None
# 🔥 创建4个历史视频面板(用于曲线模式的历史回放布局) # 🔥 创建4个历史视频面板(用于曲线模式布局的历史回放子布局)
try: try:
from .widgets.videopage import HistoryVideoPanel from .widgets.videopage import HistoryVideoPanel
except ImportError: except ImportError:
...@@ -812,8 +812,8 @@ class MainWindow( ...@@ -812,8 +812,8 @@ class MainWindow(
"""创建曲线模式布局:左侧垂直排列通道 + 右侧曲线面板 """创建曲线模式布局:左侧垂直排列通道 + 右侧曲线面板
包含两个子布局: 包含两个子布局:
- 子布局0:实时检测模式(带任务选择和底部按钮) - 子布局0:同步布局(带任务选择和底部按钮)
- 子布局1:历史回放模式(无任务选择和底部按钮) - 子布局1:历史回放布局(无任务选择和底部按钮)
🔥 两个子布局共用同一个CurvePanel(右侧) 🔥 两个子布局共用同一个CurvePanel(右侧)
""" """
...@@ -844,12 +844,12 @@ class MainWindow( ...@@ -844,12 +844,12 @@ class MainWindow(
# 🔥 创建左侧子布局栈(实时检测 vs 历史回放) # 🔥 创建左侧子布局栈(实时检测 vs 历史回放)
self.curveLayoutStack = QtWidgets.QStackedWidget() self.curveLayoutStack = QtWidgets.QStackedWidget()
self.curveLayoutStack.setFixedWidth(660) self.curveLayoutStack.setFixedWidth(660)
self._curve_sub_layout_mode = 0 # 0=实时检测, 1=历史回放 self._curve_sub_layout_mode = 0 # 0=同步布局, 1=历史回放布局
# === 子布局0:实时检测模式(左侧通道列表)=== # === 子布局0:同步布局(左侧通道列表)===
self._createRealtimeCurveSubLayout() self._createRealtimeCurveSubLayout()
# === 子布局1:历史回放模式(左侧历史视频面板容器)=== # === 子布局1:历史回放布局(左侧历史视频面板容器)===
self._createHistoryCurveSubLayout() self._createHistoryCurveSubLayout()
# 布局结构:左侧子布局栈 + 右侧共用CurvePanel # 布局结构:左侧子布局栈 + 右侧共用CurvePanel
...@@ -881,7 +881,7 @@ class MainWindow( ...@@ -881,7 +881,7 @@ class MainWindow(
self.curve_channel_layout.setContentsMargins(5, 5, 5, 5) self.curve_channel_layout.setContentsMargins(5, 5, 5, 5)
self.curve_channel_layout.setSpacing(10) self.curve_channel_layout.setSpacing(10)
# 初始化通道包裹容器列表(实时检测模式 # 初始化通道包裹容器列表(同步布局
self.channel_widgets_for_curve = [] self.channel_widgets_for_curve = []
# 创建4个通道容器(初始隐藏,等待CSV文件加载) # 创建4个通道容器(初始隐藏,等待CSV文件加载)
...@@ -924,7 +924,7 @@ class MainWindow( ...@@ -924,7 +924,7 @@ class MainWindow(
self.history_channel_layout.setContentsMargins(5, 5, 5, 5) self.history_channel_layout.setContentsMargins(5, 5, 5, 5)
self.history_channel_layout.setSpacing(10) self.history_channel_layout.setSpacing(10)
# 初始化历史视频包裹容器列表(历史回放模式 # 初始化历史视频包裹容器列表(历史回放布局
self.history_channel_widgets_for_curve = [] self.history_channel_widgets_for_curve = []
# 创建4个历史视频容器(初始隐藏,等待CSV文件加载) # 创建4个历史视频容器(初始隐藏,等待CSV文件加载)
...@@ -962,24 +962,22 @@ class MainWindow( ...@@ -962,24 +962,22 @@ class MainWindow(
def _onCurveMissionChanged(self, mission_name): def _onCurveMissionChanged(self, mission_name):
"""曲线任务选择变化(基于CSV文件动态显示)""" """曲线任务选择变化(基于CSV文件动态显示)"""
if not mission_name or mission_name == "请选择任务": if not mission_name or mission_name == "请选择任务":
print(f"[曲线布局] 未选择任务,隐藏所有通道容器")
self._updateCurveChannelDisplay([]) self._updateCurveChannelDisplay([])
return return
# 🔥 根据 curve_load_mode 决定显示逻辑 # 🔥 重新检查检测状态并切换布局
if hasattr(self, 'curvePanelHandler'): detection_running = False
curve_mode = self.curvePanelHandler.getCurveLoadMode() if hasattr(self, '_switchCurveSubLayout') and hasattr(self, '_getCurrentDetectionState'):
else: detection_running = self._getCurrentDetectionState()
curve_mode = 'realtime' self._switchCurveSubLayout(detection_running)
if curve_mode == 'realtime': # 🔥 根据检测状态决定显示逻辑(而不是依赖 getCurveLoadMode)
# 🔥 实时模式:只显示任务配置中使用的通道 if detection_running:
# 🔥 同步布局:只显示任务配置中使用的通道
selected_channels = self._getTaskChannels(mission_name) selected_channels = self._getTaskChannels(mission_name)
print(f"📊 [曲线布局-实时模式] 任务 {mission_name},显示任务使用的通道: {selected_channels}")
else: else:
# 🔥 历史模式:显示所有通道容器 # 🔥 历史回放布局:显示所有通道容器
selected_channels = ['通道1', '通道2', '通道3', '通道4'] selected_channels = ['通道1', '通道2', '通道3', '通道4']
print(f"📊 [曲线布局-历史模式] 任务 {mission_name},显示所有通道容器")
self._updateCurveChannelDisplay(selected_channels) self._updateCurveChannelDisplay(selected_channels)
...@@ -997,21 +995,15 @@ class MainWindow( ...@@ -997,21 +995,15 @@ class MainWindow(
import yaml import yaml
try: try:
# 构建任务文件夹路径 # 构建任务配置文件路径(在 database/config/mission/ 目录下)
try: try:
from database.config import get_project_root from database.config import get_project_root
project_root = get_project_root() project_root = get_project_root()
except ImportError: except ImportError:
project_root = os.getcwd() project_root = os.getcwd()
mission_path = os.path.join(project_root, 'database', 'mission_result', mission_name) # 任务配置文件在 database/config/mission/ 目录下
config_file = os.path.join(project_root, 'database', 'config', 'mission', f"{mission_name}.yaml")
if not os.path.exists(mission_path):
print(f"⚠️ [通道筛选] 任务文件夹不存在: {mission_path}")
return []
# 查找任务配置文件(.yaml文件,文件名与任务名相同)
config_file = os.path.join(mission_path, f"{mission_name}.yaml")
if not os.path.exists(config_file): if not os.path.exists(config_file):
print(f"⚠️ [通道筛选] 任务配置文件不存在: {config_file}") print(f"⚠️ [通道筛选] 任务配置文件不存在: {config_file}")
...@@ -1027,7 +1019,7 @@ class MainWindow( ...@@ -1027,7 +1019,7 @@ class MainWindow(
return [] return []
# 调试:打印配置文件的所有键 # 调试:打印配置文件的所有键
print(f" [通道筛选] 配置文件键: {list(task_config.keys())}")
# 从配置中提取使用的通道 # 从配置中提取使用的通道
# 配置格式可能是:selected_channels: ['通道2', '通道3'] 或 channels: ['channel1', 'channel2'] # 配置格式可能是:selected_channels: ['通道2', '通道3'] 或 channels: ['channel1', 'channel2']
...@@ -1039,7 +1031,6 @@ class MainWindow( ...@@ -1039,7 +1031,6 @@ class MainWindow(
channel_list = task_config['selected_channels'] channel_list = task_config['selected_channels']
if isinstance(channel_list, list): if isinstance(channel_list, list):
used_channels = [ch for ch in channel_list if isinstance(ch, str) and '通道' in ch] used_channels = [ch for ch in channel_list if isinstance(ch, str) and '通道' in ch]
print(f" [通道筛选] 从 selected_channels 读取: {used_channels}")
# 尝试其他可能的配置键名 # 尝试其他可能的配置键名
elif 'channels' in task_config: elif 'channels' in task_config:
...@@ -1104,11 +1095,11 @@ class MainWindow( ...@@ -1104,11 +1095,11 @@ class MainWindow(
# 🔥 根据当前曲线子布局模式选择要操作的容器 # 🔥 根据当前曲线子布局模式选择要操作的容器
if hasattr(self, '_curve_sub_layout_mode'): if hasattr(self, '_curve_sub_layout_mode'):
if self._curve_sub_layout_mode == 0: if self._curve_sub_layout_mode == 0:
# 实时检测模式:操作channel_widgets_for_curve # 同步布局:操作channel_widgets_for_curve
target_widgets = self.channel_widgets_for_curve if hasattr(self, 'channel_widgets_for_curve') else [] target_widgets = self.channel_widgets_for_curve if hasattr(self, 'channel_widgets_for_curve') else []
target_container = self.curve_channel_container if hasattr(self, 'curve_channel_container') else None target_container = self.curve_channel_container if hasattr(self, 'curve_channel_container') else None
else: else:
# 历史回放模式:操作history_channel_widgets_for_curve # 历史回放布局:操作history_channel_widgets_for_curve
target_widgets = self.history_channel_widgets_for_curve if hasattr(self, 'history_channel_widgets_for_curve') else [] target_widgets = self.history_channel_widgets_for_curve if hasattr(self, 'history_channel_widgets_for_curve') else []
target_container = self.history_channel_container if hasattr(self, 'history_channel_container') else None target_container = self.history_channel_container if hasattr(self, 'history_channel_container') else None
else: else:
...@@ -1148,7 +1139,6 @@ class MainWindow( ...@@ -1148,7 +1139,6 @@ class MainWindow(
if target_container: if target_container:
target_container.setFixedSize(640, total_height) target_container.setFixedSize(640, total_height)
print(f"[曲线布局] 已更新通道显示,显示 {visible_count} 个通道")
def _createModelPage(self): def _createModelPage(self):
"""创建模型管理页面""" """创建模型管理页面"""
...@@ -1493,12 +1483,17 @@ class MainWindow( ...@@ -1493,12 +1483,17 @@ class MainWindow(
更新任务面板中通道列的颜色 更新任务面板中通道列的颜色
当通道的检测状态改变时调用此方法,更新任务面板中对应通道列的背景色 当通道的检测状态改变时调用此方法,更新任务面板中对应通道列的背景色
调用 MissionPanelHandler 的方法(MainWindow 继承了 MissionPanelHandler)
""" """
print(f"🎯 [app._updateChannelColumnColor] 方法被调用")
try: try:
if hasattr(self, '_updateChannelCellColors'): # MainWindow 继承了 MissionPanelHandler,直接调用父类方法
self._updateChannelCellColors() from handlers.videopage import MissionPanelHandler
MissionPanelHandler._updateChannelColumnColor(self)
except Exception as e: except Exception as e:
print(f"⚠️ [更新通道列颜色] 失败: {e}") print(f"⚠️ [更新通道列颜色] 失败: {e}")
import traceback
traceback.print_exc()
def closeEvent(self, event): def closeEvent(self, event):
"""窗口关闭事件""" """窗口关闭事件"""
......
...@@ -5,59 +5,59 @@ channel1: ...@@ -5,59 +5,59 @@ channel1:
height: 20mm height: 20mm
name: 通道1_区域1 name: 通道1_区域1
boxes: boxes:
- - 617 - - 855
- 415 - 737
- 192 - 192
fixed_bottoms: fixed_bottoms:
- 482 - 813
fixed_tops: fixed_tops:
- 387 - 660
last_updated: '2025-11-27 15:55:10' last_updated: '2025-11-29 17:01:13'
channel2: channel2:
annotation_count: 1 annotation_count: 1
areas: areas:
area_1: area_1:
height: 20mm height: 20mm
name: 我去饿_区域1 name: 通道2_区域1
boxes: boxes:
- - 643 - - 640
- 558 - 641
- 160 - 256
fixed_bottoms: fixed_bottoms:
- 616 - 743
fixed_tops: fixed_tops:
- 534 - 538
last_updated: '2025-11-26 20:09:26' last_updated: '2025-11-29 12:49:18'
channel3: channel3:
annotation_count: 1 annotation_count: 1
areas: areas:
area_1: area_1:
height: 20mm height: 20mm
name: 3_区域1 name: 通道3_区域1
boxes: boxes:
- - 1365 - - 1306
- 915 - 762
- 128 - 224
fixed_bottoms: fixed_bottoms:
- 939 - 835
fixed_tops: fixed_tops:
- 886 - 739
last_updated: '2025-11-26 20:09:35' last_updated: '2025-11-29 12:32:57'
channel4: channel4:
annotation_count: 1 annotation_count: 1
areas: areas:
area_1: area_1:
height: 20mm height: 20mm
name: asfdhuu_区域1 name: 通道4_区域1
boxes: boxes:
- - 1689 - - 1700
- 884 - 760
- 96 - 192
fixed_bottoms: fixed_bottoms:
- 908 - 819
fixed_tops: fixed_tops:
- 860 - 729
last_updated: '2025-11-26 20:02:17' last_updated: '2025-11-29 12:30:19'
通道1: 通道1:
annotation_count: 2 annotation_count: 2
areas: areas:
......
...@@ -17,23 +17,23 @@ channels: ...@@ -17,23 +17,23 @@ channels:
name: '4' name: '4'
channel2: channel2:
general: general:
task_id: 2恶趣味 task_id: '123'
task_name: q'we task_name: '21'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\2恶趣味_q'we save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\123_21
channel3: channel3:
general: general:
task_id: '21' task_id: '123'
task_name: '321' task_name: '21'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\21_321 save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\123_21
channel4: channel4:
general: general:
task_id: '21' task_id: '1'
task_name: '321' task_name: '1'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\21_321 save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
channel1: channel1:
general: general:
task_id: '21' task_id: '1'
task_name: '321' task_name: '1'
area_count: 0 area_count: 0
safe_low: 2.0mm safe_low: 2.0mm
safe_high: 10.0mm safe_high: 10.0mm
...@@ -41,13 +41,11 @@ channel1: ...@@ -41,13 +41,11 @@ channel1:
video_format: AVI video_format: AVI
push_address: '' push_address: ''
video_path: '' video_path: ''
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\21_321 save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
areas: areas:
area_1: 通道1_区域1 area_1: 通道1_区域1
area_2: 通道1_区域2
area_heights: area_heights:
area_1: 20mm area_1: 20mm
area_2: 20mm
model: model:
model_path: d:\restructure\liquid_level_line_detection_system\database\model\detection_model\5\best.dat model_path: d:\restructure\liquid_level_line_detection_system\database\model\detection_model\5\best.dat
channel_1: channel_1:
......
task_id: '123' task_id: '123'
task_name: '21' task_name: '21'
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道2 - 通道2
- 通道3 - 通道3
......
task_id: '1'
task_name: '1'
status: 待配置
selected_channels:
- 通道1
- 通道2
- 通道3
- 通道4
created_time: '2025-11-26 19:53:35'
mission_result_folder_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
task_id: '1' task_id: '1'
task_name: '2' task_name: '2'
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道2 - 通道2
......
task_id: '1' task_id: '1'
task_name: '222' task_name: '222'
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道2 - 通道2
......
task_id: '1'
task_name: test
status: 待配置
selected_channels:
- 通道1
- 通道2
- 通道3
- 通道4
created_time: '2025-11-26 19:46:34'
mission_result_folder_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_test
task_id: '21' task_id: '21'
task_name: '321' task_name: '321'
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道2 - 通道2
......
task_id: '2'
task_name: test
status: 待配置
selected_channels:
- 通道1
- 通道2
- 通道3
- 通道4
created_time: '2025-11-26 20:01:16'
mission_result_folder_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\2_test
task_id: 2恶趣味 task_id: 2恶趣味
task_id: 2恶趣味 task_id: 2恶趣味
task_name: q'we task_name: q'we
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道2 - 通道2
created_time: '2025-11-26 14:56:26' created_time: '2025-11-26 14:56:26'
......
task_id: test
task_name: test
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 15:52:05'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\test_test
task_id: 任务
task_id: 任务
task_name: 若是
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:39:21'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\任务_若是
task_id: 企鹅
task_id: 企鹅
task_name: 1额
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:34:35'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\企鹅_1额
task_id: 去v
task_id: 去v
task_name: 去v
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:34:18'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去v_去v
task_id: 去人
task_id: 去人
task_name: '2314'
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:22:23'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去人_2314
task_id: 去问驱蚊器恶气
task_id: 去问驱蚊器恶气
task_name: 企鹅去而且
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 12:25:58'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去问驱蚊器恶气_企鹅去而且
task_id: 吃个海鲜 task_id: 吃个海鲜
task_id: 吃个海鲜 task_id: 吃个海鲜
task_name: 显示提醒他 task_name: 显示提醒他
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道4 - 通道4
created_time: '2025-11-27 11:06:03' created_time: '2025-11-27 11:06:03'
......
task_id: 大润发给 task_id: 大润发给
task_id: 大润发给 task_id: 大润发给
task_name: 上方 task_name: 上方
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道2 - 通道2
......
task_id: 文档
task_id: 文档
task_name: 啊啊
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:18:35'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\文档_啊啊
task_id: 的使得发 task_id: 的使得发
task_id: 的使得发 task_id: 的使得发
task_name: 如图微软 task_name: 如图微软
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道3 - 通道3
......
task_id: 的啊 task_id: 的啊
task_id: 的啊 task_id: 的啊
task_name: 而突然 task_name: 而突然
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道1 - 通道1
- 通道2 - 通道2
......
This source diff could not be displayed because it is too large. You can view the blob instead.
2025-11-29-16:14:45.309 0.0
2025-11-29-16:14:45.309 0.0
2025-11-29-16:14:45.519 0.0
2025-11-29-16:14:45.715 0.0
2025-11-29-16:14:45.929 0.0
2025-11-29-16:14:46.148 0.0
2025-11-29-16:14:46.335 0.0
2025-11-29-16:14:46.525 0.0
2025-11-29-16:14:46.724 0.0
2025-11-29-16:14:46.925 0.0
2025-11-29-16:14:47.116 0.0
2025-11-29-16:14:47.330 0.0
2025-11-29-16:14:47.540 0.0
2025-11-29-16:14:47.724 0.0
2025-11-29-16:14:47.929 0.0
2025-11-29-16:14:48.143 0.0
2025-11-29-16:14:48.346 0.0
2025-11-29-16:14:48.533 0.0
2025-11-29-16:14:48.744 0.0
2025-11-29-16:14:48.950 0.0
2025-11-29-16:14:49.159 0.0
2025-11-29-16:14:49.352 0.0
2025-11-29-16:14:49.552 0.0
2025-11-29-16:00:04.407 15.4
2025-11-29-16:00:04.407 15.4
2025-11-29-16:00:04.445 16.0
2025-11-29-16:00:04.640 16.2
2025-11-29-16:00:04.837 16.0
2025-11-29-16:00:05.049 16.8
2025-11-29-16:00:05.251 16.5
2025-11-29-16:00:05.449 15.1
2025-11-29-16:00:05.644 15.1
2025-11-29-16:00:05.846 15.2
2025-11-29-16:00:06.054 15.4
2025-11-29-16:00:06.257 15.7
2025-11-29-16:00:06.449 15.9
2025-11-29-16:00:06.658 15.7
2025-11-29-16:00:06.860 16.0
2025-11-29-16:00:07.054 15.5
2025-11-29-16:00:07.266 17.0
2025-11-29-16:00:07.463 17.1
2025-11-29-16:00:07.660 16.8
2025-11-29-16:00:07.870 17.0
2025-11-29-16:00:08.073 16.5
2025-11-29-16:00:08.270 16.6
This source diff could not be displayed because it is too large. You can view the blob instead.
2025-11-29-15:48:08.468 0.0
2025-11-29-15:48:08.468 0.0
2025-11-29-15:48:08.885 17.1
2025-11-29-15:48:09.053 15.5
2025-11-29-15:48:09.321 15.4
2025-11-29-15:48:09.465 0.0
2025-11-29-15:48:09.653 0.0
2025-11-29-15:48:09.876 0.0
2025-11-29-15:48:10.058 0.0
2025-11-29-15:48:10.326 0.0
2025-11-29-15:48:10.472 0.0
2025-11-29-15:48:10.653 0.0
2025-11-29-15:48:10.905 0.0
2025-11-29-15:48:11.121 0.0
2025-11-29-15:48:11.351 0.0
2025-11-29-15:48:11.495 0.0
2025-11-29-15:48:11.671 0.0
2025-11-29-15:48:11.854 0.0
2025-11-29-15:48:12.104 0.0
2025-11-29-15:48:12.308 0.0
2025-11-29-15:48:12.474 0.0
2025-11-29-15:48:12.872 0.0
2025-11-29-15:48:13.043 0.0
2025-11-29-15:48:13.221 0.0
2025-11-29-15:48:13.428 0.0
2025-11-29-15:48:13.618 0.0
2025-11-29-15:48:13.867 0.0
2025-11-29-15:48:14.050 0.0
2025-11-29-15:48:14.279 0.0
2025-11-29-15:48:14.626 0.0
2025-11-29-15:48:14.787 0.0
2025-11-29-15:48:15.016 0.0
2025-11-29-15:48:15.210 0.0
2025-11-29-15:48:15.335 0.0
2025-11-29-15:48:15.539 0.0
2025-11-29-15:48:15.715 0.0
2025-11-29-15:48:15.982 0.0
2025-11-29-15:48:16.192 0.0
2025-11-29-15:48:16.368 0.0
2025-11-29-15:48:16.575 0.0
2025-11-29-15:48:16.766 0.0
2025-11-29-15:48:16.957 0.0
2025-11-29-15:48:17.176 0.0
2025-11-29-15:48:17.370 15.9
2025-11-29-15:48:17.585 0.0
2025-11-29-15:48:17.764 15.5
2025-11-29-15:48:17.976 15.4
2025-11-29-15:48:18.209 0.0
2025-11-29-15:48:18.383 0.0
2025-11-29-15:48:18.648 0.0
2025-11-29-15:48:18.782 0.0
2025-11-29-15:48:18.974 0.0
2025-11-29-15:48:19.224 17.7
2025-11-29-15:48:19.379 0.0
2025-11-29-15:48:19.610 0.0
2025-11-29-15:48:19.788 0.0
2025-11-29-15:48:20.004 0.0
2025-11-29-15:48:20.211 0.0
2025-11-29-15:48:20.404 0.0
2025-11-29-15:48:20.597 0.0
2025-11-29-15:48:20.877 0.0
2025-11-29-15:48:21.010 0.0
2025-11-29-15:48:21.222 0.0
2025-11-29-15:48:21.422 15.5
2025-11-29-15:48:21.622 0.0
2025-11-29-15:48:21.846 0.0
2025-11-29-15:48:22.040 0.0
2025-11-29-15:48:22.261 0.0
2025-11-29-15:48:22.439 0.0
2025-11-29-15:48:22.682 0.0
2025-11-29-15:48:22.986 0.0
2025-11-29-15:48:23.180 0.0
2025-11-29-15:48:23.330 0.0
2025-11-29-15:48:23.484 0.0
2025-11-29-15:48:23.687 0.0
2025-11-29-15:48:23.907 0.0
2025-11-29-15:48:24.080 0.0
2025-11-29-15:48:24.308 0.0
2025-11-29-15:48:24.511 0.0
2025-11-29-15:48:24.700 0.0
2025-11-29-15:48:24.959 0.0
2025-11-29-15:48:25.151 0.0
2025-11-29-15:48:25.317 0.0
2025-11-29-15:48:25.532 0.0
2025-11-29-15:48:25.710 0.0
2025-11-29-15:48:25.930 17.7
2025-11-29-15:48:26.139 18.0
2025-11-29-15:48:26.449 16.7
2025-11-29-15:48:26.639 0.0
2025-11-29-15:48:26.848 0.0
2025-11-29-15:48:27.027 0.0
2025-11-29-15:48:27.263 0.0
2025-11-29-15:48:27.450 0.0
2025-11-29-15:48:27.637 0.0
2025-11-29-15:48:27.834 0.0
2025-11-29-15:48:28.034 0.0
2025-11-29-15:48:28.248 0.0
2025-11-29-15:48:28.436 0.0
2025-11-29-15:48:28.660 0.0
2025-11-29-15:48:28.909 0.0
2025-11-29-15:48:29.223 0.0
2025-11-29-15:48:29.411 0.0
2025-11-29-15:48:29.610 0.0
2025-11-29-15:48:29.849 0.0
2025-11-29-15:48:30.017 0.0
2025-11-29-15:48:30.215 0.0
2025-11-29-15:48:30.447 0.0
2025-11-29-15:48:30.648 0.0
2025-11-29-15:48:30.865 0.0
2025-11-29-15:48:31.054 0.0
2025-11-29-15:48:31.386 0.0
2025-11-29-15:48:31.569 0.0
2025-11-29-15:48:31.788 0.0
2025-11-29-15:48:31.993 0.0
2025-11-29-15:48:32.170 0.0
2025-11-29-15:48:32.395 0.0
2025-11-29-15:48:32.594 0.0
2025-11-29-15:48:32.775 0.0
2025-11-29-15:48:32.992 0.0
2025-11-29-15:48:33.233 0.0
2025-11-29-15:48:33.409 0.0
2025-11-29-15:48:33.621 0.0
2025-11-29-15:48:33.842 0.0
2025-11-29-15:48:34.046 0.0
2025-11-29-15:48:34.215 0.0
2025-11-29-15:48:34.423 0.0
2025-11-29-15:48:34.671 0.0
2025-11-29-15:48:34.857 0.0
2025-11-29-15:48:35.066 0.0
2025-11-29-15:48:35.325 0.0
2025-11-29-15:48:35.526 0.0
2025-11-29-15:48:35.724 0.0
2025-11-29-15:48:35.925 0.0
2025-11-29-15:48:36.124 0.0
2025-11-29-15:48:36.345 0.0
2025-11-29-15:48:36.538 15.7
2025-11-29-15:48:36.755 0.0
2025-11-29-15:48:36.959 0.0
2025-11-29-15:48:37.190 0.0
2025-11-29-15:48:37.408 0.0
2025-11-29-15:48:37.631 0.0
2025-11-29-15:48:37.855 0.0
2025-11-29-15:48:38.048 0.0
2025-11-29-15:48:38.261 0.0
2025-11-29-15:48:38.451 0.0
2025-11-29-15:48:38.886 0.0
2025-11-29-15:48:39.098 0.0
2025-11-29-15:48:39.332 0.0
2025-11-29-15:48:39.543 0.0
2025-11-29-15:48:39.741 0.0
2025-11-29-15:48:39.963 0.0
2025-11-29-15:48:40.146 0.0
2025-11-29-15:48:40.379 0.0
2025-11-29-15:48:40.600 0.0
2025-11-29-15:48:40.845 0.0
2025-11-29-15:48:41.032 0.0
2025-11-29-15:48:41.264 0.0
2025-11-29-15:48:41.639 0.0
2025-11-29-15:48:41.855 0.0
2025-11-29-15:48:42.048 0.0
2025-11-29-15:48:42.253 0.0
2025-11-29-15:48:42.448 0.0
2025-11-29-15:48:42.644 0.0
2025-11-29-15:48:42.849 0.0
2025-11-29-15:48:43.044 0.0
2025-11-29-15:48:43.286 17.6
2025-11-29-15:48:43.491 0.0
2025-11-29-15:48:43.688 0.0
2025-11-29-15:48:43.894 0.0
2025-11-29-15:48:44.110 0.0
2025-11-29-15:48:44.338 15.9
2025-11-29-15:48:44.549 17.6
2025-11-29-15:48:44.754 15.1
2025-11-29-15:48:44.986 0.0
2025-11-29-15:48:45.190 0.0
2025-11-29-15:48:45.385 0.0
2025-11-29-15:48:45.623 0.0
2025-11-29-15:48:45.861 0.0
2025-11-29-15:48:46.063 0.0
2025-11-29-15:48:46.279 0.0
2025-11-29-15:48:46.506 0.0
2025-11-29-15:48:46.894 0.0
2025-11-29-15:48:47.125 0.0
2025-11-29-15:48:47.323 0.0
2025-11-29-15:48:47.519 0.0
2025-11-29-15:48:47.720 0.0
2025-11-29-15:48:47.919 0.0
2025-11-29-15:48:48.121 0.0
2025-11-29-15:48:48.333 0.0
2025-11-29-15:48:48.534 0.0
2025-11-29-15:48:48.823 0.0
2025-11-29-15:48:49.073 0.0
2025-11-29-15:48:49.313 0.0
2025-11-29-15:48:49.482 0.0
2025-11-29-15:48:49.769 0.0
2025-11-29-15:48:49.971 0.0
2025-11-29-15:48:50.189 0.0
2025-11-29-15:48:50.432 0.0
2025-11-29-15:48:50.658 0.0
2025-11-29-15:48:50.896 0.0
2025-11-29-15:48:51.198 0.0
2025-11-29-15:48:51.550 0.0
2025-11-29-15:48:51.779 0.0
2025-11-29-15:48:52.003 0.0
2025-11-29-15:48:52.186 0.0
2025-11-29-15:48:52.414 0.0
2025-11-29-15:48:52.701 0.0
2025-11-29-15:48:52.918 0.0
2025-11-29-15:48:53.125 0.0
2025-11-29-15:48:53.335 0.0
2025-11-29-15:48:53.543 0.0
2025-11-29-15:48:53.770 0.0
2025-11-29-15:48:53.981 0.0
2025-11-29-15:48:54.182 0.0
2025-11-29-15:48:54.395 0.0
2025-11-29-15:48:54.620 0.0
2025-11-29-15:48:54.816 0.0
2025-11-29-15:48:55.079 0.0
2025-11-29-15:48:55.301 0.0
2025-11-29-15:48:55.635 0.0
2025-11-29-15:48:56.009 0.0
2025-11-29-15:48:56.241 0.0
2025-11-29-15:48:56.448 0.0
2025-11-29-15:48:56.663 0.0
2025-11-29-15:48:56.904 0.0
2025-11-29-15:48:57.136 0.0
2025-11-29-15:48:57.357 0.0
2025-11-29-15:48:57.611 0.0
2025-11-29-15:48:57.879 0.0
2025-11-29-15:48:58.124 15.4
2025-11-29-15:48:58.365 0.0
2025-11-29-15:48:58.643 0.0
2025-11-29-15:48:59.010 0.0
2025-11-29-15:48:59.397 0.0
2025-11-29-15:48:59.915 0.0
2025-11-29-15:49:00.425 0.0
2025-11-29-15:49:00.891 0.0
2025-11-29-15:49:01.444 0.0
2025-11-29-15:49:02.002 0.0
2025-11-29-15:49:02.568 0.0
2025-11-29-15:49:03.130 0.0
2025-11-29-15:49:03.615 0.0
2025-11-29-15:49:04.168 15.4
2025-11-29-15:49:04.880 0.0
2025-11-29-15:49:05.693 0.0
2025-11-29-15:49:06.530 0.0
2025-11-29-15:49:07.323 0.0
2025-11-29-15:49:07.844 0.0
2025-11-29-15:49:08.416 0.0
2025-11-29-15:48:49.971 0.0
2025-11-29-15:48:49.971 0.0
2025-11-29-15:48:50.189 0.0
2025-11-29-15:48:50.432 0.0
2025-11-29-15:48:50.658 0.0
2025-11-29-15:48:50.896 0.0
2025-11-29-15:48:51.198 0.0
2025-11-29-15:48:51.550 0.0
2025-11-29-15:48:51.779 0.0
2025-11-29-15:48:52.003 0.0
2025-11-29-15:48:52.186 0.0
2025-11-29-15:48:52.415 0.0
2025-11-29-15:48:52.701 0.0
2025-11-29-15:48:52.918 0.0
2025-11-29-15:48:53.125 0.0
2025-11-29-15:48:53.335 0.0
2025-11-29-15:48:53.543 0.0
2025-11-29-15:48:53.770 0.0
2025-11-29-15:48:53.981 0.0
2025-11-29-15:48:54.182 0.0
2025-11-29-15:48:54.394 0.0
2025-11-29-15:48:54.621 0.0
2025-11-29-15:48:54.816 0.0
2025-11-29-15:48:55.079 0.0
2025-11-29-15:48:55.301 0.0
2025-11-29-15:48:55.635 0.0
2025-11-29-15:48:56.009 0.0
2025-11-29-15:48:56.241 0.0
2025-11-29-15:48:56.448 0.0
2025-11-29-15:48:56.665 0.0
2025-11-29-15:48:56.904 0.0
2025-11-29-15:48:57.136 0.0
2025-11-29-15:48:57.358 0.0
2025-11-29-15:48:57.611 0.0
2025-11-29-15:48:57.879 0.0
2025-11-29-15:48:58.124 0.0
2025-11-29-15:48:58.366 0.0
2025-11-29-15:48:58.643 0.0
2025-11-29-15:48:59.010 0.0
2025-11-29-15:48:59.397 0.0
2025-11-29-15:48:59.915 0.0
2025-11-29-15:49:00.425 0.0
2025-11-29-15:49:00.891 0.0
2025-11-29-15:49:01.444 0.0
2025-11-29-15:49:02.002 0.0
2025-11-29-15:49:02.571 0.0
2025-11-29-15:49:03.131 0.0
2025-11-29-15:49:03.615 0.0
2025-11-29-15:49:04.168 0.0
2025-11-29-15:49:04.882 0.0
2025-11-29-15:49:05.693 0.0
2025-11-29-15:49:06.530 0.0
2025-11-29-15:49:07.323 0.0
2025-11-29-15:49:07.850 0.0
2025-11-29-15:49:08.419 0.0
2025-11-29-16:16:55.866 0.0
2025-11-29-16:16:56.435 0.0
2025-11-29-16:16:57.090 0.0
2025-11-29-16:16:57.981 0.0
2025-11-29-16:16:58.648 0.0
2025-11-29-16:16:59.614 0.0
2025-11-29-16:17:00.741 0.0
2025-11-29-16:17:01.434 0.0
2025-11-29-16:17:01.711 0.0
2025-11-29-16:17:01.974 0.0
2025-11-29-16:17:02.249 0.0
2025-11-29-16:17:02.487 0.0
2025-11-29-16:17:02.683 0.0
2025-11-29-16:17:02.871 0.0
2025-11-29-16:17:03.038 0.0
2025-11-29-16:17:03.197 0.0
2025-11-29-16:17:03.453 0.0
2025-11-29-16:17:03.642 0.0
2025-11-29-16:17:03.803 0.0
2025-11-29-16:17:04.008 0.0
2025-11-29-16:17:04.216 0.0
2025-11-29-16:17:30.725 0.0
2025-11-29-16:17:30.929 0.0
2025-11-29-16:17:31.273 0.0
2025-11-29-16:17:31.550 0.0
2025-11-29-16:17:31.856 0.0
2025-11-29-16:17:32.096 0.0
2025-11-29-16:17:32.411 0.0
2025-11-29-16:17:32.695 0.0
2025-11-29-16:17:32.941 0.0
2025-11-29-16:17:33.181 0.0
2025-11-29-16:17:33.477 0.0
2025-11-29-16:17:33.878 0.0
2025-11-29-16:17:34.285 0.0
2025-11-29-16:17:34.708 0.0
2025-11-29-16:17:34.989 0.0
2025-11-29-16:17:35.474 0.0
2025-11-29-16:17:35.838 20.0
2025-11-29-16:17:36.138 0.0
2025-11-29-16:17:36.596 0.0
2025-11-29-16:17:37.087 0.0
2025-11-29-16:17:37.601 0.0
2025-11-29-16:17:38.152 0.0
2025-11-29-16:17:38.675 0.0
2025-11-29-16:17:39.166 0.0
2025-11-29-16:17:39.599 0.0
2025-11-29-16:17:39.935 0.0
2025-11-29-16:17:40.111 0.0
2025-11-29-16:17:40.326 0.0
2025-11-29-16:17:40.516 0.0
2025-11-29-15:49:00.891 0.0
2025-11-29-15:49:00.891 0.0
2025-11-29-15:49:01.444 0.0
2025-11-29-15:49:02.002 0.0
2025-11-29-15:49:02.563 0.0
2025-11-29-15:49:03.131 0.0
2025-11-29-15:49:03.615 0.0
2025-11-29-15:49:04.168 0.0
2025-11-29-15:49:04.882 0.0
2025-11-29-15:49:05.693 0.0
2025-11-29-15:49:06.530 0.0
2025-11-29-15:49:07.323 0.0
2025-11-29-15:49:07.844 0.0
2025-11-29-15:49:08.416 0.0
2025-11-29-16:16:59.614 0.0
2025-11-29-16:17:00.741 20.0
2025-11-29-16:17:01.434 0.0
2025-11-29-16:17:01.711 0.0
2025-11-29-16:17:01.974 0.0
2025-11-29-16:17:02.249 0.0
2025-11-29-16:17:02.487 0.0
2025-11-29-16:17:02.683 0.0
2025-11-29-16:17:02.871 0.0
2025-11-29-16:17:03.038 20.0
2025-11-29-16:17:03.197 0.0
2025-11-29-16:17:03.453 0.0
2025-11-29-16:17:03.642 0.0
2025-11-29-16:17:03.803 0.0
2025-11-29-16:17:04.008 0.0
2025-11-29-16:17:04.216 0.0
2025-11-29-16:17:04.361 0.0
2025-11-29-16:17:04.556 0.0
2025-11-29-16:17:04.756 0.0
2025-11-29-16:17:04.963 0.0
2025-11-29-16:17:05.169 0.0
2025-11-29-16:17:05.368 0.0
2025-11-29-16:17:26.350 0.0
2025-11-29-16:17:26.478 0.0
2025-11-29-16:17:26.664 0.0
2025-11-29-16:17:26.852 0.0
2025-11-29-16:17:27.169 0.0
2025-11-29-16:17:27.260 0.0
2025-11-29-16:17:27.453 0.0
2025-11-29-16:17:27.729 0.0
2025-11-29-16:17:27.921 20.0
2025-11-29-16:17:28.099 0.0
2025-11-29-16:17:28.323 0.0
2025-11-29-16:17:28.482 0.0
2025-11-29-16:17:28.678 0.0
2025-11-29-16:17:28.888 0.0
2025-11-29-16:17:29.116 0.0
2025-11-29-16:17:29.340 0.0
2025-11-29-16:17:29.494 0.0
2025-11-29-16:17:29.831 0.0
2025-11-29-16:17:29.935 0.0
2025-11-29-16:17:30.166 0.0
2025-11-29-16:17:30.408 0.0
2025-11-29-16:17:30.725 0.0
2025-11-29-16:17:30.929 0.0
2025-11-29-16:17:31.273 0.0
2025-11-29-16:17:31.549 0.0
2025-11-29-16:17:31.855 0.0
2025-11-29-16:17:32.096 0.0
2025-11-29-16:17:32.411 0.0
2025-11-29-16:17:32.691 0.0
2025-11-29-16:17:32.941 0.0
2025-11-29-16:17:33.180 0.0
2025-11-29-16:17:33.477 0.0
2025-11-29-16:17:33.877 0.0
2025-11-29-16:17:34.285 0.0
2025-11-29-16:17:34.707 0.0
2025-11-29-16:17:34.989 0.0
2025-11-29-16:17:35.474 20.0
2025-11-29-16:17:35.846 0.0
2025-11-29-16:17:36.138 0.0
2025-11-29-16:17:36.596 0.0
2025-11-29-16:17:37.087 0.0
2025-11-29-16:17:37.601 0.0
2025-11-29-16:17:38.152 0.0
2025-11-29-16:17:38.675 0.0
2025-11-29-16:17:39.166 0.0
2025-11-29-16:17:39.598 0.0
2025-11-29-16:02:34.790 0.0
2025-11-29-16:02:34.790 0.0
2025-11-29-16:02:35.090 0.0
2025-11-29-16:02:35.440 0.0
2025-11-29-16:02:35.773 0.0
2025-11-29-16:02:36.035 0.0
2025-11-29-16:02:36.302 0.0
2025-11-29-16:02:36.611 0.0
2025-11-29-16:02:36.921 0.0
2025-11-29-16:02:37.332 0.0
2025-11-29-16:02:37.585 0.0
2025-11-29-16:02:37.793 0.0
2025-11-29-16:02:38.141 0.0
2025-11-29-16:02:38.443 0.0
2025-11-29-16:02:39.099 0.0
2025-11-29-16:02:39.844 0.0
2025-11-29-16:02:40.330 0.0
2025-11-29-16:02:40.786 0.0
2025-11-29-16:02:41.395 0.0
2025-11-29-16:02:41.995 0.0
2025-11-29-16:02:42.642 0.0
2025-11-29-16:02:43.173 0.0
2025-11-29-16:02:43.899 0.0
2025-11-29-16:02:44.552 0.0
2025-11-29-16:02:38.443 0.0
2025-11-29-16:02:38.443 0.0
2025-11-29-16:02:39.099 0.0
2025-11-29-16:02:39.844 20.0
2025-11-29-16:02:40.330 0.0
2025-11-29-16:02:40.786 0.0
2025-11-29-16:02:41.395 0.0
2025-11-29-16:02:41.995 20.0
2025-11-29-16:02:42.642 0.0
2025-11-29-16:02:43.173 20.0
2025-11-29-16:02:43.899 0.0
2025-11-29-16:02:44.552 20.0
2025-11-29-16:02:44.950 0.0
2025-11-29-16:02:45.120 0.0
2025-11-29-16:02:45.334 0.0
2025-11-29-16:02:45.539 0.0
2025-11-29-16:02:45.783 20.0
2025-11-29-16:02:45.960 20.0
2025-11-29-16:02:46.181 20.0
2025-11-29-16:02:46.368 20.0
2025-11-29-16:02:46.508 20.0
2025-11-29-16:02:46.684 0.0
2025-11-29-16:02:46.892 20.0
2025-11-29-16:02:47.101 20.0
2025-11-29-16:02:47.306 20.0
2025-11-29-16:02:47.494 20.0
2025-11-29-16:02:47.698 20.0
2025-11-29-16:02:47.891 0.0
2025-11-29-16:02:48.105 20.0
2025-11-29-16:02:48.304 20.0
2025-11-29-16:02:48.511 0.0
2025-11-29-16:02:48.705 0.0
2025-11-29-16:02:48.913 0.0
2025-11-29-16:02:49.111 20.0
2025-11-29-16:02:49.334 0.0
2025-11-29-16:02:49.539 20.0
2025-11-29-16:02:49.737 0.0
2025-11-29-16:02:49.936 0.0
2025-11-29-16:02:50.142 0.0
2025-11-29-16:02:50.338 20.0
2025-11-29-16:02:50.545 0.0
2025-11-29-16:02:50.752 0.0
2025-11-29-16:02:50.946 0.0
2025-11-29-16:02:51.154 0.0
2025-11-29-16:02:51.422 0.0
2025-11-29-16:02:51.563 0.0
2025-11-29-16:02:51.760 0.0
2025-11-29-16:02:51.971 0.0
2025-11-29-16:02:52.163 0.0
2025-11-29-16:02:52.367 0.0
2025-11-29-16:02:52.654 0.0
2025-11-29-16:02:41.995 0.0
2025-11-29-16:02:41.995 0.0
2025-11-29-16:02:42.643 0.0
2025-11-29-16:02:43.174 0.0
2025-11-29-16:02:43.899 0.0
2025-11-29-16:02:44.552 0.0
2025-11-29-16:02:44.950 20.0
2025-11-29-16:02:45.120 0.0
2025-11-29-16:02:45.334 0.0
2025-11-29-16:02:45.540 0.0
2025-11-29-16:02:45.783 0.0
2025-11-29-16:02:45.961 0.0
2025-11-29-16:02:46.181 0.0
2025-11-29-16:02:46.368 0.0
task_id: 2恶趣味 task_id: 2恶趣味
task_id: 2恶趣味 task_id: 2恶趣味
task_name: q'we task_name: q'we
status: 待配置 status: 未启动
selected_channels: selected_channels:
- 通道2 - 通道2
created_time: '2025-11-26 14:56:26' created_time: '2025-11-26 14:56:26'
......
task_id: test
task_name: test
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 15:52:05'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\test_test
2025-11-29-15:54:49.838 17.4
2025-11-29-15:54:49.838 17.4
2025-11-29-15:54:49.904 16.6
2025-11-29-15:54:50.120 16.5
2025-11-29-15:54:50.323 16.2
2025-11-29-15:54:50.537 16.0
2025-11-29-15:54:50.737 16.2
2025-11-29-15:54:51.036 16.5
2025-11-29-15:54:51.174 0.0
2025-11-29-15:54:51.311 0.0
2025-11-29-15:54:51.601 0.0
2025-11-29-15:54:51.758 17.1
2025-11-29-15:54:52.010 0.0
2025-11-29-15:54:52.199 16.6
2025-11-29-15:54:52.375 16.3
2025-11-29-15:54:52.620 17.0
2025-11-29-15:54:52.831 15.9
2025-11-29-15:54:53.131 16.2
2025-11-29-15:54:53.288 16.3
2025-11-29-15:54:53.486 17.1
2025-11-29-15:54:53.663 17.0
2025-11-29-15:54:53.905 17.3
2025-11-29-15:54:54.086 16.8
2025-11-29-15:54:54.268 16.6
2025-11-29-15:54:54.509 17.0
2025-11-29-15:54:54.711 16.2
2025-11-29-15:54:54.921 17.0
2025-11-29-15:54:55.146 17.1
2025-11-29-15:54:55.363 17.0
2025-11-29-15:54:55.585 17.3
2025-11-29-15:54:55.778 17.3
2025-11-29-15:54:55.993 17.3
2025-11-29-15:54:56.210 16.8
2025-11-29-15:54:56.409 16.3
2025-11-29-15:54:56.605 17.3
2025-11-29-15:54:56.791 16.5
2025-11-29-15:54:56.968 16.8
2025-11-29-15:54:57.216 16.8
2025-11-29-15:54:57.384 0.0
2025-11-29-15:54:57.608 16.6
2025-11-29-15:54:57.830 16.8
2025-11-29-15:54:58.022 0.0
2025-11-29-15:54:58.210 17.1
2025-11-29-15:54:58.404 16.6
2025-11-29-15:54:58.660 16.2
2025-11-29-15:54:58.826 16.5
2025-11-29-15:54:59.015 16.5
2025-11-29-15:54:59.212 16.5
2025-11-29-15:54:59.430 14.8
2025-11-29-15:52:34.752 0.0
2025-11-29-15:52:34.752 0.0
2025-11-29-15:52:34.788 0.0
2025-11-29-15:52:35.013 0.0
2025-11-29-15:52:35.205 0.0
2025-11-29-15:52:35.436 0.0
2025-11-29-15:52:35.645 0.0
2025-11-29-15:52:35.920 19.1
2025-11-29-15:52:36.032 19.1
2025-11-29-15:52:36.270 19.1
2025-11-29-15:52:36.457 19.0
2025-11-29-15:52:36.689 19.1
2025-11-29-15:52:36.876 19.1
2025-11-29-15:52:37.094 19.1
2025-11-29-15:52:37.286 19.1
2025-11-29-15:52:37.476 19.1
2025-11-29-15:52:37.729 19.1
2025-11-29-15:52:37.897 19.1
2025-11-29-15:52:38.118 0.0
2025-11-29-15:52:38.324 18.7
2025-11-29-15:52:38.544 18.4
2025-11-29-15:52:38.748 0.0
2025-11-29-15:52:38.938 0.0
2025-11-29-15:52:39.149 0.0
2025-11-29-15:52:39.382 0.0
2025-11-29-15:52:39.568 0.0
2025-11-29-15:52:39.766 0.0
2025-11-29-15:52:39.985 0.0
2025-11-29-15:52:40.216 19.1
2025-11-29-15:52:40.428 19.1
2025-11-29-15:52:40.625 19.1
2025-11-29-15:52:40.830 0.0
2025-11-29-15:52:41.031 0.0
2025-11-29-15:52:41.244 0.0
2025-11-29-15:52:41.454 0.0
2025-11-29-15:52:41.691 0.0
2025-11-29-15:52:41.878 0.0
2025-11-29-15:52:42.112 0.0
2025-11-29-15:52:42.314 19.1
2025-11-29-15:52:42.521 19.1
2025-11-29-15:52:42.718 19.2
2025-11-29-15:52:42.903 19.2
2025-11-29-15:52:43.235 19.1
2025-11-29-15:52:43.370 19.1
2025-11-29-15:52:43.520 19.1
2025-11-29-15:52:43.708 19.0
2025-11-29-15:52:43.916 19.0
2025-11-29-15:52:44.129 19.0
2025-11-29-15:52:44.341 19.1
2025-11-29-15:52:44.546 19.1
2025-11-29-15:52:44.768 19.1
2025-11-29-15:52:44.969 19.1
2025-11-29-15:52:45.159 19.0
2025-11-29-15:52:45.353 19.0
2025-11-29-15:52:45.557 19.0
2025-11-29-15:52:45.763 19.0
2025-11-29-15:52:45.981 19.0
2025-11-29-15:52:46.182 19.1
2025-11-29-15:52:46.375 19.1
2025-11-29-15:52:46.580 19.1
2025-11-29-15:52:46.788 19.1
2025-11-29-15:52:46.989 19.1
2025-11-29-15:52:47.200 19.0
2025-11-29-15:52:47.403 19.1
2025-11-29-15:52:47.618 19.1
2025-11-29-15:52:47.821 19.1
2025-11-29-15:52:48.017 0.0
2025-11-29-15:52:48.224 0.0
2025-11-29-15:52:48.454 0.0
2025-11-29-15:52:48.647 0.0
2025-11-29-15:52:48.850 0.0
2025-11-29-15:52:49.044 19.2
2025-11-29-15:52:49.274 19.2
2025-11-29-15:52:49.474 0.0
2025-11-29-15:52:49.672 0.0
2025-11-29-15:52:49.876 19.2
2025-11-29-15:52:50.060 19.1
2025-11-29-15:52:50.266 0.0
2025-11-29-15:52:50.471 0.0
2025-11-29-15:52:50.663 0.0
2025-11-29-15:52:50.901 19.1
2025-11-29-15:52:51.079 19.1
2025-11-29-15:52:51.277 19.1
2025-11-29-15:52:51.474 19.1
2025-11-29-15:52:51.670 19.1
2025-11-29-15:52:51.881 19.2
2025-11-29-15:52:52.086 19.1
2025-11-29-15:52:52.347 19.2
2025-11-29-15:52:52.479 19.0
2025-11-29-15:52:52.738 19.2
2025-11-29-15:52:52.866 19.2
2025-11-29-15:52:53.058 19.2
2025-11-29-15:52:53.246 19.2
2025-11-29-15:52:53.470 19.1
2025-11-29-15:52:53.659 19.2
2025-11-29-15:52:53.849 0.0
2025-11-29-15:52:54.076 19.1
2025-11-29-15:52:54.260 19.1
2025-11-29-15:52:54.467 19.1
2025-11-29-15:52:54.744 19.2
2025-11-29-15:52:54.921 19.2
2025-11-29-15:52:55.150 19.2
2025-11-29-15:52:55.323 19.2
2025-11-29-15:52:55.511 19.2
2025-11-29-15:52:55.703 0.0
2025-11-29-15:52:55.933 19.2
2025-11-29-15:52:56.121 19.2
2025-11-29-15:52:56.341 19.1
2025-11-29-15:52:56.524 19.2
2025-11-29-15:52:56.718 19.1
2025-11-29-15:52:56.914 19.2
2025-11-29-15:52:57.114 0.0
2025-11-29-15:52:57.357 0.0
2025-11-29-15:52:57.533 0.0
2025-11-29-15:52:57.736 0.0
2025-11-29-15:52:57.956 19.1
2025-11-29-15:52:58.136 0.0
2025-11-29-15:52:58.345 0.0
2025-11-29-15:52:58.556 0.0
2025-11-29-15:52:58.744 0.0
2025-11-29-15:52:58.953 0.0
2025-11-29-15:52:59.149 0.0
2025-11-29-15:52:59.357 0.0
2025-11-29-15:52:59.551 0.0
2025-11-29-15:52:59.758 0.0
2025-11-29-15:52:59.963 0.0
2025-11-29-15:53:00.170 19.1
2025-11-29-15:53:00.363 19.1
2025-11-29-15:53:00.585 19.1
2025-11-29-15:53:00.769 19.1
2025-11-29-15:53:00.972 19.1
2025-11-29-15:53:01.175 19.0
2025-11-29-15:53:01.380 19.1
2025-11-29-15:53:01.598 0.0
2025-11-29-15:53:01.788 0.0
2025-11-29-15:53:01.979 19.2
2025-11-29-15:53:02.186 0.0
2025-11-29-15:53:02.432 0.0
2025-11-29-15:53:02.592 0.0
2025-11-29-15:53:02.781 0.0
2025-11-29-15:53:03.091 0.0
2025-11-29-15:53:03.147 19.1
2025-11-29-15:53:03.346 19.1
2025-11-29-15:53:03.558 19.1
2025-11-29-15:53:03.762 19.1
2025-11-29-15:53:03.964 19.1
2025-11-29-15:53:04.169 19.1
2025-11-29-15:53:04.367 19.1
2025-11-29-15:53:04.576 19.1
2025-11-29-15:53:04.773 19.2
2025-11-29-15:53:04.981 19.1
2025-11-29-15:53:05.174 19.2
2025-11-29-15:53:05.371 19.1
2025-11-29-15:53:05.572 19.1
2025-11-29-15:53:05.788 19.2
2025-11-29-15:53:05.992 19.1
2025-11-29-15:53:06.197 19.2
2025-11-29-15:53:06.412 19.2
2025-11-29-15:53:06.619 19.2
2025-11-29-15:53:06.828 19.2
2025-11-29-15:53:07.037 19.1
2025-11-29-15:53:07.261 19.1
2025-11-29-15:53:07.449 19.1
2025-11-29-15:53:07.656 19.1
2025-11-29-15:53:07.863 19.1
2025-11-29-15:53:08.087 19.2
2025-11-29-15:53:08.280 0.0
2025-11-29-15:53:08.493 19.2
2025-11-29-15:53:08.698 19.2
2025-11-29-15:53:08.914 0.0
2025-11-29-15:53:09.101 19.1
2025-11-29-15:53:09.302 0.0
2025-11-29-15:53:09.508 0.0
2025-11-29-15:53:09.714 18.4
2025-11-29-15:53:09.921 0.0
2025-11-29-15:53:10.126 19.0
2025-11-29-15:53:10.342 19.1
2025-11-29-15:53:10.537 19.1
2025-11-29-15:53:10.741 19.0
2025-11-29-15:53:10.947 0.0
2025-11-29-15:53:11.143 18.4
2025-11-29-15:53:11.347 19.0
2025-11-29-15:53:11.552 19.0
2025-11-29-15:53:40.333 0.0
2025-11-29-15:53:40.377 0.0
2025-11-29-15:53:40.578 0.0
2025-11-29-15:53:40.780 0.0
2025-11-29-15:53:40.995 0.0
2025-11-29-15:53:41.203 0.0
2025-11-29-15:53:41.373 0.0
2025-11-29-15:53:41.585 0.0
2025-11-29-15:53:41.795 0.0
2025-11-29-15:53:42.005 0.0
2025-11-29-15:53:42.223 0.0
2025-11-29-15:53:42.432 0.0
2025-11-29-15:53:42.615 0.0
2025-11-29-15:53:42.823 0.0
2025-11-29-15:53:43.015 0.0
2025-11-29-15:53:43.234 0.0
2025-11-29-15:53:43.440 0.0
2025-11-29-15:53:43.653 0.0
2025-11-29-15:53:43.852 0.0
2025-11-29-15:53:44.059 0.0
2025-11-29-15:53:44.276 0.0
2025-11-29-15:53:44.479 0.0
2025-11-29-15:53:44.684 0.0
2025-11-29-15:53:44.891 0.0
2025-11-29-15:53:45.111 0.0
2025-11-29-15:53:45.347 0.0
2025-11-29-15:53:45.577 0.0
2025-11-29-15:53:45.755 0.0
2025-11-29-15:53:45.980 0.0
2025-11-29-15:53:46.177 0.0
2025-11-29-15:53:46.357 0.0
2025-11-29-15:53:46.563 0.0
2025-11-29-15:53:46.799 0.0
2025-11-29-15:53:47.007 0.0
2025-11-29-15:53:47.199 0.0
2025-11-29-15:53:47.381 0.0
2025-11-29-15:53:47.598 0.0
2025-11-29-15:53:47.819 0.0
2025-11-29-15:53:48.012 0.0
2025-11-29-15:53:48.214 0.0
2025-11-29-15:53:48.426 0.0
2025-11-29-15:53:48.634 0.0
2025-11-29-15:53:48.802 0.0
2025-11-29-15:53:49.049 0.0
2025-11-29-15:53:49.216 0.0
2025-11-29-15:53:49.413 0.0
2025-11-29-15:53:49.610 0.0
2025-11-29-15:53:49.818 0.0
2025-11-29-15:53:50.013 0.0
2025-11-29-15:53:50.221 0.0
2025-11-29-15:53:50.432 0.0
2025-11-29-15:53:50.614 0.0
2025-11-29-15:53:50.837 0.0
2025-11-29-15:53:51.047 0.0
2025-11-29-15:53:51.247 0.0
2025-11-29-15:53:51.461 0.0
2025-11-29-15:53:51.643 0.0
2025-11-29-15:53:51.857 0.0
2025-11-29-15:53:52.058 0.0
2025-11-29-15:53:52.258 0.0
2025-11-29-15:53:52.467 0.0
2025-11-29-15:53:52.660 0.0
2025-11-29-15:53:52.865 0.0
2025-11-29-15:53:53.060 0.0
2025-11-29-15:53:53.267 0.0
2025-11-29-15:53:53.487 0.0
2025-11-29-15:53:53.669 0.0
2025-11-29-15:53:53.876 0.0
2025-11-29-15:53:54.084 0.0
2025-11-29-15:53:54.286 0.0
2025-11-29-15:53:54.480 0.0
2025-11-29-15:53:54.687 0.0
2025-11-29-15:53:54.897 0.0
2025-11-29-15:53:55.089 0.0
2025-11-29-15:53:55.307 0.0
2025-11-29-15:53:55.489 0.0
2025-11-29-15:53:55.699 0.0
2025-11-29-15:53:55.892 0.0
2025-11-29-15:53:56.101 0.0
2025-11-29-15:53:56.305 0.0
2025-11-29-15:53:56.512 0.0
2025-11-29-15:53:56.725 0.0
2025-11-29-15:53:56.904 0.0
2025-11-29-15:53:57.111 0.0
2025-11-29-15:53:57.319 0.0
2025-11-29-15:53:57.519 0.0
2025-11-29-15:53:57.714 0.0
2025-11-29-15:53:57.913 0.0
2025-11-29-15:53:58.126 0.0
2025-11-29-15:53:58.316 0.0
2025-11-29-15:53:58.524 0.0
2025-11-29-15:53:58.722 0.0
2025-11-29-15:53:58.922 0.0
2025-11-29-15:53:59.134 0.0
2025-11-29-15:53:59.329 0.0
2025-11-29-15:53:59.542 0.0
2025-11-29-15:53:59.739 0.0
2025-11-29-15:53:59.946 0.0
2025-11-29-15:54:00.145 0.0
2025-11-29-15:54:00.365 0.0
2025-11-29-15:54:00.563 0.0
2025-11-29-15:54:00.754 0.0
2025-11-29-15:54:00.964 0.0
2025-11-29-15:54:01.167 0.0
2025-11-29-15:54:01.368 0.0
2025-11-29-15:54:01.568 0.0
2025-11-29-15:54:01.766 0.0
2025-11-29-15:54:01.962 0.0
2025-11-29-15:54:02.167 0.0
2025-11-29-15:54:02.371 0.0
2025-11-29-15:54:02.581 0.0
2025-11-29-15:54:02.811 0.0
2025-11-29-15:54:03.016 0.0
2025-11-29-15:54:03.212 0.0
2025-11-29-15:54:03.417 0.0
2025-11-29-15:54:03.557 0.0
2025-11-29-15:54:03.743 0.0
2025-11-29-15:54:03.972 0.0
2025-11-29-15:54:04.158 0.0
2025-11-29-15:54:04.384 0.0
2025-11-29-15:54:04.557 0.0
2025-11-29-15:54:04.764 0.0
2025-11-29-15:54:04.960 0.0
2025-11-29-15:54:05.177 0.0
2025-11-29-15:54:05.434 0.0
2025-11-29-15:54:05.638 0.0
2025-11-29-15:54:05.829 0.0
2025-11-29-15:54:06.041 0.0
2025-11-29-15:54:06.184 0.0
2025-11-29-15:54:06.411 0.0
2025-11-29-15:54:06.639 0.0
2025-11-29-15:54:06.848 0.0
task_id: 任务
task_id: 任务
task_name: 若是
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:39:21'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\任务_若是
2025-11-29-13:39:40.946 0.0
2025-11-29-13:39:40.946 0.0
2025-11-29-13:39:40.993 0.0
2025-11-29-13:39:41.186 0.0
2025-11-29-13:39:41.387 0.0
2025-11-29-13:39:41.588 0.0
2025-11-29-13:39:41.785 0.0
2025-11-29-13:39:41.977 0.0
2025-11-29-13:39:42.180 0.0
2025-11-29-13:39:42.392 0.0
2025-11-29-13:39:42.588 0.0
2025-11-29-13:39:42.893 16.3
task_id: 企鹅
task_id: 企鹅
task_name: 1额
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:34:35'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\企鹅_1额
task_id: 去v
task_id: 去v
task_name: 去v
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:34:18'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去v_去v
task_id: 去人
task_id: 去人
task_name: '2314'
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:22:23'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去人_2314
task_id: 去问驱蚊器恶气
task_id: 去问驱蚊器恶气
task_name: 企鹅去而且
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 12:25:58'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\去问驱蚊器恶气_企鹅去而且
task_id: 文档
task_id: 文档
task_name: 啊啊
status: 未启动
selected_channels:
- 通道1
created_time: '2025-11-29 13:18:35'
mission_result_folder_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\文档_啊啊
这是综合模型,经过了多种场景的训练与测试,适应性强,准确率高。
这是综合模型,经过了多种场景的训练与测试,适应性强,准确率高。
\ No newline at end of file
# 调试代码清理进度报告
**开始时间**: 2025-11-26 19:32
**总文件数**: 64
**总调试语句数**: 3441
## 清理策略
1. print语句: 3225处 - 全部删除
2. DEBUG注释: 200处 - 全部删除
3. TODO/FIXME注释: 16处 - 保留(用于后续开发)
## 清理进度
### handlers 文件夹
#### ✅ handlers/app.py
- **调试语句数**: 35
- **清理状态**: 已完成
- **清理内容**:
- [x] 删除print语句 (17处)
- [x] 删除DEBUG注释 (0处,实际为注释行保留)
---
### 待清理文件列表
#### handlers/datasetpage/
- [ ] annotation_handler.py (21处)
- [ ] crop_preview_handler.py
- [ ] dataset_handler.py
- [ ] preprocess_handler.py
- [ ] training_handler.py
- [ ] videobrowser_handler.py
#### handlers/modelpage/
- [ ] model_loader.py
- [ ] model_operations.py
- [ ] model_set_handler.py
- [ ] training_handler.py
- [ ] tools/*.py (多个工具文件)
#### handlers/videopage/
- [ ] amplify_window_handler.py
- [ ] channelpanel_handler.py
- [ ] curvepanel_handler.py
- [ ] detection.py
- [ ] general_set_handler.py
- [ ] historypanel_handler.py
- [ ] missionpanel_handler.py
- [ ] modelsetting_handler.py
- [ ] test_handler.py
- [ ] thread_manager/*.py (多个线程管理文件)
- [ ] HK_SDK/*.py (多个SDK文件)
#### handlers/其他
- [ ] settings_handler.py
- [ ] view_handler.py
### widgets 文件夹
#### widgets/datasetpage/
- [ ] annotationtool.py
- [ ] crop_config_dialog.py
- [ ] crop_preview_panel.py
- [ ] datacollection_panel.py
- [ ] datapreprocess_panel.py
- [ ] training_panel.py
- [ ] videobrowser.py
- [ ] videoclipper.py
#### widgets/videopage/
- [ ] channelpanel.py
- [ ] curvepanel.py
- [ ] general_set.py
- [ ] historyvideopanel.py
- [ ] logicsetting_dialogue.py
- [ ] missionpanel.py
- [ ] modelsetting_dialogue.py
#### widgets/modelpage/
- [ ] modelset_page.py
- [ ] training_page.py
#### widgets/其他
- [ ] menubar.py
- [ ] responsive_layout.py
- [ ] style_manager.py
---
## 统计信息
- **已完成文件**: 4/64 (部分完成)
- **已删除语句**: 约100+/3441
- **完成百分比**: 约3%
## 已完成清理的文件
### 完全清理
1.**handlers/app.py** - 删除17处print语句
2.**widgets/style_manager.py** - 删除12处print语句和DEBUG注释
3.**widgets/responsive_layout.py** - 删除5处print语句
4.**widgets/videopage/channelpanel.py** - 删除9处print语句
5.**handlers/videopage/channelpanel_handler.py** - 删除约25处print语句
6.**handlers/view_handler.py** - 删除约30处print语句
7.**handlers/videopage/curvepanel_handler.py** - 删除约15处print语句
8.**handlers/videopage/thread_manager/thread_manager.py** - 删除约25处print语句
9.**handlers/videopage/thread_manager/threads/curve_thread.py** - 删除约20处print语句
10.**handlers/videopage/thread_manager/threads/global_detection_thread.py** - 删除约20处print语句
11.**handlers/videopage/thread_manager/threads/storage_thread.py** - 删除9处print语句
12.**handlers/videopage/thread_manager/threads/display_thread.py** - 删除5处print语句
13.**widgets/videopage/missionpanel.py** - 删除约20处print语句
14.**widgets/videopage/general_set.py** - 删除约30处print语句
15.**widgets/videopage/curvepanel.py** - 删除4处print语句
16.**widgets/videopage/historyvideopanel.py** - 删除约16处print语句和3处DEBUG注释
### 部分清理
17. 🔄 **handlers/videopage/missionpanel_handler.py** - 已清理前880行,删除约50处print语句(文件共2004行,需继续清理)
23. 🔄 **handlers/modelpage/model_test_handler.py** - 已清理约20处print语句(文件共2090行,剩余约280处,需继续清理)
### 新增完成清理
18.**widgets/datasetpage/crop_preview_panel.py** - 删除约47处print语句和2处DEBUG注释
19.**widgets/datasetpage/datacollection_panel.py** - 删除约20处print语句和1处DEBUG注释
20.**handlers/modelpage/model_page_handler.py** - 删除7处print语句和2处DEBUG注释
21.**handlers/modelpage/model_set_handler.py** - 删除47处print语句和2处DEBUG注释
22.**handlers/modelpage/model_signal_handler.py** - 删除6处print语句
## 清理进度说明
由于项目包含64个文件,共3441处调试语句,手动清理工作量较大。建议采用以下策略:
### 优先级清理顺序
1. **高优先级** - 主程序入口和核心handler (已完成大部分)
- ✅ handlers/app.py
- ✅ handlers/view_handler.py
- ✅ handlers/videopage/channelpanel_handler.py
- ✅ handlers/videopage/curvepanel_handler.py
- ✅ handlers/videopage/thread_manager/thread_manager.py
- 🔄 handlers/videopage/missionpanel_handler.py (进行中)
- ⏳ handlers/videopage/detection.py
2. **中优先级** - UI组件和样式管理 (已完成)
- ✅ widgets/style_manager.py
- ✅ widgets/responsive_layout.py
- ✅ widgets/videopage/channelpanel.py
- ✅ widgets/videopage/missionpanel.py
- ✅ widgets/videopage/general_set.py
- ✅ widgets/videopage/curvepanel.py
- ✅ widgets/videopage/historyvideopanel.py
3. **低优先级** - 测试文件和工具脚本
- ⏳ handlers/modelpage/tools/*.py
- ⏳ handlers/videopage/HK_SDK/*.py
- ⏳ widgets/datasetpage/test_*.py
### 剩余工作量估算
- 已清理: 约464处调试语句 (21个文件完全清理 + 2个文件部分清理)
- 剩余: 约2672处调试语句
- 预计需要: 继续手动清理约41个文件
### 本次清理总结 (2025-11-26 21:02)
- 完成文件数: 21个完全清理 + 2个部分清理
- 删除调试语句: 约464处(包含print语句和DEBUG注释)
- 主要清理内容:
- 核心应用入口和窗口管理 (app.py)
- 视图布局切换管理 (view_handler.py)
- 样式和布局管理系统 (style_manager.py, responsive_layout.py)
- 通道面板UI和Handler (channelpanel.py, channelpanel_handler.py)
- 曲线面板Handler (curvepanel_handler.py)
- 完整线程管理系统 (thread_manager.py, curve_thread.py, global_detection_thread.py, storage_thread.py, display_thread.py)
- 完整UI组件系统 (missionpanel.py, general_set.py, curvepanel.py, historyvideopanel.py)
- 数据集页面组件 (crop_preview_panel.py, datacollection_panel.py)
- 模型页面Handler系统 (model_page_handler.py, model_set_handler.py, model_signal_handler.py)
- 部分任务面板Handler (missionpanel_handler.py)
---
*最后更新: 2025-11-26 21:00*
# 调试语句清理报告
**清理时间**: 2025-11-26 20:31:38
**备份目录**: backups\cleanup_20251126_203137
## 清理统计
- 扫描文件总数: 108
- 修改文件数量: 58
- 删除语句总数: 540
## 详细清理记录
| 文件 | 删除数量 |
|------|----------|
| handlers\modelpage\model_test_handler.py | 85 |
| handlers\videopage\missionpanel_handler.py | 46 |
| handlers\modelpage\model_training_handler.py | 37 |
| handlers\videopage\general_set_handler.py | 33 |
| widgets\datasetpage\datapreprocess_panel.py | 30 |
| handlers\videopage\amplify_window_handler.py | 20 |
| widgets\videopage\general_set.py | 20 |
| widgets\modelpage\training_page.py | 17 |
| handlers\modelpage\test_integration.py | 14 |
| handlers\modelpage\tools\test_dat_conversion.py | 13 |
| handlers\modelpage\tools\test_bat_model.py | 12 |
| handlers\modelpage\tools\test_pt_detection.py | 12 |
| handlers\cleanup_debug_statements.py | 11 |
| widgets\videopage\channelpanel.py | 11 |
| widgets\videopage\missionpanel.py | 11 |
| handlers\datasetpage\crop_preview_handler.py | 10 |
| handlers\app.py | 9 |
| handlers\datasetpage\test_realtime_monitoring.py | 9 |
| widgets\datasetpage\datacollection_panel.py | 9 |
| widgets\datasetpage\test_labelme_integration.py | 9 |
| widgets\datasetpage\crop_preview_panel.py | 8 |
| handlers\modelpage\tools\test_bat_image_detection.py | 7 |
| handlers\modelpage\tools\test_dat_image_detection.py | 7 |
| handlers\videopage\thread_manager\result_distributor.py | 6 |
| widgets\locate_debug_statements.py | 6 |
| widgets\style_manager.py | 6 |
| widgets\videopage\curvepanel.py | 6 |
| handlers\datasetpage\datacollection_channel_handler.py | 5 |
| handlers\videopage\mock_physical_zoom_controller.py | 5 |
| handlers\videopage\detection.py | 4 |
| handlers\videopage\thread_manager\threads\display_thread.py | 4 |
| widgets\videopage\historyvideopanel.py | 4 |
| handlers\modelpage\cleanup_test_code.py | 3 |
| handlers\modelpage\model_trainingworker_handler.py | 3 |
| handlers\videopage\channelpanel_handler.py | 3 |
| handlers\videopage\curvepanel_handler.py | 3 |
| handlers\videopage\test_handler.py | 3 |
| handlers\videopage\HK_SDK\test_hikcapture.py | 3 |
| handlers\videopage\thread_manager\threads\storage_thread.py | 3 |
| handlers\videopage\thread_manager\threads\test_model_loading.py | 3 |
| widgets\datasetpage\annotationtool.py | 3 |
| widgets\datasetpage\crop_config_dialog.py | 3 |
| widgets\datasetpage\videobrowser.py | 3 |
| widgets\datasetpage\videoclipper.py | 3 |
| handlers\view_handler.py | 2 |
| handlers\modelpage\model_page_handler.py | 2 |
| handlers\modelpage\model_set_handler.py | 2 |
| widgets\modelpage\modelset_page.py | 2 |
| handlers\datasetpage\datapreprocess_handler.py | 1 |
| handlers\videopage\HK_SDK\FocusControl.py | 1 |
| handlers\videopage\HK_SDK\HCNetSDK.py | 1 |
| handlers\videopage\HK_SDK\HKcapture.py | 1 |
| handlers\videopage\thread_manager\thread_manager.py | 1 |
| widgets\menubar.py | 1 |
| widgets\datasetpage\test_crop_preview_integration.py | 1 |
| widgets\datasetpage\training_panel.py | 1 |
| widgets\videopage\logicsetting_dialogue.py | 1 |
| widgets\videopage\modelsetting_dialogue.py | 1 |
"""
调试日志模块
使用logging模块替代print进行调试输出
日志文件保存在: D:\restructure\liquid_level_line_detection_system\database\log\debuglog
"""
import logging
import os
import sys
from pathlib import Path
from datetime import datetime
from typing import Optional
class DebugLogger:
"""调试日志管理器"""
_instance = None
_loggers = {}
def __new__(cls):
"""单例模式"""
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
"""初始化日志管理器"""
if not hasattr(self, '_initialized'):
# 获取项目根目录(支持打包后的环境)
if getattr(sys, 'frozen', False):
# 打包后的环境
base_dir = Path(sys.executable).parent
else:
# 开发环境
base_dir = Path(__file__).parent.parent
self.log_dir = base_dir / "database" / "log" / "debuglog"
self.log_dir.mkdir(parents=True, exist_ok=True)
self._initialized = True
def get_logger(
self,
name: str,
level: int = logging.DEBUG,
console_output: bool = True,
file_output: bool = True
) -> logging.Logger:
"""
获取或创建logger
Args:
name: logger名称(通常使用模块名)
level: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
console_output: 是否输出到控制台
file_output: 是否输出到文件
Returns:
logging.Logger: 配置好的logger实例
"""
# 如果logger已存在,直接返回
if name in self._loggers:
return self._loggers[name]
# 创建logger
logger = logging.getLogger(name)
logger.setLevel(level)
# 清除已有的handlers(避免重复添加)
logger.handlers.clear()
# 定义日志格式
# 详细格式:时间 - 名称 - 级别 - 文件:行号 - 消息
detailed_formatter = logging.Formatter(
fmt='%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 简洁格式:时间 - 级别 - 消息
simple_formatter = logging.Formatter(
fmt='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 控制台输出(使用简洁格式)
if console_output:
console_handler = logging.StreamHandler()
console_handler.setLevel(level)
console_handler.setFormatter(simple_formatter)
logger.addHandler(console_handler)
# 文件输出(使用详细格式)
if file_output:
# 按日期创建日志文件
today = datetime.now().strftime('%Y%m%d')
log_file = self.log_dir / f"{name}_{today}.log"
file_handler = logging.FileHandler(
log_file,
mode='a',
encoding='utf-8'
)
file_handler.setLevel(level)
file_handler.setFormatter(detailed_formatter)
logger.addHandler(file_handler)
# 缓存logger
self._loggers[name] = logger
return logger
def create_module_logger(
self,
module_name: str,
level: int = logging.DEBUG
) -> logging.Logger:
"""
为模块创建专用logger(快捷方法)
Args:
module_name: 模块名称
level: 日志级别
Returns:
logging.Logger: 配置好的logger
"""
return self.get_logger(
name=module_name,
level=level,
console_output=True,
file_output=True
)
def clear_old_logs(self, days: int = 7):
"""
清理旧日志文件
Args:
days: 保留最近多少天的日志
"""
from datetime import timedelta
cutoff_date = datetime.now() - timedelta(days=days)
for log_file in self.log_dir.glob("*.log"):
try:
file_time = datetime.fromtimestamp(log_file.stat().st_mtime)
if file_time < cutoff_date:
log_file.unlink()
print(f"已删除旧日志: {log_file.name}")
except Exception as e:
print(f"删除日志文件失败 {log_file.name}: {e}")
# 全局单例实例
_debug_logger_instance = DebugLogger()
def get_logger(
name: str,
level: int = logging.DEBUG,
console_output: bool = True,
file_output: bool = True
) -> logging.Logger:
"""
获取logger的便捷函数
使用示例:
from handlers.debuglog import get_logger
logger = get_logger(__name__)
logger.debug("调试信息")
logger.info("普通信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")
Args:
name: logger名称(建议使用 __name__)
level: 日志级别
console_output: 是否输出到控制台
file_output: 是否输出到文件
Returns:
logging.Logger: 配置好的logger
"""
return _debug_logger_instance.get_logger(name, level, console_output, file_output)
def clear_old_logs(days: int = 7):
"""
清理旧日志文件的便捷函数
Args:
days: 保留最近多少天的日志
"""
_debug_logger_instance.clear_old_logs(days)
# 预定义的日志级别常量
DEBUG = logging.DEBUG # 10 - 详细的调试信息
INFO = logging.INFO # 20 - 一般信息
WARNING = logging.WARNING # 30 - 警告信息
ERROR = logging.ERROR # 40 - 错误信息
CRITICAL = logging.CRITICAL # 50 - 严重错误
if __name__ == "__main__":
"""测试代码"""
# 测试1: 基本使用
print("="*80)
print("测试1: 基本日志功能")
print("="*80)
logger = get_logger("test_module")
logger.debug("这是调试信息")
logger.info("这是普通信息")
logger.warning("这是警告信息")
logger.error("这是错误信息")
logger.critical("这是严重错误信息")
# 测试2: 不同模块的logger
print("\n" + "="*80)
print("测试2: 多个模块的logger")
print("="*80)
logger1 = get_logger("module1")
logger2 = get_logger("module2")
logger1.info("来自模块1的消息")
logger2.info("来自模块2的消息")
# 测试3: 只输出到文件
print("\n" + "="*80)
print("测试3: 只输出到文件(控制台看不到)")
print("="*80)
file_only_logger = get_logger(
"file_only",
console_output=False,
file_output=True
)
file_only_logger.info("这条消息只会出现在日志文件中")
print("(上面的消息已写入文件,但不会显示在控制台)")
# 测试4: 不同日志级别
print("\n" + "="*80)
print("测试4: 设置不同的日志级别")
print("="*80)
info_logger = get_logger("info_level", level=INFO)
info_logger.debug("这条DEBUG消息不会显示(级别太低)")
info_logger.info("这条INFO消息会显示")
info_logger.warning("这条WARNING消息会显示")
# 测试5: 异常日志
print("\n" + "="*80)
print("测试5: 记录异常信息")
print("="*80)
error_logger = get_logger("error_test")
try:
result = 1 / 0
except Exception as e:
error_logger.error(f"发生异常: {e}", exc_info=True)
print("\n" + "="*80)
print("测试完成!")
print(f"日志文件保存在: {_debug_logger_instance.log_dir}")
print("="*80)
...@@ -54,7 +54,7 @@ class ModelSetHandler: ...@@ -54,7 +54,7 @@ class ModelSetHandler:
type_layout = QtWidgets.QHBoxLayout() type_layout = QtWidgets.QHBoxLayout()
type_layout.addWidget(QtWidgets.QLabel("模型类型:")) type_layout.addWidget(QtWidgets.QLabel("模型类型:"))
type_combo = QtWidgets.QComboBox() type_combo = QtWidgets.QComboBox()
type_combo.addItems(["YOLOv8", "YOLOv11", "Faster R-CNN", "SSD", "RetinaNet", "自定义"])
type_layout.addWidget(type_combo) type_layout.addWidget(type_combo)
layout.addLayout(type_layout) layout.addLayout(type_layout)
......
...@@ -162,39 +162,14 @@ class ModelSettingsHandler: ...@@ -162,39 +162,14 @@ class ModelSettingsHandler:
# 按钮 # 按钮
button_layout = QtWidgets.QHBoxLayout() button_layout = QtWidgets.QHBoxLayout()
save_btn = QtWidgets.QPushButton("保存设置")
cancel_btn = QtWidgets.QPushButton("取消") cancel_btn = QtWidgets.QPushButton("取消")
reset_btn = QtWidgets.QPushButton("重置") reset_btn = QtWidgets.QPushButton("重置")
button_layout.addWidget(save_btn)
button_layout.addWidget(reset_btn) button_layout.addWidget(reset_btn)
button_layout.addWidget(cancel_btn) button_layout.addWidget(cancel_btn)
main_layout.addLayout(button_layout) main_layout.addLayout(button_layout)
# 连接按钮事件 # 连接按钮事件
def save_settings():
# 更新模型参数
updated_params = model_params.copy()
updated_params.update({
'type': type_edit.text(),
'confidence': confidence_spin.value(),
'iou': iou_spin.value(),
'classes': classes_spin.value(),
'input': input_edit.text(),
'device': device_combo.currentText(),
'batch_size': batch_spin.value(),
'workers': workers_spin.value(),
'epochs': epochs_spin.value(),
'blur_training': blur_spin.value(),
'description': desc_edit.toPlainText()
})
# 保存到模型集页面
self.modelSetPage._model_params[model_name] = updated_params
QtWidgets.QMessageBox.information(dialog, "保存成功", f"模型 '{model_name}' 的设置已保存")
dialog.accept()
def reset_settings(): def reset_settings():
# 重置所有设置到原始值 # 重置所有设置到原始值
type_edit.setText(model_params.get('type', '')) type_edit.setText(model_params.get('type', ''))
...@@ -209,7 +184,6 @@ class ModelSettingsHandler: ...@@ -209,7 +184,6 @@ class ModelSettingsHandler:
blur_spin.setValue(model_params.get('blur_training', 100)) blur_spin.setValue(model_params.get('blur_training', 100))
desc_edit.setPlainText(model_params.get('description', '')) desc_edit.setPlainText(model_params.get('description', ''))
save_btn.clicked.connect(save_settings)
reset_btn.clicked.connect(reset_settings) reset_btn.clicked.connect(reset_settings)
cancel_btn.clicked.connect(dialog.reject) cancel_btn.clicked.connect(dialog.reject)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
from ast import main
123131441
fsafasa
main
\ No newline at end of file
# 自动标点功能模块使用说明
## 功能概述
`auto_dot.py` 模块实现了基于YOLO分割掩码的自动标点功能,可以自动检测容器的顶部和底部位置,替代人工手动标点。
## 核心特性
- **输入**: 图片 + 检测框
- **输出**: 点位置信息 + 标注后的图片
- **检测方法**:
1. **liquid底部 + air顶部** (最可靠)
2. **liquid底部 + liquid顶部** (次选)
3. **air底部 + air顶部** (备选)
## 独立调试
### 1. 准备测试数据
将测试图片放置到:
```
D:\restructure\liquid_level_line_detection_system\test_data\test_image.jpg
```
### 2. 配置检测框
编辑 `auto_dot.py` 中的 `test_auto_dot()` 函数,修改 `boxes` 参数:
```python
# 方式1: [x1, y1, x2, y2] 格式
boxes = [
[100, 200, 300, 600], # 第一个容器
[400, 200, 600, 600], # 第二个容器
]
# 方式2: [cx, cy, size] 格式
boxes = [
[200, 400, 400], # 中心点(200, 400), 尺寸400
]
```
### 3. 运行测试
```bash
cd D:\restructure\liquid_level_line_detection_system\handlers\videopage
python auto_dot.py
```
### 4. 查看结果
- **控制台输出**: 详细的检测过程和结果
- **标注图片**: `D:\restructure\liquid_level_line_detection_system\test_output\auto_dot_result.jpg`
## API 使用示例
```python
from handlers.videopage.auto_dot import AutoDotDetector
import cv2
# 1. 创建检测器
detector = AutoDotDetector(
model_path="path/to/model.dat",
device='cuda' # 或 'cpu'
)
# 2. 加载图片
image = cv2.imread("test_image.jpg")
# 3. 定义检测框
boxes = [
[100, 200, 300, 600], # [x1, y1, x2, y2]
]
# 4. 执行检测
result = detector.detect_container_boundaries(
image=image,
boxes=boxes,
conf_threshold=0.5
)
# 5. 获取结果
if result['success']:
for container in result['containers']:
print(f"容器 {container['index']}:")
print(f" 顶部: ({container['top_x']}, {container['top']})")
print(f" 底部: ({container['bottom_x']}, {container['bottom']})")
print(f" 高度: {container['height']}px")
print(f" 置信度: {container['confidence']:.3f}")
# 保存标注图片
cv2.imwrite("result.jpg", result['annotated_image'])
```
## 输出数据结构
```python
{
'success': bool, # 检测是否成功
'containers': [
{
'index': int, # 容器索引
'top': int, # 顶部y坐标
'bottom': int, # 底部y坐标
'top_x': int, # 顶部x坐标
'bottom_x': int, # 底部x坐标
'height': int, # 容器高度(像素)
'confidence': float, # 检测置信度
'method': str # 检测方法
},
...
],
'annotated_image': np.ndarray # 标注后的图片
}
```
## 检测方法说明
### 方法1: liquid_air (最可靠)
- **容器底部**: liquid掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 同时检测到液体和空气
### 方法2: liquid_only (次选)
- **容器底部**: liquid掩码的最低点
- **容器顶部**: liquid掩码的最高点
- **适用场景**: 只检测到液体,未检测到空气
### 方法3: air_only (备选)
- **容器底部**: air掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 只检测到空气,未检测到液体
## 可视化标注
标注图片包含:
- **绿色圆点**: 容器顶部
- **红色圆点**: 容器底部
- **青色连线**: 容器高度
- **水平参考线**: 顶部和底部的水平位置
- **文字标注**: Top-N, Bottom-N, 高度值
## 注意事项
1. **模型路径**: 确保模型文件存在且可访问
2. **检测框位置**: 检测框应覆盖完整的容器区域
3. **置信度阈值**: 默认0.5,可根据实际情况调整
4. **GPU加速**: 建议使用CUDA加速,提高检测速度
## 调试技巧
1. **查看控制台输出**: 详细的检测过程日志
2. **检查标注图片**: 验证检测结果的准确性
3. **调整检测框**: 如果检测失败,尝试调整检测框的位置和大小
4. **降低置信度**: 如果检测不到掩码,尝试降低 `conf_threshold`
## 接入系统
调试成功后,可以在主系统中调用:
```python
from handlers.videopage.auto_dot import AutoDotDetector
# 在标注页面添加"自动标点"按钮
# 点击后调用 detector.detect_container_boundaries()
# 将返回的 top/bottom 坐标填充到标注点位置
```
...@@ -198,7 +198,7 @@ class ChannelPanelHandler: ...@@ -198,7 +198,7 @@ class ChannelPanelHandler:
pass pass
# 如果检测线程已在运行,重新启动以使用新引擎 # 如果检测线程已在运行,重新启动以使用新引擎
if channel_id in self._detection_flags and self._detection_flags[channel_id]: if channel_id in self._channel_detect_statuss and self._channel_detect_statuss[channel_id]:
pass pass
return True return True
...@@ -877,19 +877,11 @@ class ChannelPanelHandler: ...@@ -877,19 +877,11 @@ class ChannelPanelHandler:
if panel: if panel:
panel.updateChannelStatus(channel_id, 'connected') panel.updateChannelStatus(channel_id, 'connected')
panel.setConnected(True) panel.setConnected(True)
pass
else:
pass
# 兼容单通道场景
if hasattr(self, 'channelPanel'):
self.channelPanel.updateChannelStatus(channel_id, 'connected')
self.channelPanel.setConnected(True)
self.statusBar().showMessage( self.statusBar().showMessage(
self.tr(" 通道已连接: {} - 视频流已启动").format(channel_id) self.tr(" 通道已连接: {} - 视频流已启动").format(channel_id)
) )
except Exception as e: except Exception as e:
pass
import traceback import traceback
traceback.print_exc() traceback.print_exc()
...@@ -941,12 +933,6 @@ class ChannelPanelHandler: ...@@ -941,12 +933,6 @@ class ChannelPanelHandler:
# 🔥 保留映射(不删除),以便任务同步时能找到面板 # 🔥 保留映射(不删除),以便任务同步时能找到面板
# del self._channel_panels_map[channel_id] # 注释掉,保留映射 # del self._channel_panels_map[channel_id] # 注释掉,保留映射
# 兼容单通道场景
if hasattr(self, 'channelPanel'):
self.channelPanel.updateChannelStatus(channel_id, 'disconnected')
self.channelPanel.setConnected(False)
self.channelPanel.clearDisplay()
self.statusBar().showMessage(self.tr("⏹ 通道已断开: {}").format(channel_id)) self.statusBar().showMessage(self.tr("⏹ 通道已断开: {}").format(channel_id))
def onChannelManage(self): def onChannelManage(self):
...@@ -1429,7 +1415,7 @@ class ChannelPanelHandler: ...@@ -1429,7 +1415,7 @@ class ChannelPanelHandler:
else: else:
print(f" {channel_id} 检测引擎未就绪,检测线程将只读取帧不执行检测") print(f" {channel_id} 检测引擎未就绪,检测线程将只读取帧不执行检测")
while self._detection_flags.get(channel_id, False): while self._channel_detect_statuss.get(channel_id, False):
try: try:
loop_start_time = time.time() loop_start_time = time.time()
......
...@@ -1165,16 +1165,41 @@ class GeneralSetPanelHandler: ...@@ -1165,16 +1165,41 @@ class GeneralSetPanelHandler:
self.top_points = [] # 存储顶部标记点 self.top_points = [] # 存储顶部标记点
def add_box(self, cx, cy, size): def add_box(self, cx, cy, size):
"""添加检测区域""" """
添加检测区域,并自动计算顶部点和底部点
Args:
cx: 框中心x坐标
cy: 框中心y坐标
size: 框的边长
"""
self.boxes.append((cx, cy, size)) self.boxes.append((cx, cy, size))
# 自动计算并添加底部点和顶部点
# 底部点:box底边y坐标 - box高度的10%,x为中心
half_size = size / 2
bottom_y = cy + half_size - (size * 0.1) # 底边y - 10%高度
bottom_x = cx # x位置为box轴对称中心
self.bottom_points.append((int(bottom_x), int(bottom_y)))
# 顶部点:box顶边y坐标 + box高度的10%,x为中心
top_y = cy - half_size + (size * 0.1) # 顶边y + 10%高度
top_x = cx # x位置为box轴对称中心
self.top_points.append((int(top_x), int(top_y)))
print(f"添加框: 中心({cx}, {cy}), 边长{size}")
print(f" 底部点: ({int(bottom_x)}, {int(bottom_y)})")
print(f" 顶部点: ({int(top_x)}, {int(top_y)})")
def add_bottom(self, x, y): def add_bottom(self, x, y):
"""添加底部标记点""" """添加底部标记点(保留用于兼容性,但不再使用)"""
self.bottom_points.append((x, y)) # 此方法保留但不再使用,因为底部点会在add_box时自动添加
pass
def add_top(self, x, y): def add_top(self, x, y):
"""添加顶部标记点""" """添加顶部标记点(保留用于兼容性,但不再使用)"""
self.top_points.append((x, y)) # 此方法保留但不再使用,因为顶部点会在add_box时自动添加
pass
def get_mission_results(self): def get_mission_results(self):
"""获取标注结果""" """获取标注结果"""
......
...@@ -147,7 +147,7 @@ class TestHandler: ...@@ -147,7 +147,7 @@ class TestHandler:
QtWidgets.QMessageBox.information( QtWidgets.QMessageBox.information(
None, "成功", None, "成功",
f"配置已复制到 test.yaml!\n\n" f"配置已复制到 test.yaml!\n\n"
f"已配置通道:{', '.join(channels)}\n\n" f"已启动通道:{', '.join(channels)}\n\n"
f"配置来源:\n" f"配置来源:\n"
f"- 通道连接信息:default_config.yaml\n" f"- 通道连接信息:default_config.yaml\n"
f"- 标注数据:annotation_mission_result.yaml\n\n" f"- 标注数据:annotation_mission_result.yaml\n\n"
...@@ -914,12 +914,12 @@ class TestHandler: ...@@ -914,12 +914,12 @@ class TestHandler:
if channel_id not in config: if channel_id not in config:
config[channel_id] = {} config[channel_id] = {}
# 检查是否已配置save_liquid_data_path # 检查是否已启动save_liquid_data_path
existing_path = config[channel_id].get('save_liquid_data_path', '') or \ existing_path = config[channel_id].get('save_liquid_data_path', '') or \
config[channel_id].get('general', {}).get('save_liquid_data_path', '') config[channel_id].get('general', {}).get('save_liquid_data_path', '')
if existing_path and existing_path.strip(): if existing_path and existing_path.strip():
# 已配置,无需设置 # 已启动,无需设置
return return
# 设置默认路径:recordings/{channel_id} # 设置默认路径:recordings/{channel_id}
......
...@@ -51,7 +51,7 @@ class ChannelThreadContext: ...@@ -51,7 +51,7 @@ class ChannelThreadContext:
# ========== 控制标志 ========== # ========== 控制标志 ==========
self.capture_flag = False # 捕获线程运行标志 self.capture_flag = False # 捕获线程运行标志
self.display_flag = False # 显示线程运行标志 self.display_flag = False # 显示线程运行标志
self.detection_flag = False # 检测线程运行标志 self.channel_detect_status = False # 检测线程运行标志
# 注意:curve_flag已改为全局单例管理,不再存储在context中 # 注意:curve_flag已改为全局单例管理,不再存储在context中
self.storage_flag = False # 存储线程运行标志 self.storage_flag = False # 存储线程运行标志
......
...@@ -45,6 +45,9 @@ except ImportError: ...@@ -45,6 +45,9 @@ except ImportError:
class ModelLoadingProgressDialog(QDialog): class ModelLoadingProgressDialog(QDialog):
"""模型加载进度条对话框""" """模型加载进度条对话框"""
# 🔥 添加取消信号
cancelRequested = Signal() # 用户点击关闭按钮时发出
def __init__(self, parent=None, total_models: int = 1): def __init__(self, parent=None, total_models: int = 1):
""" """
初始化进度条对话框 初始化进度条对话框
...@@ -56,6 +59,7 @@ class ModelLoadingProgressDialog(QDialog): ...@@ -56,6 +59,7 @@ class ModelLoadingProgressDialog(QDialog):
super().__init__(parent) super().__init__(parent)
self.total_models = total_models self.total_models = total_models
self.current_model = 0 self.current_model = 0
self._user_cancelled = False # 标记用户是否取消
self.setupUI() self.setupUI()
...@@ -68,11 +72,10 @@ class ModelLoadingProgressDialog(QDialog): ...@@ -68,11 +72,10 @@ class ModelLoadingProgressDialog(QDialog):
# 设置左上角图标为逻辑图标 # 设置左上角图标为逻辑图标
self.setWindowIcon(newIcon("逻辑")) self.setWindowIcon(newIcon("逻辑"))
# 移除帮助按钮和关闭按钮 # 🔥 只移除帮助按钮,保留关闭按钮(用户可以点击关闭按钮取消加载)
self.setWindowFlags( self.setWindowFlags(
self.windowFlags() & self.windowFlags() &
~Qt.WindowContextHelpButtonHint & # 移除帮助按钮 ~Qt.WindowContextHelpButtonHint # 移除帮助按钮
~Qt.WindowCloseButtonHint # 移除关闭按钮
) )
# 居中显示 # 居中显示
...@@ -213,3 +216,17 @@ class ModelLoadingProgressDialog(QDialog): ...@@ -213,3 +216,17 @@ class ModelLoadingProgressDialog(QDialog):
self.title_label.setText("模型加载失败") self.title_label.setText("模型加载失败")
self.title_label.setStyleSheet("font-weight: bold; padding: 5px 0;") self.title_label.setStyleSheet("font-weight: bold; padding: 5px 0;")
self.step_label.setText("请检查模型文件和配置") self.step_label.setText("请检查模型文件和配置")
def closeEvent(self, event):
"""
处理关闭事件(用户点击右上角关闭按钮)
发出取消信号,通知外部停止加载线程
"""
if not self._user_cancelled:
self._user_cancelled = True
print(f"⚠️ [模型加载] 用户取消加载,发出取消信号")
self.cancelRequested.emit()
# 接受关闭事件
event.accept()
...@@ -245,7 +245,7 @@ class ChannelThreadManager: ...@@ -245,7 +245,7 @@ class ChannelThreadManager:
if not context: if not context:
return False return False
if context.detection_flag: if context.channel_detect_status:
return True return True
try: try:
...@@ -271,17 +271,22 @@ class ChannelThreadManager: ...@@ -271,17 +271,22 @@ class ChannelThreadManager:
global_thread.register_channel(channel_id, context, callback) global_thread.register_channel(channel_id, context, callback)
# 更新通道状态 # 更新通道状态
context.detection_flag = True context.channel_detect_status = True
context.detection_enabled = True context.detection_enabled = True
# 🔥 更新主窗口中的通道检测变量(channel1detect, channel2detect等) # 🔥 更新主窗口中的通道检测变量(channel1detect, channel2detect等)
if self.main_window: if self.main_window:
detect_var_name = f'{channel_id}detect' detect_var_name = f'{channel_id}detect'
setattr(self.main_window, detect_var_name, True) setattr(self.main_window, detect_var_name, True)
print(f"🔥 [线程管理器] 已设置 {detect_var_name} = True")
# 🔥 更新任务面板中通道列的颜色(检测状态变化时 # 🔥 更新任务面板中状态列的颜色(只更新为绿色,不置黑
if hasattr(self.main_window, '_updateChannelColumnColor'): if hasattr(self.main_window, '_updateChannelColumnColor'):
print(f"🔥 [线程管理器] 准备调用 _updateChannelColumnColor")
self.main_window._updateChannelColumnColor() self.main_window._updateChannelColumnColor()
print(f"🔥 [线程管理器] _updateChannelColumnColor 调用完成")
else:
print(f"❌ [线程管理器] main_window 没有 _updateChannelColumnColor 方法!")
# 保持兼容性:设置一个占位符线程对象 # 保持兼容性:设置一个占位符线程对象
context.detection_thread = threading.Thread( context.detection_thread = threading.Thread(
...@@ -510,7 +515,7 @@ class ChannelThreadManager: ...@@ -510,7 +515,7 @@ class ChannelThreadManager:
global_thread.unregister_channel(channel_id) global_thread.unregister_channel(channel_id)
# 更新通道状态 # 更新通道状态
context.detection_flag = False context.channel_detect_status = False
context.detection_enabled = False context.detection_enabled = False
# 🔥 更新主窗口中的通道检测变量(channel1detect, channel2detect等) # 🔥 更新主窗口中的通道检测变量(channel1detect, channel2detect等)
...@@ -518,7 +523,7 @@ class ChannelThreadManager: ...@@ -518,7 +523,7 @@ class ChannelThreadManager:
detect_var_name = f'{channel_id}detect' detect_var_name = f'{channel_id}detect'
setattr(self.main_window, detect_var_name, False) setattr(self.main_window, detect_var_name, False)
# 🔥 更新任务面板中通道列的颜色(检测状态变化时 # 🔥 更新任务面板中状态列的颜色(只更新为绿色,不置黑
if hasattr(self.main_window, '_updateChannelColumnColor'): if hasattr(self.main_window, '_updateChannelColumnColor'):
self.main_window._updateChannelColumnColor() self.main_window._updateChannelColumnColor()
...@@ -996,7 +1001,7 @@ class ChannelThreadManager: ...@@ -996,7 +1001,7 @@ class ChannelThreadManager:
'count': context.display_count 'count': context.display_count
}, },
'detection': { 'detection': {
'running': context.detection_flag, 'running': context.channel_detect_status,
'count': context.detection_count, 'count': context.detection_count,
'enabled': context.detection_enabled 'enabled': context.detection_enabled
}, },
......
...@@ -318,7 +318,6 @@ class CurveThread: ...@@ -318,7 +318,6 @@ class CurveThread:
data_points = [] data_points = []
try: try:
print(f"🔄 [全局曲线线程] 开始加载CSV文件: {csv_filepath}")
with open(csv_filepath, 'r', encoding='utf-8') as f: with open(csv_filepath, 'r', encoding='utf-8') as f:
line_count = 0 line_count = 0
for line in f: for line in f:
...@@ -349,11 +348,9 @@ class CurveThread: ...@@ -349,11 +348,9 @@ class CurveThread:
except ValueError as ve: except ValueError as ve:
pass pass
print(f"✅ [全局曲线线程] CSV文件加载完成: {csv_filepath}, 共 {len(data_points)} 个数据点")
return data_points return data_points
except Exception as e: except Exception as e:
print(f"⚠️ [全局曲线线程] 加载CSV到内存失败 {csv_filepath}: {e}")
import traceback import traceback
traceback.print_exc() traceback.print_exc()
return [] return []
...@@ -395,7 +392,8 @@ class CurveThread: ...@@ -395,7 +392,8 @@ class CurveThread:
return new_lines return new_lines
except Exception as e: except Exception as e:
print(f"⚠️ [全局曲线线程] 增量读取CSV失败 {csv_filepath}: {e}") import traceback
traceback.print_exc()
return [] return []
@staticmethod @staticmethod
...@@ -418,7 +416,8 @@ class CurveThread: ...@@ -418,7 +416,8 @@ class CurveThread:
files.append(os.path.join(directory, name)) files.append(os.path.join(directory, name))
return files return files
except Exception as e: except Exception as e:
print(f"⚠️ [全局曲线线程] 无法列出CSV文件: {e}") import traceback
traceback.print_exc()
return [] return []
@staticmethod @staticmethod
...@@ -491,7 +490,8 @@ class CurveThread: ...@@ -491,7 +490,8 @@ class CurveThread:
curve_frame_rate = max(1, min(25, curve_frame_rate)) curve_frame_rate = max(1, min(25, curve_frame_rate))
return curve_frame_rate return curve_frame_rate
except Exception as e: except Exception as e:
print(f"⚠️ [全局曲线线程] 读取曲线帧率配置失败: {e}") import traceback
traceback.print_exc()
# 默认返回2 Hz # 默认返回2 Hz
return 2 return 2
......
...@@ -70,7 +70,7 @@ class DetectionThread: ...@@ -70,7 +70,7 @@ class DetectionThread:
channel_id = context.channel_id channel_id = context.channel_id
frame_interval = 1.0 / frame_rate if frame_rate > 0 else 0.05 frame_interval = 1.0 / frame_rate if frame_rate > 0 else 0.05
while context.detection_flag: while context.channel_detect_status:
try: try:
frame_start_time = time.time() frame_start_time = time.time()
...@@ -150,7 +150,7 @@ class DetectionThread: ...@@ -150,7 +150,7 @@ class DetectionThread:
print(f" - 批大小: {batch_size}") print(f" - 批大小: {batch_size}")
print(f" - 目标FPS: {frame_rate}") print(f" - 目标FPS: {frame_rate}")
while context.detection_flag: while context.channel_detect_status:
try: try:
frame_start_time = time.time() frame_start_time = time.time()
......
...@@ -34,11 +34,18 @@ class StorageThread: ...@@ -34,11 +34,18 @@ class StorageThread:
Returns: Returns:
str: 项目根目录的绝对路径 str: 项目根目录的绝对路径
""" """
# 当前文件是 handlers/videopage/thread_manager/threads/storage_thread.py import sys
# 需要向上5级到达项目根目录
current_file = os.path.abspath(__file__) # 🔥 打包后:使用 sys._MEIPASS 指向 _internal 目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(current_file))))) if getattr(sys, 'frozen', False):
return project_root # 打包环境:返回 _internal 目录
return sys._MEIPASS
else:
# 开发环境:当前文件是 handlers/videopage/thread_manager/threads/storage_thread.py
# 需要向上5级到达项目根目录
current_file = os.path.abspath(__file__)
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(current_file)))))
return project_root
@staticmethod @staticmethod
def run(context, frame_rate: float, main_window=None): def run(context, frame_rate: float, main_window=None):
......
# DebugLog 调试日志模块使用说明
## 功能概述
`debuglog.py` 提供了一个基于 `logging` 模块的调试日志系统,用于替代 `print()` 进行调试输出。
## 核心特性
-**单例模式**: 全局统一的日志管理
-**双重输出**: 同时输出到控制台和文件
-**按日期分文件**: 每天自动创建新的日志文件
-**多级别日志**: DEBUG, INFO, WARNING, ERROR, CRITICAL
-**详细信息**: 文件日志包含时间、模块、文件名、行号等
-**自动清理**: 支持清理旧日志文件
-**UTF-8编码**: 支持中文日志
## 日志文件位置
```
D:\restructure\liquid_level_line_detection_system\database\log\debuglog\
```
## 快速开始
### 1. 基本使用
```python
from handlers.debuglog import get_logger
# 创建logger(建议使用 __name__ 作为名称)
logger = get_logger(__name__)
# 记录不同级别的日志
logger.debug("调试信息")
logger.info("普通信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")
```
### 2. 在类中使用
```python
from handlers.debuglog import get_logger
class MyClass:
def __init__(self):
self.logger = get_logger(self.__class__.__name__)
def do_something(self):
self.logger.info("开始执行操作")
try:
# 你的代码
result = self.process()
self.logger.info(f"操作成功,结果: {result}")
except Exception as e:
self.logger.error(f"操作失败: {e}", exc_info=True)
```
### 3. 在函数中使用
```python
from handlers.debuglog import get_logger
logger = get_logger(__name__)
def my_function(param):
logger.debug(f"函数调用,参数: {param}")
# 你的代码
result = param * 2
logger.info(f"函数执行完成,返回: {result}")
return result
```
## 高级用法
### 1. 只输出到文件(不显示在控制台)
```python
from handlers.debuglog import get_logger
logger = get_logger(
"my_module",
console_output=False, # 不输出到控制台
file_output=True # 只输出到文件
)
logger.info("这条消息只会写入日志文件")
```
### 2. 设置日志级别
```python
from handlers.debuglog import get_logger, INFO
# 只记录 INFO 及以上级别的日志
logger = get_logger("my_module", level=INFO)
logger.debug("这条不会显示") # DEBUG < INFO
logger.info("这条会显示") # INFO >= INFO
logger.warning("这条会显示") # WARNING > INFO
```
日志级别(从低到高):
- `DEBUG` (10) - 详细的调试信息
- `INFO` (20) - 一般信息
- `WARNING` (30) - 警告信息
- `ERROR` (40) - 错误信息
- `CRITICAL` (50) - 严重错误
### 3. 记录异常信息
```python
from handlers.debuglog import get_logger
logger = get_logger(__name__)
try:
result = 1 / 0
except Exception as e:
# exc_info=True 会记录完整的堆栈跟踪
logger.error(f"发生异常: {e}", exc_info=True)
```
### 4. 清理旧日志
```python
from handlers.debuglog import clear_old_logs
# 清理7天前的日志文件
clear_old_logs(days=7)
# 清理30天前的日志文件
clear_old_logs(days=30)
```
## 日志格式
### 控制台输出(简洁格式)
```
2025-11-29 15:30:45 - INFO - 这是一条信息
2025-11-29 15:30:46 - WARNING - 这是一条警告
2025-11-29 15:30:47 - ERROR - 这是一条错误
```
### 文件输出(详细格式)
```
2025-11-29 15:30:45 - my_module - INFO - [main.py:123] - 这是一条信息
2025-11-29 15:30:46 - my_module - WARNING - [main.py:124] - 这是一条警告
2025-11-29 15:30:47 - my_module - ERROR - [main.py:125] - 这是一条错误
```
## 实际应用示例
### 示例1: 在 auto_dot.py 中使用
```python
from handlers.debuglog import get_logger
class AutoAnnotationDetector:
def __init__(self, model_path: str = None, device: str = 'cuda'):
self.logger = get_logger(self.__class__.__name__)
self.model = None
self.model_path = model_path
self.device = self._validate_device(device)
if model_path:
self.load_model(model_path)
def load_model(self, model_path: str) -> bool:
try:
self.logger.info(f"开始加载模型: {model_path}")
if not os.path.exists(model_path):
self.logger.error(f"模型文件不存在: {model_path}")
return False
# 加载模型...
self.logger.info(f"模型加载成功: {os.path.basename(model_path)}")
return True
except Exception as e:
self.logger.error(f"模型加载失败: {e}", exc_info=True)
return False
def detect(self, image, conf_threshold=0.5, min_area=100):
self.logger.debug(f"开始检测 - 置信度阈值: {conf_threshold}, 最小面积: {min_area}")
try:
# 执行检测...
self.logger.info(f"检测完成,共 {len(valid_masks)} 个有效mask")
return result
except Exception as e:
self.logger.error(f"检测失败: {e}", exc_info=True)
return {'success': False, 'error': str(e)}
```
### 示例2: 替代现有的 print 语句
**之前(使用 print):**
```python
print(f"🔄 正在加载模型: {model_path}")
print(f"✅ 模型加载成功")
print(f"❌ 模型加载失败: {e}")
```
**之后(使用 logger):**
```python
logger.info(f"正在加载模型: {model_path}")
logger.info(f"模型加载成功")
logger.error(f"模型加载失败: {e}", exc_info=True)
```
### 示例3: 在测试函数中使用
```python
from handlers.debuglog import get_logger
def test_auto_annotation():
logger = get_logger("test_auto_annotation")
logger.info("="*80)
logger.info("自动标注功能测试")
logger.info("="*80)
# 配置参数
model_path = r"D:\...\best.dat"
logger.debug(f"模型路径: {model_path}")
# 检查文件
if not os.path.exists(model_path):
logger.error(f"模型文件不存在: {model_path}")
return
# 创建检测器
logger.info("初始化自动标注检测器...")
detector = AutoAnnotationDetector(model_path=model_path, device='cuda')
# 执行检测
logger.info("开始执行检测...")
detection_result = detector.detect(image, conf_threshold=0.5, min_area=100)
if detection_result.get('success'):
logger.info("检测成功")
else:
logger.error(f"检测失败: {detection_result.get('error')}")
```
## 最佳实践
1. **使用 `__name__` 作为 logger 名称**
```python
logger = get_logger(__name__)
```
2. **在类中创建实例变量**
```python
def __init__(self):
self.logger = get_logger(self.__class__.__name__)
```
3. **记录异常时使用 `exc_info=True`**
```python
except Exception as e:
logger.error(f"错误: {e}", exc_info=True)
```
4. **根据重要性选择合适的日志级别**
- `DEBUG`: 详细的调试信息(开发时使用)
- `INFO`: 正常的操作信息
- `WARNING`: 警告但不影响运行
- `ERROR`: 错误但程序可以继续
- `CRITICAL`: 严重错误,程序可能无法继续
5. **定期清理旧日志**
```python
# 在程序启动时清理旧日志
from handlers.debuglog import clear_old_logs
clear_old_logs(days=7)
```
## 测试
运行测试代码:
```bash
python handlers/debuglog.py
```
这会执行5个测试用例,展示各种使用方式。
## 注意事项
1. 日志文件按日期命名,格式为:`{logger_name}_{YYYYMMDD}.log`
2. 日志文件使用 UTF-8 编码,支持中文
3. 同一个 logger 名称会复用已创建的 logger 实例
4. 文件日志会追加写入,不会覆盖
5. 建议在生产环境中将日志级别设置为 `INFO` 或更高
...@@ -9,4 +9,6 @@ R - Renamed(已重命名):文件已被重命名 ...@@ -9,4 +9,6 @@ R - Renamed(已重命名):文件已被重命名
C - Copied(已复制):文件已被复制 C - Copied(已复制):文件已被复制
U - Unmerged(未合并):存在合并冲突 U - Unmerged(未合并):存在合并冲突
channeldetect=True channeldetect=True
curve_load_mode curve_load_mode
\ No newline at end of file 检测线程运行中 (detection_running=True) → 索引0(实时检测模式)
检测线程停止 (detection_running=False) → 索引1(历史回放模式)
\ No newline at end of file
1曲线模式索引0布局,只显示根据curvemission筛选使用的通道面板失效了
1曲线模式索引0布局,只显示根据curvemission筛选使用的通道面板失效了
2判断detection_falg前,若curvemission任务面板状态列的状态为未启动( mission_status变量),则直接使用索引1布局
选择任务
检查任务状态
任务状态 = "未启动"?
├─ 是 → 返回 False → 索引1(历史回放)
└─ 否 → 继续检查
检查通道 channel_detect_status
任意通道 channel_detect_status = True?
├─ 是 → 返回 True → 索引0(实时检测)
└─ 否 → 返回 False → 索引1(历史回放)
保存标注结果用于持久显示
self._last_annotation_pixmap
任务面板任务信息文本状态切换逻辑 class MissionTextStatus,channel_detect_status
1. 任务面板信息文本显示初始默认都为灰色
2. 单击选中行时文本该行文本置为黑色
3. 启动检测线程时对应任务的对应通道列置为绿色
4. 新建任务信息文本显示初始默认都为灰色
5. 单击任务行后该任务mission_status为true时才置黑该任务行
6. mission_status判断逻辑,只要任意channelmission值为此任务,则此任务mission_status=true
7. 状态列切换逻辑:
- 分配给任务的所有通道都在检测中 → 绿色"检测中"
- 所有通道都停止检测,但任务仍被分配 → 黑色"已启动"
- 部分通道在检测(不是全部) → 黑色"已启动"
- 任务未被分配 → 灰色"未启动"
判断规则:只有当分配给该任务的所有通道都在检测时,状态列才显示绿色"检测中"
class ModelLoadingProgressDialog(QDialog):
"""模型加载进度条对话框"""
自动选择标注区域类
1.设置一个或多个最小面积box,box区域包含了某一区域的分割结果
自动标点,根据分割结果选择对应分支逻辑
1: liquid_only
- **容器底部**: liquid掩码的最低点
- **容器顶部**: liquid掩码的最高点
- **适用场景**: 只检测到液体,未检测到空气和泡沫
2: air_only
- **容器底部**: air掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 只检测到空气,未检测到液体和泡沫
3: foam_only
- **容器底部**: foam掩码的最低点
- **容器顶部**: foam掩码的最高点
- **适用场景**: 只检测到泡沫,未检测到液体和空气
4: liquid_air
- **容器底部**: liquid掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 同时检测到液体和空气,未检测到泡沫
5: liquid_foam
- **容器底部**: liquid掩码的最低点
- **容器顶部**: foam掩码的最高点
- **适用场景**: 同时检测到液体和泡沫,未检测到空气
6: liquid_foam_air
- **容器底部**: liquid掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 同时检测到液体、泡沫和空气
7: foam_air
- **容器底部**: foam掩码的最低点
- **容器顶部**: air掩码的最高点
- **适用场景**: 同时检测到泡沫和空气,未检测到液体
通道面板的查看曲线按钮禁用逻辑,任务面板的查看曲线按钮一直启用
1channelmission为未分配任务时,包括曲线按钮在内所有通道面板按钮禁用。
2切换到曲线模式布局的索引0实时检测模式时,只禁用通道面板的查看曲线按钮
PAGE_VIDEO 实时检测界面名称管理
1.PAGE_VIDEO 实时检测管理页面页面名称,self._video_layout_mode = 0 任务表格 + 2x2通道面板(PAGE_VIDEO 的索引0)称为默认布局,self._video_layout_mode = 1垂直通道面板 + 曲线面板(PAGE_VIDEO 的索引1)为曲线模式布局
2.曲线模式布局子布局(self._video_layout_mode = 1的索引0)称为同步布局,曲线模式布局子布局(self._video_layout_mode = 1的索引1)为历史回放布局
\ No newline at end of file
...@@ -482,11 +482,12 @@ class ChannelPanel(QtWidgets.QWidget): ...@@ -482,11 +482,12 @@ class ChannelPanel(QtWidgets.QWidget):
self._is_disabled = disabled self._is_disabled = disabled
if disabled: if disabled:
# 禁用所有按钮 # 禁用所有按钮(包括查看曲线按钮)
if hasattr(self, 'btnToggleConnect'): if hasattr(self, 'btnToggleConnect'):
self.btnToggleConnect.setEnabled(False) self.btnToggleConnect.setEnabled(False)
if hasattr(self, 'btnCurve'): if hasattr(self, 'btnCurve'):
self.btnCurve.setEnabled(False) self.btnCurve.setEnabled(False)
self.btnCurve.setToolTip("请先分配任务")
if hasattr(self, 'btnAmplify'): if hasattr(self, 'btnAmplify'):
self.btnAmplify.setEnabled(False) self.btnAmplify.setEnabled(False)
if hasattr(self, 'btnEdit'): if hasattr(self, 'btnEdit'):
...@@ -499,11 +500,34 @@ class ChannelPanel(QtWidgets.QWidget): ...@@ -499,11 +500,34 @@ class ChannelPanel(QtWidgets.QWidget):
} }
""") """)
else: else:
# 启用所有按钮 # 启用按钮
if hasattr(self, 'btnToggleConnect'): if hasattr(self, 'btnToggleConnect'):
self.btnToggleConnect.setEnabled(True) self.btnToggleConnect.setEnabled(True)
# 🔥 查看曲线按钮:有任务时启用,但需要检查是否在曲线模式的实时检测子布局
# 只有在曲线模式(_video_layout_mode==1)且子布局索引0(实时检测)时才禁用
if hasattr(self, 'btnCurve'): if hasattr(self, 'btnCurve'):
self.btnCurve.setEnabled(True) should_enable_curve = True # 默认启用(因为已经有任务了)
try:
# 通过parent链向上查找主窗口
main_window = self.window()
# 检查是否在曲线模式主布局
if hasattr(main_window, '_video_layout_mode') and main_window._video_layout_mode == 1:
# 在曲线模式下,检查子布局索引
if hasattr(main_window, 'curveLayoutStack'):
current_index = main_window.curveLayoutStack.currentIndex()
# 子布局索引0是同步布局,禁用查看曲线按钮
if current_index == 0:
should_enable_curve = False
except:
pass
self.btnCurve.setEnabled(should_enable_curve)
if not should_enable_curve:
self.btnCurve.setToolTip("同步布局下无法查看曲线")
else:
self.btnCurve.setToolTip("查看曲线")
if hasattr(self, 'btnAmplify'): if hasattr(self, 'btnAmplify'):
self.btnAmplify.setEnabled(True) self.btnAmplify.setEnabled(True)
if hasattr(self, 'btnEdit'): if hasattr(self, 'btnEdit'):
......
...@@ -185,7 +185,8 @@ class CurvePanel(QtWidgets.QWidget): ...@@ -185,7 +185,8 @@ class CurvePanel(QtWidgets.QWidget):
toolbar_layout.addSpacing(10) toolbar_layout.addSpacing(10)
# 模式标签(保存为实例变量,以便动态更新) # 🔥 模式标签已隐藏(用户要求删除左侧布局索引文本标签)
# 保留变量以避免其他代码引用错误,但不添加到布局中
self.mode_label = QtWidgets.QLabel("历史回放") self.mode_label = QtWidgets.QLabel("历史回放")
self.mode_label.setStyleSheet("font-weight: bold; padding: 2px 8px;") self.mode_label.setStyleSheet("font-weight: bold; padding: 2px 8px;")
...@@ -197,7 +198,7 @@ class CurvePanel(QtWidgets.QWidget): ...@@ -197,7 +198,7 @@ class CurvePanel(QtWidgets.QWidget):
except ImportError: except ImportError:
pass pass
toolbar_layout.addWidget(self.mode_label) # toolbar_layout.addWidget(self.mode_label) # 🔥 已注释,不显示模式标签
# 任务文件夹选择(下拉选项框)- 响应式布局 # 任务文件夹选择(下拉选项框)- 响应式布局
self.curvemission = QtWidgets.QComboBox() self.curvemission = QtWidgets.QComboBox()
......
...@@ -195,7 +195,7 @@ class HistoryVideoPanel(QtWidgets.QWidget): ...@@ -195,7 +195,7 @@ class HistoryVideoPanel(QtWidgets.QWidget):
nvr_layout.addWidget(nvr_label) nvr_layout.addWidget(nvr_label)
self.nvrAddressEdit = QtWidgets.QLineEdit() self.nvrAddressEdit = QtWidgets.QLineEdit()
self.nvrAddressEdit.setPlaceholderText("请输入NVR地址...") self.nvrAddressEdit.setPlaceholderText("NVR历史回放功能开发中,敬请期待。")
self.nvrAddressEdit.setFont(FontManager.getMediumFont()) self.nvrAddressEdit.setFont(FontManager.getMediumFont())
self.nvrAddressEdit.setStyleSheet(""" self.nvrAddressEdit.setStyleSheet("""
QLineEdit { QLineEdit {
......
...@@ -648,7 +648,24 @@ class MissionPanel(QtWidgets.QWidget): ...@@ -648,7 +648,24 @@ class MissionPanel(QtWidgets.QWidget):
# 更新分页显示(如果需要) # 更新分页显示(如果需要)
if update_display: if update_display:
self._updatePagination() # 🔥 检查新行是否在当前页,如果是则直接添加到表格,否则更新分页
display_data = self._filtered_rows_data if self._search_text else self._all_rows_data
total_rows = len(display_data)
start_index = (self._current_page - 1) * self._page_size
end_index = start_index + self._page_size
# 新行的索引
new_row_index = len(self._all_rows_data) - 1
# 如果新行在当前页范围内,直接添加到表格
if start_index <= new_row_index < end_index and self.table.rowCount() < self._page_size:
self._addRowToTable(row_data, user_data, button_callback)
# 只更新页码标签,不刷新整个表格
total_pages = (total_rows + self._page_size - 1) // self._page_size if total_rows > 0 else 1
self.page_label.setText(f"{self._current_page} / {total_pages}")
else:
# 新行不在当前页,需要完整刷新分页
self._updatePagination()
# 返回在全部数据中的索引 # 返回在全部数据中的索引
return len(self._all_rows_data) - 1 return len(self._all_rows_data) - 1
...@@ -1424,7 +1441,7 @@ class MissionPanel(QtWidgets.QWidget): ...@@ -1424,7 +1441,7 @@ class MissionPanel(QtWidgets.QWidget):
'task_id': task_id, 'task_id': task_id,
'task_name': task_name, 'task_name': task_name,
'selected_channels': selected_channels, 'selected_channels': selected_channels,
'status': '待配置' 'status': '未启动'
} }
# 发送任务确认信号 # 发送任务确认信号
...@@ -1581,7 +1598,7 @@ class MissionPanel(QtWidgets.QWidget): ...@@ -1581,7 +1598,7 @@ class MissionPanel(QtWidgets.QWidget):
row_data = [ row_data = [
task_info.get('task_id', ''), task_info.get('task_id', ''),
task_info.get('task_name', ''), task_info.get('task_name', ''),
task_info.get('status', '待配置'), task_info.get('status', '未启动'),
channel_data[0], # 通道1列 channel_data[0], # 通道1列
channel_data[1], # 通道2列 channel_data[1], # 通道2列
channel_data[2], # 通道3列 channel_data[2], # 通道3列
......
...@@ -159,16 +159,7 @@ class ModelSettingDialog(QtWidgets.QDialog): ...@@ -159,16 +159,7 @@ class ModelSettingDialog(QtWidgets.QDialog):
""") """)
availableLayout.addWidget(self.modelListWidget) availableLayout.addWidget(self.modelListWidget)
# 刷新按钮布局 - 居中显示 # 🔥 刷新按钮已删除(用户要求)
refresh_button_layout = QtWidgets.QHBoxLayout()
refresh_button_layout.addStretch()
# 刷新按钮 - 使用全局文本按钮样式管理器,仅文本无图标
self.btnRefreshModels = createTextButton(self.tr("刷新列表"), parent=self)
refresh_button_layout.addWidget(self.btnRefreshModels)
refresh_button_layout.addStretch()
availableLayout.addLayout(refresh_button_layout)
availableGroup.setLayout(availableLayout) availableGroup.setLayout(availableLayout)
...@@ -184,7 +175,7 @@ class ModelSettingDialog(QtWidgets.QDialog): ...@@ -184,7 +175,7 @@ class ModelSettingDialog(QtWidgets.QDialog):
"""连接信号槽""" """连接信号槽"""
# 可用模型列表 # 可用模型列表
self.modelListWidget.itemDoubleClicked.connect(self._onModelListDoubleClicked) self.modelListWidget.itemDoubleClicked.connect(self._onModelListDoubleClicked)
self.btnRefreshModels.clicked.connect(self._refreshModelList) # self.btnRefreshModels.clicked.connect(self._refreshModelList) # 🔥 已删除刷新按钮
def _refreshModelList(self): def _refreshModelList(self):
"""刷新可用模型列表 - 发射信号请求handler处理""" """刷新可用模型列表 - 发射信号请求handler处理"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment