vertical: step - 1

This commit is contained in:
Havoc 2025-05-31 12:33:28 +08:00
parent 824b9d7786
commit 365d59fe75
4 changed files with 711 additions and 242 deletions

View File

@ -80,3 +80,338 @@
2025-05-31 09:49:18 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_094918_337104.jpg
2025-05-31 09:49:18 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_094918_337104.jpg
2025-05-31 09:49:18 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_094918_337104', 'center_point': (944, 1080), 'deviation': -15.5, 'left_track_mid_x': 624.0, 'right_track_mid_x': 1219.0, 'track_width': 595.0, 'center_slope': 0.02132675438596272, 'stone_path_mode': False}
2025-05-31 10:29:14 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:29:16 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:29:18 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:29:20 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 49 条直线
2025-05-31 10:29:22 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 19 条垂直线
2025-05-31 10:29:24 | DEBUG | utils.log_helper - 🐞 步骤4.5: 合并后找到 10 条垂直线
2025-05-31 10:29:26 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 5, 右侧候选线数量: 5
2025-05-31 10:29:26 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.89
2025-05-31 10:29:28 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_102928_778495.jpg
2025-05-31 10:29:28 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_102928_778495.jpg
2025-05-31 10:29:28 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_102928_778495', 'center_point': (952, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 528.0, 'right_track_mid_x': 1388.5, 'track_width': 860.5, 'center_slope': -0.0016446763600527115}
2025-05-31 10:29:37 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:29:39 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:29:41 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:29:44 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 10:29:46 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 10:29:48 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 10:29:48 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.02
2025-05-31 10:29:50 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_102950_067699.jpg
2025-05-31 10:29:50 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_102950_067699.jpg
2025-05-31 10:29:50 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_102950_067699', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669, 'stone_path_mode': False}
2025-05-31 10:32:18 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:32:20 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:32:22 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:32:24 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 10:32:26 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 10:32:28 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 10:32:28 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.02
2025-05-31 10:32:30 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_103230_706359.jpg
2025-05-31 10:32:30 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_103230_706359.jpg
2025-05-31 10:32:30 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_103230_706359', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 10:54:05 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:54:06 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:54:06 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:54:07 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 10:54:08 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 10:54:09 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 10:54:09 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 10:54:10 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_105410_128420.jpg
2025-05-31 10:54:10 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_105410_128420.jpg
2025-05-31 10:54:10 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_105410_128420', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 10:56:14 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:56:15 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:56:16 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:56:16 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 10:56:17 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 10:56:18 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 10:56:18 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 10:56:19 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_105619_406431.jpg
2025-05-31 10:56:19 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_105619_406431.jpg
2025-05-31 10:56:19 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_105619_406431', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 10:59:46 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 10:59:47 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 10:59:48 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 10:59:49 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 10:59:50 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 10:59:51 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 10:59:51 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 10:59:51 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_105951_966275.jpg
2025-05-31 10:59:51 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_105951_966275.jpg
2025-05-31 10:59:51 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_105951_966275', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:09:05 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:09:06 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:09:07 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:09:08 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:09:09 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 11:09:10 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 11:09:10 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:09:10 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_110910_854647.jpg
2025-05-31 11:09:10 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_110910_854647.jpg
2025-05-31 11:09:10 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_110910_854647', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:09:24 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:09:26 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:09:28 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:09:30 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:09:32 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 11:09:34 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 11:09:34 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:09:36 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_110936_844379.jpg
2025-05-31 11:09:36 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_110936_844379.jpg
2025-05-31 11:09:36 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_110936_844379', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:14:39 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:14:41 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:14:43 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:14:45 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:14:47 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 11:14:49 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 11:14:49 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:14:51 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_111451_964924.jpg
2025-05-31 11:14:51 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_111451_964924.jpg
2025-05-31 11:14:51 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_111451_964924', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:14:56 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:14:58 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:15:00 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:15:02 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:15:04 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 11:15:06 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 11:15:06 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:15:08 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_111508_434244.jpg
2025-05-31 11:15:08 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_111508_434244.jpg
2025-05-31 11:15:08 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_111508_434244', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:15:23 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:15:24 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:15:25 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:15:26 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:15:27 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 24 条垂直线
2025-05-31 11:15:28 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 12, 右侧候选线数量: 12
2025-05-31 11:15:28 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:15:29 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_111529_709703.jpg
2025-05-31 11:15:29 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_111529_709703.jpg
2025-05-31 11:15:29 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_111529_709703', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:15:35 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:15:36 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:15:37 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:15:38 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:15:39 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 27 条垂直线
2025-05-31 11:15:40 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 15, 右侧候选线数量: 12
2025-05-31 11:15:40 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:15:41 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_111541_404961.jpg
2025-05-31 11:15:41 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_111541_404961.jpg
2025-05-31 11:15:41 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_111541_404961', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:18:59 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:19:00 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:19:01 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:19:03 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:19:04 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 27 条垂直线
2025-05-31 11:19:05 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 15, 右侧候选线数量: 12
2025-05-31 11:19:05 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:19:06 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_111906_059419.jpg
2025-05-31 11:19:06 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_111906_059419.jpg
2025-05-31 11:19:06 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_111906_059419', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:20:17 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:20:19 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:20:20 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:20:21 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:20:22 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 27 条垂直线
2025-05-31 11:20:23 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 15, 右侧候选线数量: 12
2025-05-31 11:20:24 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:20:25 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_112025_176560.jpg
2025-05-31 11:20:25 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_112025_176560.jpg
2025-05-31 11:20:25 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_112025_176560', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:20:36 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:20:37 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:20:38 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:20:39 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 11:20:40 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 27 条垂直线
2025-05-31 11:20:41 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 15, 右侧候选线数量: 12
2025-05-31 11:20:42 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 11:20:43 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_112043_362415.jpg
2025-05-31 11:20:43 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_112043_362415.jpg
2025-05-31 11:20:43 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_112043_362415', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}
2025-05-31 11:47:40 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:47:42 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:47:43 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:47:44 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:47:44 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:47:44 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:47:45 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:47:46 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:47:47 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:47:48 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_114748_278587.jpg
2025-05-31 11:47:48 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_114748_278587.jpg
2025-05-31 11:47:48 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_114748_278587', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:47:50 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:47:51 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:47:52 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:47:53 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:47:53 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:47:53 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:47:54 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:47:55 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:47:56 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:47:57 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_114757_837088.jpg
2025-05-31 11:47:57 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_114757_837088.jpg
2025-05-31 11:47:57 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_114757_837088', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:49:15 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:49:16 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:49:17 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:49:18 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:49:18 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:49:18 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:49:19 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:49:20 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:49:21 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:49:22 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_114922_309402.jpg
2025-05-31 11:49:22 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_114922_309402.jpg
2025-05-31 11:49:22 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_114922_309402', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:54:18 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:54:19 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:54:20 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:54:21 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:54:21 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:54:21 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:54:22 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:54:23 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:54:24 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:54:25 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115425_535559.jpg
2025-05-31 11:54:25 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115425_535559.jpg
2025-05-31 11:54:25 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115425_535559', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:54:31 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:54:32 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:54:33 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:54:34 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:54:34 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:54:34 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:54:35 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:54:36 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:54:37 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:54:38 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115438_968316.jpg
2025-05-31 11:54:38 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115438_968316.jpg
2025-05-31 11:54:38 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115438_968316', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:54:42 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:54:43 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:54:44 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:54:45 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:54:45 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:54:45 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:54:46 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:54:47 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:54:48 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:54:49 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115449_602349.jpg
2025-05-31 11:54:49 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115449_602349.jpg
2025-05-31 11:54:49 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115449_602349', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 11:55:50 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:55:51 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:55:52 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:55:53 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:55:53 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:55:53 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:55:54 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:55:55 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:55:56 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:55:57 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115557_917521.jpg
2025-05-31 11:55:57 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115557_917521.jpg
2025-05-31 11:55:57 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115557_917521', 'center_point': (945, 1080), 'deviation': 0.10552257197241488, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02638064299316605}
2025-05-31 11:56:12 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:56:13 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:56:14 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:57:45 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:57:46 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:57:47 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:57:48 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:57:48 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:57:48 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:57:49 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 15 条垂直线
2025-05-31 11:57:50 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 10, 右侧候选线数量: 5
2025-05-31 11:57:51 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:57:52 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115752_281641.jpg
2025-05-31 11:57:52 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115752_281641.jpg
2025-05-31 11:57:52 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115752_281641', 'center_point': (945, 1080), 'deviation': 0.10552257197241488, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02638064299316605}
2025-05-31 11:58:36 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 11:58:37 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 11:58:38 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 11:58:39 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 11:58:39 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 11:58:39 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 11:58:40 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 11:58:41 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 4, 右侧候选线数量: 3
2025-05-31 11:58:42 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 11:58:43 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_115843_399705.jpg
2025-05-31 11:58:43 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_115843_399705.jpg
2025-05-31 11:58:43 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_115843_399705', 'center_point': (945, 1080), 'deviation': 0.10552257197241488, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02638064299316605}
2025-05-31 12:14:32 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:14:33 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:14:35 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:14:36 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 12:14:36 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 12:14:36 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 12:14:37 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:14:38 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 4, 右侧候选线数量: 3
2025-05-31 12:14:39 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 12:14:40 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_121440_131832.jpg
2025-05-31 12:14:40 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_121440_131832.jpg
2025-05-31 12:14:40 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_121440_131832', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 12:18:29 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:18:30 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:18:31 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:18:32 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 12:18:32 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 12:18:32 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 12:18:33 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:18:34 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 4, 右侧候选线数量: 3
2025-05-31 12:18:35 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 12:18:37 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_121837_013535.jpg
2025-05-31 12:18:37 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_121837_013535.jpg
2025-05-31 12:18:37 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_121837_013535', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 12:18:46 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:18:47 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:18:48 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:18:49 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 12:18:49 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 12:18:49 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 12:18:50 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:18:51 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 4, 右侧候选线数量: 3
2025-05-31 12:18:52 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 12:18:53 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_121853_427060.jpg
2025-05-31 12:18:53 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_121853_427060.jpg
2025-05-31 12:18:53 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_121853_427060', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 12:19:01 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:19:02 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:19:03 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:19:04 | DEBUG | utils.log_helper - 🐞 步骤2.5: 初始检测到 54 条直线,尝试合并
2025-05-31 12:19:04 | DEBUG | utils.log_helper - 🐞 合并后剩余 31 条直线
2025-05-31 12:19:04 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 31 条直线
2025-05-31 12:19:05 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:19:06 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 4, 右侧候选线数量: 3
2025-05-31 12:19:07 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 0.95
2025-05-31 12:19:08 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_121908_570358.jpg
2025-05-31 12:19:08 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_121908_570358.jpg
2025-05-31 12:19:08 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_121908_570358', 'center_point': (945, 1080), 'deviation': 3.410605131648481e-13, 'left_track_mid_x': 608.5, 'right_track_mid_x': 1219.0, 'track_width': 610.5, 'center_slope': 0.02351973684210257}
2025-05-31 12:25:05 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:25:07 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:25:08 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:25:09 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 12:25:10 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:31:54 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:31:55 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:31:56 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:31:57 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 12:31:58 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:32:08 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:32:09 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:32:10 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:32:11 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 12:32:12 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 7 条垂直线
2025-05-31 12:33:06 | DEBUG | utils.log_helper - 🐞 步骤1: 创建黄色掩码
2025-05-31 12:33:07 | DEBUG | utils.log_helper - 🐞 步骤1.5: 底部区域掩码
2025-05-31 12:33:09 | DEBUG | utils.log_helper - 🐞 步骤2: 边缘检测
2025-05-31 12:33:10 | DEBUG | utils.log_helper - 🐞 步骤3: 检测到 54 条直线
2025-05-31 12:33:11 | DEBUG | utils.log_helper - 🐞 步骤4: 找到 11 条垂直线
2025-05-31 12:33:12 | DEBUG | utils.log_helper - 🐞 左侧候选线数量: 6, 右侧候选线数量: 5
2025-05-31 12:33:13 | DEBUG | utils.log_helper - 🐞 选择最佳线对,评分: 1.01
2025-05-31 12:33:14 | INFO | utils.log_helper - 保存双轨迹线检测结果图像到: logs/image/dual_track_20250531_123314_086361.jpg
2025-05-31 12:33:14 | INFO | utils.log_helper - 保存原始图像到: logs/image/dual_track_orig_20250531_123314_086361.jpg
2025-05-31 12:33:14 | INFO | utils.log_helper - 双轨迹线检测结果: {'timestamp': '20250531_123314_086361', 'center_point': (944, 1080), 'deviation': -1.1368683772161603e-13, 'left_track_mid_x': 565.0, 'right_track_mid_x': 1335.5, 'track_width': 770.5, 'center_slope': 0.01738261738261669}

View File

@ -22,9 +22,8 @@ print("正在使用普通模式检测...")
center_info, left_track_info, right_track_info = detect_dual_track_lines(
image_path,
observe=True, # 设置为True以查看处理过程和结果
delay=2000, # 增加显示时间以便观察
delay=1000, # 增加显示时间以便观察
save_log=True,
stone_path_mode=False
)
if center_info:

166
utils/base_line_handler.py Normal file
View File

@ -0,0 +1,166 @@
import numpy as np
import cv2
def _are_lines_mergeable(line1_pts, line2_pts,
max_angle_diff_deg,
max_ep_gap_abs, max_ep_gap_factor,
max_p_dist_abs, max_p_dist_factor):
"""
判断两条线段是否可以合并
lineX_pts: [x1, y1, x2, y2]
max_angle_diff_deg: 最大角度差 ()
max_ep_gap_abs: 端点间最大绝对间隙
max_ep_gap_factor: 端点间最大相对间隙 (基于较短线段长度的因子)
max_p_dist_abs: 最大绝对垂直距离
max_p_dist_factor: 最大相对垂直距离 (基于较短线段长度的因子)
"""
x1a, y1a, x2a, y2a = line1_pts
x1b, y1b, x2b, y2b = line2_pts
p1a, p2a = np.array([x1a, y1a]), np.array([x2a, y2a])
p1b, p2b = np.array([x1b, y1b]), np.array([x2b, y2b])
len_a = np.linalg.norm(p2a - p1a)
len_b = np.linalg.norm(p2b - p1b)
if len_a < 1e-3 or len_b < 1e-3: return False # 避免零长度线段
shorter_len = min(len_a, len_b)
# 1. 角度相似性
angle_a = np.arctan2(y2a - y1a, x2a - x1a)
angle_b = np.arctan2(y2b - y1b, x2b - x1b)
angle_diff = np.degrees(angle_a - angle_b)
while angle_diff <= -180: angle_diff += 360
while angle_diff > 180: angle_diff -= 360
is_angle_similar = abs(angle_diff) < max_angle_diff_deg or \
abs(abs(angle_diff) - 180) < max_angle_diff_deg
if not is_angle_similar:
return False
# 2. 共线性: 检查一个线段的端点到另一个线段(无限延长)的垂直距离
current_max_allowed_perp_dist = max(max_p_dist_abs, max_p_dist_factor * shorter_len)
def get_perp_dist_point_to_inf_line(p, line_p1, line_p2, line_len):
if line_len < 1e-3: return np.linalg.norm(p - line_p1) # 线是点
return abs((line_p2[1]-line_p1[1])*p[0] - (line_p2[0]-line_p1[0])*p[1] + \
line_p2[0]*line_p1[1] - line_p2[1]*line_p1[0]) / line_len
dist_b1_to_a_inf = get_perp_dist_point_to_inf_line(p1b, p1a, p2a, len_a)
dist_b2_to_a_inf = get_perp_dist_point_to_inf_line(p2b, p1a, p2a, len_a)
dist_a1_to_b_inf = get_perp_dist_point_to_inf_line(p1a, p1b, p2b, len_b)
dist_a2_to_b_inf = get_perp_dist_point_to_inf_line(p2a, p1b, p2b, len_b)
# 如果两条线都很短,那么允许的垂直距离也应该小
# 如果一条线的端点离另一条无限延长的线太远,则不合并
if min(dist_b1_to_a_inf, dist_b2_to_a_inf) > current_max_allowed_perp_dist and \
min(dist_a1_to_b_inf, dist_a2_to_b_inf) > current_max_allowed_perp_dist:
return False
# 3. 邻近性/重叠性: 端点之间的最小距离
min_ep_dist = min(np.linalg.norm(p1a-p1b), np.linalg.norm(p1a-p2b),
np.linalg.norm(p2a-p1b), np.linalg.norm(p2a-p2b))
current_max_allowed_ep_gap = max(max_ep_gap_abs, max_ep_gap_factor * shorter_len)
if min_ep_dist > current_max_allowed_ep_gap:
return False
# 附加检查:确保线段确实是"连接的"或"重叠的"
# 计算一个端点到另一个 *线段* (非无限线) 的距离
def dist_point_to_segment(p, seg_a, seg_b):
ap = p - seg_a
ab = seg_b - seg_a
ab_len_sq = np.dot(ab, ab)
if ab_len_sq < 1e-6: return np.linalg.norm(ap)
t = np.dot(ap, ab) / ab_len_sq
if t < 0.0: closest_point = seg_a
elif t > 1.0: closest_point = seg_b
else: closest_point = seg_a + t * ab
return np.linalg.norm(p - closest_point)
dist_p1a_to_seg_b = dist_point_to_segment(p1a, p1b, p2b)
dist_p2a_to_seg_b = dist_point_to_segment(p2a, p1b, p2b)
dist_p1b_to_seg_a = dist_point_to_segment(p1b, p1a, p2a)
dist_p2b_to_seg_a = dist_point_to_segment(p2b, p1a, p2a)
if min(dist_p1a_to_seg_b, dist_p2a_to_seg_b, dist_p1b_to_seg_a, dist_p2b_to_seg_a) > current_max_allowed_ep_gap:
return False
return True
def _merge_two_lines(line1_pts, line2_pts):
points = np.array([
line1_pts[:2], line1_pts[2:],
line2_pts[:2], line2_pts[2:]
], dtype=np.float32)
vx, vy, x0, y0 = cv2.fitLine(points.reshape(-1,1,2), cv2.DIST_L2, 0, 0.01, 0.01)
vx, vy, x0, y0 = vx[0], vy[0], x0[0], y0[0]
projected_params = []
line_origin = np.array([x0, y0])
line_direction = np.array([vx, vy])
for i in range(4):
pt_vec = points[i] - line_origin
param = np.dot(pt_vec, line_direction)
projected_params.append(param)
min_param = min(projected_params)
max_param = max(projected_params)
p_start = line_origin + min_param * line_direction
p_end = line_origin + max_param * line_direction
return [int(round(p_start[0])), int(round(p_start[1])),
int(round(p_end[0])), int(round(p_end[1]))]
def _merge_collinear_lines_iterative(lines_from_hough,
min_initial_len,
max_angle_diff_deg,
max_ep_gap_abs, max_ep_gap_factor,
max_p_dist_abs, max_p_dist_factor):
if lines_from_hough is None:
return None
# 将HoughLinesP的输出转换为Python列表 [[x1,y1,x2,y2], ...]
py_lines = [list(line[0]) for line in lines_from_hough]
# 过滤掉初始太短的线
current_lines = [line for line in py_lines if np.linalg.norm(np.array(line[:2]) - np.array(line[2:])) >= min_initial_len]
if not current_lines or len(current_lines) < 2:
return np.array([[line] for line in current_lines]) if current_lines else np.array([])
made_change_in_pass = True
while made_change_in_pass:
made_change_in_pass = False
i = 0
while i < len(current_lines):
j = i + 1
merged_line_i = False
while j < len(current_lines):
if _are_lines_mergeable(current_lines[i], current_lines[j],
max_angle_diff_deg,
max_ep_gap_abs, max_ep_gap_factor,
max_p_dist_abs, max_p_dist_factor):
merged_line = _merge_two_lines(current_lines[i], current_lines[j])
current_lines[i] = merged_line # 更新第i条线
current_lines.pop(j) # 移除第j条线
made_change_in_pass = True
merged_line_i = True
# 由于current_lines[i]已改变,且列表长度已改变,
# 最安全的是从头开始或至少重新评估current_lines[i]
# 但对于这种贪心策略继续尝试将新的current_lines[i]与后续线合并是可以的
# j的位置不需要改变因为它指向被删除元素后的下一个元素
continue # j 现在指向下一条未检查的线相对于更新后的i
j += 1
# 如果 line_i 在内部循环中被修改过,则外部的 i 也应该重新评估
# 但由于我们是迭代地进行整个过程(while made_change_in_pass), 最终会收敛
i += 1
return np.array([[line] for line in current_lines]) if current_lines else np.array([])

View File

@ -3,9 +3,14 @@ import numpy as np
import os
import datetime
from utils.base_line_handler import _merge_collinear_lines_iterative
from utils.log_helper import LogHelper, get_logger, section, info, debug, warning, error, success, timing
def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, stone_path_mode=False):
def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True,
max_slope_threshold=2,
min_slope_threshold=0.5,
min_line_length=0.05,
max_line_gap=40):
"""
检测左右两条平行的黄色轨道线优化后能够更准确处理各种路况
@ -14,7 +19,11 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
observe: 是否输出中间状态信息和可视化结果默认为False
delay: 展示每个步骤的等待时间(毫秒)
save_log: 是否保存日志和图像
stone_path_mode: 石板路模式针对石板路上的黄线进行特殊处理
max_slope_threshold: 最大斜率阈值
min_slope_threshold: 最小斜率阈值
min_line_length: 最小线段长度
max_line_gap: 最大线段间距
返回:
tuple: (中心线信息, 左轨迹线信息, 右轨迹线信息)
@ -44,57 +53,24 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
# 转换到HSV颜色空间以便更容易提取黄色
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 根据是否为石板路模式选择不同的参数
if stone_path_mode:
# 石板路上的黄线通常对比度更低,需要更宽松的颜色范围
lower_yellow = np.array([8, 50, 50]) # 更宽松的黄色下限
upper_yellow = np.array([45, 255, 255]) # 更宽松的黄色上限
else:
# 标准黄色的HSV范围
lower_yellow = np.array([15, 80, 80])
upper_yellow = np.array([35, 255, 255])
# 标准黄色的HSV范围
lower_yellow = np.array([15, 80, 80])
upper_yellow = np.array([35, 255, 255])
# 创建黄色的掩码
mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
# 应用对比度增强
if stone_path_mode:
# 在处理掩码前先对原图像进行预处理
# 对原图进行自适应直方图均衡化增强对比度
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
l = clahe.apply(l)
lab = cv2.merge((l, a, b))
enhanced_img = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
# 用增强后的图像重新检测黄色
enhanced_hsv = cv2.cvtColor(enhanced_img, cv2.COLOR_BGR2HSV)
enhanced_mask = cv2.inRange(enhanced_hsv, lower_yellow, upper_yellow)
# 组合原始掩码和增强掩码
mask = cv2.bitwise_or(mask, enhanced_mask)
if observe:
debug("增强对比度和颜色检测", "处理")
cv2.imshow("增强对比度", enhanced_img)
cv2.imshow("增强后的黄色掩码", enhanced_mask)
cv2.waitKey(delay)
# 形态学操作以改善掩码
if stone_path_mode:
# 石板路上的线条可能更细更断续,使用更大的膨胀核和更多的迭代次数
kernel = np.ones((7, 7), np.uint8)
mask = cv2.dilate(mask, kernel, iterations=2)
mask = cv2.erode(mask, np.ones((3, 3), np.uint8), iterations=1)
else:
kernel = np.ones((5, 5), np.uint8)
mask = cv2.dilate(mask, kernel, iterations=1)
mask = cv2.erode(mask, np.ones((3, 3), np.uint8), iterations=1)
kernel = np.ones((5, 5), np.uint8)
mask = cv2.dilate(mask, kernel, iterations=1)
mask = cv2.erode(mask, np.ones((3, 3), np.uint8), iterations=1)
if observe:
debug("步骤1: 创建黄色掩码", "处理")
cv2.imshow("黄色掩码", mask)
mask_display = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
cv2.putText(mask_display, "Step 1: Yellow Mask", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(mask_display, f"Lower: {lower_yellow}", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.putText(mask_display, f"Upper: {upper_yellow}", (10, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("黄色掩码", mask_display)
cv2.waitKey(delay)
# 裁剪底部区域重点关注近处的黄线
@ -103,28 +79,26 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
if observe:
debug("步骤1.5: 底部区域掩码", "处理")
cv2.imshow("底部区域掩码", bottom_roi)
bottom_roi_display = cv2.cvtColor(bottom_roi, cv2.COLOR_GRAY2BGR)
cv2.putText(bottom_roi_display, "Step 1.5: Bottom ROI", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(bottom_roi_display, f"ROI Height: {bottom_roi_height}px ({bottom_roi_height/height*100:.0f}%)", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("底部区域掩码", bottom_roi_display)
cv2.waitKey(delay)
# 边缘检测 - 针对石板路调整参数
if stone_path_mode:
edges = cv2.Canny(mask, 20, 100, apertureSize=3) # 进一步降低阈值以捕捉更弱的边缘
else:
edges = cv2.Canny(mask, 50, 150, apertureSize=3)
# INFO 边缘检测
edges = cv2.Canny(mask, 50, 150, apertureSize=3)
if observe:
debug("步骤2: 边缘检测", "处理")
cv2.imshow("边缘检测", edges)
edges_display = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
cv2.putText(edges_display, "Step 2: Edge Detection (Canny)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(edges_display, "Thresholds: (50, 150)", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("边缘检测", edges_display)
cv2.waitKey(delay)
# 霍夫变换检测直线 - 根据是否为石板路调整参数
if stone_path_mode:
# 石板路上的线段可能更短更断续,使用更宽松的参数
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=15,
minLineLength=width*0.02, maxLineGap=60)
else:
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=25,
minLineLength=width*0.05, maxLineGap=40)
# INFO 霍夫变换检测直线
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=25,
minLineLength=width*min_line_length, maxLineGap=max_line_gap)
if lines is None or len(lines) == 0:
error("未检测到直线", "失败")
@ -133,6 +107,8 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
if observe:
debug(f"步骤3: 检测到 {len(lines)} 条直线", "处理")
lines_img = img.copy()
cv2.putText(lines_img, "Step 3: Hough Lines", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.putText(lines_img, f"Th:25, MinLen:{width*0.05:.1f}, MaxGap:{max_line_gap}", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(lines_img, (x1, y1), (x2, y2), (0, 255, 0), 2)
@ -154,11 +130,8 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
else:
slope = (y2 - y1) / (x2 - x1)
# 根据是否为石板路调整斜率阈值
min_slope_threshold = 0.4 if stone_path_mode else 0.75
# 筛选接近垂直的线 (斜率较大),但允许更多倾斜度
if abs(slope) > min_slope_threshold:
if max_slope_threshold > abs(slope) > min_slope_threshold:
line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
# 计算线的中点x坐标
mid_x = (x1 + x2) / 2
@ -167,30 +140,15 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
# 保存线段、其坐标、斜率和长度
vertical_lines.append((line[0], mid_x, mid_y, slope, line_length))
# vertical_lines = _merge_collinear_lines_iterative(vertical_lines,
# min_initial_len=5.0,
# max_angle_diff_deg=10.0,
# max_ep_gap_abs=max_line_gap / 2.0,
# max_ep_gap_factor=0.25,
# max_p_dist_abs=max_line_gap / 4.0,
# max_p_dist_factor=0.1)
if len(vertical_lines) < 2:
# 石板路模式下,尝试放宽斜率条件重新筛选线段
if stone_path_mode:
vertical_lines = []
for line in lines:
x1, y1, x2, y2 = line[0]
# 仍然优先选择图像底部的线
if y1 < height * 0.6 and y2 < height * 0.6:
continue # 忽略上部分的线
# 计算斜率 (避免除零错误)
if abs(x2 - x1) < 5: # 几乎垂直的线
slope = 100
else:
slope = (y2 - y1) / (x2 - x1)
# 使用更宽松的斜率阈值
if abs(slope) > 0.2: # 进一步放宽斜率阈值
line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
mid_x = (x1 + x2) / 2
mid_y = (y1 + y2) / 2
vertical_lines.append((line[0], mid_x, mid_y, slope, line_length))
if len(vertical_lines) < 2:
error("未检测到足够的垂直线", "失败")
return None, None, None
@ -198,6 +156,8 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
if observe:
debug(f"步骤4: 找到 {len(vertical_lines)} 条垂直线", "处理")
v_lines_img = img.copy()
cv2.putText(v_lines_img, "Step 4: Vertical Lines Filtered", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.putText(v_lines_img, f"Min Slope Abs: {min_slope_threshold:.2f}", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
for line_info in vertical_lines:
line, _, _, slope, _ = line_info
x1, y1, x2, y2 = line
@ -211,76 +171,6 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
# 优先选择更接近图像底部的线 - 根据y坐标均值排序
vertical_lines.sort(key=lambda x: x[2], reverse=True) # 按mid_y从大到小排序
# 石板路模式下,可能需要处理断续的线段或合并相近的线段
if stone_path_mode and len(vertical_lines) >= 3:
# 尝试合并相近的线段
merged_lines = []
processed = [False] * len(vertical_lines)
for i in range(len(vertical_lines)):
if processed[i]:
continue
current_line = vertical_lines[i]
_, current_mid_x, current_mid_y, current_slope, current_length = current_line
# 查找相近的线段
similar_lines = [current_line]
processed[i] = True
for j in range(i+1, len(vertical_lines)):
if processed[j]:
continue
candidate_line = vertical_lines[j]
_, candidate_mid_x, candidate_mid_y, candidate_slope, candidate_length = candidate_line
# 如果x坐标接近且斜率相似认为是同一条线的不同部分
x_diff = abs(current_mid_x - candidate_mid_x)
slope_diff = abs(current_slope - candidate_slope)
y_diff = abs(current_mid_y - candidate_mid_y)
# 放宽相似线段的判断条件
if ((x_diff < width * 0.08 and slope_diff < 0.4) or # 更宽松的x差异和斜率差异
(x_diff < width * 0.05 and y_diff < height * 0.2)): # 或者x和y都比较接近
similar_lines.append(candidate_line)
processed[j] = True
# 如果找到多条相近的线,合并它们
if len(similar_lines) > 1:
# 按线长度加权合并
total_weight = sum(line[4] for line in similar_lines)
merged_x1 = sum(line[0][0] * line[4] for line in similar_lines) / total_weight
merged_y1 = sum(line[0][1] * line[4] for line in similar_lines) / total_weight
merged_x2 = sum(line[0][2] * line[4] for line in similar_lines) / total_weight
merged_y2 = sum(line[0][3] * line[4] for line in similar_lines) / total_weight
merged_line = (np.array([int(merged_x1), int(merged_y1),
int(merged_x2), int(merged_y2)]),
(merged_x1 + merged_x2) / 2,
(merged_y1 + merged_y2) / 2,
(merged_y2 - merged_y1) / (merged_x2 - merged_x1 + 1e-6),
np.sqrt((merged_x2-merged_x1)**2 + (merged_y2-merged_y1)**2))
merged_lines.append(merged_line)
else:
merged_lines.append(current_line)
vertical_lines = merged_lines
if observe:
debug(f"步骤4.5: 合并后找到 {len(vertical_lines)} 条垂直线", "处理")
merged_img = img.copy()
for line_info in vertical_lines:
line, _, _, slope, _ = line_info
x1, y1, x2, y2 = line
cv2.line(merged_img, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 255), 2)
# 显示斜率
cv2.putText(merged_img, f"{slope:.2f}", (int((x1+x2)//2), int((y1+y2)//2)),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
cv2.imshow("合并后的垂直线", merged_img)
cv2.waitKey(delay)
# 按x坐标将线分为左右两组
left_lines = [line for line in vertical_lines if line[1] < center_x]
right_lines = [line for line in vertical_lines if line[1] > center_x]
@ -301,10 +191,40 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
if observe:
debug(f"左侧候选线数量: {len(left_lines)}, 右侧候选线数量: {len(right_lines)}", "线候选")
# 创建左右线可视化图像
left_right_img = img.copy()
cv2.putText(left_right_img, "Left and Right Candidate Lines", (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
# 绘制左侧候选线(蓝色)
for line_info in left_lines:
line = line_info[0]
x1, y1, x2, y2 = line
cv2.line(left_right_img, (x1, y1), (x2, y2), (255, 0, 0), 2)
# 显示斜率
mid_x = (x1 + x2) // 2
mid_y = (y1 + y2) // 2
cv2.putText(left_right_img, f"L:{line_info[3]:.2f}", (mid_x, mid_y),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
# 绘制右侧候选线(红色)
for line_info in right_lines:
line = line_info[0]
x1, y1, x2, y2 = line
cv2.line(left_right_img, (x1, y1), (x2, y2), (0, 0, 255), 2)
# 显示斜率
mid_x = (x1 + x2) // 2
mid_y = (y1 + y2) // 2
cv2.putText(left_right_img, f"R:{line_info[3]:.2f}", (mid_x, mid_y),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
cv2.imshow("左右候选线", left_right_img)
cv2.waitKey(delay)
# 优化说明:在默认模式下,评分函数和线对选择都优先考虑更靠近图像中心的线段
# 这有助于减少对图像边缘可能出现的干扰线的选择,提高轨道线检测的准确性
# 改进的评分函数 - 同时考虑斜率、位置、长度和在图像中的位置
# INFO 改进的评分函数 - 同时考虑斜率、位置、长度和在图像中的位置
def score_line(line_info, is_left):
_, mid_x, mid_y, slope, length = line_info
line_points = line_info[0] # 获取线段的端点坐标
@ -325,14 +245,8 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
length_score = min(1.0, length_ratio * 1.2) # 适当提高长线段的权重
# 位置评分 - 线段位于预期位置得分高
# 根据是否为石板路模式调整预期位置
center_x = width / 2
if stone_path_mode:
# 石板路上的轨道宽度可能不同
expected_track_width = width * 0.5 # 石板路轨道宽度估计
else:
# 普通轨道的期望位置 - 默认模式下更靠近中心
expected_track_width = width * 0.4 # 普通轨道宽度估计,更窄以接近中心
expected_track_width = width * 0.4 # 普通轨道宽度估计,更窄以接近中心
# 计算预期的线位置(基于图像中心和轨道宽度)
expected_x = center_x - expected_track_width * 0.5 if is_left else center_x + expected_track_width * 0.5
@ -391,27 +305,16 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
bottom_reach_score = 1.0 if reaches_bottom else 0.5
# 综合评分 - 调整权重
if stone_path_mode:
# 石板路模式下更关注位置和底部接近程度
final_score = (
y_score * 0.25 + # 底部接近度
length_score * 0.15 + # 线段长度
x_score * 0.15 + # 中点位置
bottom_x_score * 0.2 + # 底部点位置
slope_score * 0.15 + # 斜率合适性
bottom_reach_score * 0.1 # 是否到达底部
)
else:
# 普通轨道模式下更关注中心接近性
final_score = (
y_score * 0.15 + # 底部接近度
length_score * 0.15 + # 线段长度
x_score * 0.15 + # 中点位置
center_proximity_score * 0.2 + # 与中心的接近度 (新增)
bottom_x_score * 0.15 + # 底部点位置
slope_score * 0.1 + # 斜率合适性
bottom_reach_score * 0.1 # 是否到达底部
)
# 普通轨道模式下更关注中心接近性
final_score = (
y_score * 0.15 + # 底部接近度
length_score * 0.05 + # 线段长度
x_score * 0.15 + # 中点位置
center_proximity_score * 0.3 + # 与中心的接近度 (新增)
bottom_x_score * 0.15 + # 底部点位置
slope_score * 0.1 + # 斜率合适性
bottom_reach_score * 0.1 # 是否到达底部
)
return final_score
@ -465,12 +368,8 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
width_score = 0.0
else:
# 轨道宽度应该在合理范围内 - 调整范围更加精确
if stone_path_mode:
expected_width = width * 0.5 # 石板路可能更宽一些
allowed_deviation = width * 0.3 # 允许的偏差范围
else:
expected_width = width * 0.4 # 普通轨道相对窄一些,更靠近中心
allowed_deviation = width * 0.2 # 允许的偏差范围,更精确
expected_width = width * 0.4 # 普通轨道相对窄一些,更靠近中心
allowed_deviation = width * 0.2 # 允许的偏差范围,更精确
width_diff = abs(track_width - expected_width)
width_score = max(0, 1.0 - width_diff / allowed_deviation)
@ -509,25 +408,22 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
# 综合评分 - 调整权重
# 更重视平行性和底部宽度
if stone_path_mode:
pair_score = (left_score + right_score) * 0.3 + parallel_score * 0.25 + width_score * 0.2 + symmetry_score * 0.1 + bottom_width_score * 0.15
else:
# 默认模式下,增加对中心接近性的权重
# 计算左右线到中心的距离
left_to_center = abs(left_x - center_x)
right_to_center = abs(right_x - center_x)
# 标准化距离(与图像宽度相关)
left_center_ratio = left_to_center / (width * 0.5)
right_center_ratio = right_to_center / (width * 0.5)
# 接近度得分 - 越接近中心分数越高
left_center_score = max(0, 1.0 - left_center_ratio)
right_center_score = max(0, 1.0 - right_center_ratio)
center_proximity_score = (left_center_score + right_center_score) / 2
# 给予中心接近性更高的权重
pair_score = (left_score + right_score) * 0.25 + parallel_score * 0.2 + width_score * 0.15 + symmetry_score * 0.1 + bottom_width_score * 0.1 + center_proximity_score * 0.2
# 默认模式下,增加对中心接近性的权重
# 计算左右线到中心的距离
left_to_center = abs(left_x - center_x)
right_to_center = abs(right_x - center_x)
# 标准化距离(与图像宽度相关)
left_center_ratio = left_to_center / (width * 0.5)
right_center_ratio = right_to_center / (width * 0.5)
# 接近度得分 - 越接近中心分数越高
left_center_score = max(0, 1.0 - left_center_ratio)
right_center_score = max(0, 1.0 - right_center_ratio)
center_proximity_score = (left_center_score + right_center_score) / 2
# 给予中心接近性更高的权重
pair_score = (left_score + right_score) * 0.25 + parallel_score * 0.2 + width_score * 0.15 + symmetry_score * 0.1 + bottom_width_score * 0.1 + center_proximity_score * 0.2
if pair_score > best_pair_score:
best_pair_score = pair_score
@ -575,6 +471,26 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
right_x1, right_x2 = right_x2, right_x1
right_y1, right_y2 = right_y2, right_y1
# 尝试延长线段到图像底部,处理被石板路部分遮挡的情况
left_extended_y2 = height
if abs(left_x2 - left_x1) < 5: # 几乎垂直
left_extended_x2 = left_x2
else:
left_slope = (left_y2 - left_y1) / (left_x2 - left_x1)
left_extended_x2 = left_x1 + (left_extended_y2 - left_y1) / left_slope
right_extended_y2 = height
if abs(right_x2 - right_x1) < 5: # 几乎垂直
right_extended_x2 = right_x2
else:
right_slope = (right_y2 - right_y1) / (right_x2 - right_x1)
right_extended_x2 = right_x1 + (right_extended_y2 - right_y1) / right_slope
# 更新线段端点为延长后的坐标
left_x2, left_y2 = int(left_extended_x2), left_extended_y2
right_x2, right_y2 = int(right_extended_x2), right_extended_y2
# 尝试延长线段到图像底部,处理被石板路部分遮挡的情况
left_extended_y2 = height
if abs(left_x2 - left_x1) < 5: # 几乎垂直
@ -893,11 +809,16 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
# 显示偏差信息
cv2.putText(result_img, f"Deviation: {deviation:.1f}px", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(result_img, "Final Result", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
if 'best_pair_score' in locals() and best_pair_score != -1:
cv2.putText(result_img, f"Pair Score: {best_pair_score:.2f}", (10, 85), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
current_y_offset = 105
else:
current_y_offset = 85
# 显示是否为石板路模式
if stone_path_mode:
cv2.putText(result_img, "Stone Path Mode", (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
cv2.putText(result_img, f"L-Slope: {left_line[3]:.2f}, R-Slope: {right_line[3]:.2f}", (10, current_y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
current_y_offset += 20
cv2.putText(result_img, f"Track Width: {right_line[1] - left_line[1]:.1f}px", (10, current_y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
if observe:
cv2.imshow("轨迹线检测结果", result_img)
@ -929,7 +850,6 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
"right_track_mid_x": float(right_line[1]),
"track_width": float(right_line[1] - left_line[1]),
"center_slope": float(center_slope),
"stone_path_mode": stone_path_mode
}
info(f"双轨迹线检测结果: {log_info}", "日志")
@ -952,7 +872,6 @@ def detect_dual_track_lines(image, observe=False, delay=1000, save_log=True, sto
"slope": float(center_slope),
"is_vertical": abs(center_slope) > 5.0, # 判断是否接近垂直
"track_width": float(right_line[1] - left_line[1]), # 两轨迹线之间的距离
"stone_path_mode": stone_path_mode # 记录是否使用了石板路模式
}
return center_info, left_track_info, right_track_info
@ -1013,7 +932,11 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
if observe:
debug("步骤1: 创建黄色掩码", "处理")
cv2.imshow("黄色掩码", combined_mask)
mask_display = cv2.cvtColor(combined_mask, cv2.COLOR_GRAY2BGR)
cv2.putText(mask_display, "Step 1: Yellow Mask (Center Based)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(mask_display, f"Lower: {lower_yellow} + Darker Var.", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.putText(mask_display, f"Upper: {upper_yellow} + Darker Var.", (10, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("黄色掩码", mask_display)
cv2.waitKey(delay)
# 裁剪底部区域重点关注近处的黄线
@ -1022,7 +945,10 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
if observe:
debug("步骤1.5: 底部区域掩码", "处理")
cv2.imshow("底部区域掩码", bottom_roi)
bottom_roi_display = cv2.cvtColor(bottom_roi, cv2.COLOR_GRAY2BGR)
cv2.putText(bottom_roi_display, "Step 1.5: Bottom ROI (Center Based)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(bottom_roi_display, f"ROI Height: {bottom_roi_height}px ({bottom_roi_height/height*100:.0f}%)", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("底部区域掩码", bottom_roi_display)
cv2.waitKey(delay)
# 边缘检测
@ -1030,7 +956,10 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
if observe:
debug("步骤2: 边缘检测", "处理")
cv2.imshow("边缘检测", edges)
edges_display = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
cv2.putText(edges_display, "Step 2: Edge Detection (Canny - Center Based)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(edges_display, "Thresholds: (50, 150)", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
cv2.imshow("边缘检测", edges_display)
cv2.waitKey(delay)
# 霍夫变换检测直线
@ -1038,18 +967,9 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
minLineLength=width*0.05, maxLineGap=40)
if lines is None or len(lines) == 0:
error("未检测到直线", "失败")
error("未检测到直线 (或合并后无直线 - Center Based)", "失败")
return None, None, None
if observe:
debug(f"步骤3: 检测到 {len(lines)} 条直线", "处理")
lines_img = img.copy()
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(lines_img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("检测到的直线", lines_img)
cv2.waitKey(delay)
# 筛选近似垂直的线
vertical_lines = []
for line in lines:
@ -1065,7 +985,7 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
else:
slope = (y2 - y1) / (x2 - x1)
# 筛选接近垂直的线 (斜率较大)
# 筛选接近垂直的线 (斜率较大),但允许更多倾斜度
if abs(slope) > 0.5: # 降低斜率阈值以捕获更多候选线
line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
# 计算线的中点x坐标
@ -1081,18 +1001,41 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
if observe:
debug(f"步骤4: 找到 {len(vertical_lines)} 条垂直线", "处理")
v_lines_img = img.copy()
v_lines_img_display = img.copy()
cv2.putText(v_lines_img_display, "Step 4: Vertical Lines Filtered (Center Based)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.putText(v_lines_img_display, "Min Slope Abs: 0.50", (10, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1) # Slope threshold is 0.5 here
for line_info in vertical_lines:
line, _, _, slope, _ = line_info
x1, y1, x2, y2 = line
cv2.line(v_lines_img, (x1, y1), (x2, y2), (0, 255, 255), 2)
cv2.line(v_lines_img_display, (x1, y1), (x2, y2), (0, 255, 255), 2)
# 显示斜率
cv2.putText(v_lines_img, f"{slope:.2f}", ((x1+x2)//2, (y1+y2)//2),
cv2.putText(v_lines_img_display, f"{slope:.2f}", ((x1+x2)//2, (y1+y2)//2),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
cv2.imshow("垂直线", v_lines_img)
cv2.imshow("垂直线", v_lines_img_display)
cv2.waitKey(delay)
# 评分函数 - 用于找到最可能的中心线
debug(f"步骤2.5 (Center Based): 初始检测到 {len(vertical_lines)} 条垂直线,尝试合并", "处理")
# 合并参数设置 (可以根据需要调整,这里使用与 detect_dual_track_lines 类似的设置)
# 注意:这里的 max_line_gap 是 HoughLinesP 本身的参数,不是函数参数
# 如果需要独立于 detect_dual_track_lines 中的 max_line_gap需要单独定义或传递
current_max_line_gap = 40 # 来自 HoughLinesP
min_len_for_merge_cb = 5.0
angle_thresh_deg_cb = 10.0
ep_gap_abs_cb = current_max_line_gap / 2.0
ep_gap_factor_cb = 0.25
p_dist_abs_cb = current_max_line_gap / 4.0
p_dist_factor_cb = 0.1
# vertical_lines = _merge_collinear_lines_iterative(vertical_lines,
# min_initial_len=min_len_for_merge_cb,
# max_angle_diff_deg=angle_thresh_deg_cb,
# max_ep_gap_abs=ep_gap_abs_cb,
# max_ep_gap_factor=ep_gap_factor_cb,
# max_p_dist_abs=p_dist_abs_cb,
# max_p_dist_factor=p_dist_factor_cb)
# INFO 评分函数 - 用于找到最可能的中心线
def score_center_line(line_info):
_, mid_x, mid_y, slope, length = line_info
@ -1129,6 +1072,20 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
# 找到可能的中心线
center_candidates = sorted(vertical_lines, key=score_center_line, reverse=True)
if observe:
debug(f"步骤3.5: 找到 {len(center_candidates)} 条可能的中心线", "处理")
center_candidates_img_display = img.copy()
cv2.putText(center_candidates_img_display, "Step 3: Center Candidates (Center Based)", (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
for line_info in center_candidates:
line, _, _, slope, _ = line_info
x1, y1, x2, y2 = line
cv2.line(center_candidates_img_display, (x1, y1), (x2, y2), (0, 255, 255), 2)
# 显示斜率
cv2.putText(center_candidates_img_display, f"{slope:.2f}", ((x1+x2)//2, (y1+y2)//2),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
cv2.imshow("可能的中心线", center_candidates_img_display)
cv2.waitKey(delay)
# 如果有足够的候选线取前3个进行评估
if len(center_candidates) >= 3:
@ -1345,7 +1302,7 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
bottom_center_x = max(0, min(width - 1, bottom_center_x))
deviation = bottom_center_x - center_x
# 创建结果图像
# INFO 创建结果图像
result_img = None
if observe or save_log:
result_img = img.copy()
@ -1368,6 +1325,18 @@ def detect_center_based_dual_track_lines(image, observe=False, delay=1000, save_
# 显示偏差信息
cv2.putText(result_img, f"Deviation: {deviation:.1f}px", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(result_img, "Final Result (Center Based)", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
if 'best_score' in locals() and best_score != -1:
cv2.putText(result_img, f"Pair Score: {best_score:.2f}", (10, 85), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
current_y_offset = 105
else:
current_y_offset = 85
cv2.putText(result_img, f"Center Slope: {center_slope:.2f}", (10, current_y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
current_y_offset += 20
cv2.putText(result_img, f"L-Slope: {left_line[3]:.2f}, R-Slope: {right_line[3]:.2f}", (10, current_y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
current_y_offset += 20
cv2.putText(result_img, f"Track Width: {right_line[1] - left_line[1]:.1f}px", (10, current_y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
if observe:
cv2.imshow("改进的中心线检测结果", result_img)
@ -1446,7 +1415,7 @@ def auto_detect_dual_track_lines(image, observe=False, delay=1000, save_log=True
result = detect_center_based_dual_track_lines(image, observe, delay, save_log)
else:
info("使用传统检测方法", "检测")
result = detect_dual_track_lines(image, observe, delay, save_log, stone_path_mode=False)
result = detect_dual_track_lines(image, observe, delay, save_log)
# 检查结果是否成功
if result[0] is not None: