更新日志文件,增加了边缘检测过程中的调试信息和结果记录;修改了黄色赛道检测演示程序的输入路径;在边缘检测算法中引入了线段质量评分机制,优化了线段选择逻辑,提升了检测的准确性和稳定性。
This commit is contained in:
		
							parent
							
								
									e08c8b15a9
								
							
						
					
					
						commit
						4a2ab00f8d
					
				@ -55,3 +55,13 @@
 | 
			
		||||
2025-05-19 20:50:40 | DEBUG    | utils.log_helper - 🐞 显示边缘斜率和中线交点
 | 
			
		||||
2025-05-19 20:50:41 | INFO     | utils.log_helper - ℹ️ 保存横向边缘检测结果图像到: logs/image/horizontal_edge_20250519_205041_583040.jpg
 | 
			
		||||
2025-05-19 20:50:41 | INFO     | utils.log_helper - ℹ️ 横向边缘检测结果: {'timestamp': '20250519_205041_583040', 'edge_point': (92, 1077), 'distance_to_center': -868, 'slope': -0.07008086253369272, 'distance_to_bottom': 63.83018867924534, 'intersection_point': (960, 1016), 'is_truncated': False}
 | 
			
		||||
2025-05-19 21:24:41 | DEBUG    | utils.log_helper - 🐞 步骤1: 原始图像已加载
 | 
			
		||||
2025-05-19 21:24:42 | DEBUG    | utils.log_helper - 🐞 步骤2: 创建黄色掩码
 | 
			
		||||
2025-05-19 21:24:43 | DEBUG    | utils.log_helper - 🐞 步骤3: 提取黄色部分
 | 
			
		||||
2025-05-19 21:24:44 | DEBUG    | utils.log_helper - 🐞 检测底部和顶部边缘点
 | 
			
		||||
2025-05-19 21:24:45 | DEBUG    | utils.log_helper - 🐞 步骤4: 边缘检测
 | 
			
		||||
2025-05-19 21:24:46 | DEBUG    | utils.log_helper - 🐞 步骤5: 检测到 18 条直线
 | 
			
		||||
2025-05-19 21:24:47 | DEBUG    | utils.log_helper - 🐞 步骤6: 找到 3 条水平线
 | 
			
		||||
2025-05-19 21:24:48 | DEBUG    | utils.log_helper - 🐞 显示边缘斜率和中线交点
 | 
			
		||||
2025-05-19 21:24:49 | INFO     | utils.log_helper - ℹ️ 保存横向边缘检测结果图像到: logs/image/horizontal_edge_20250519_212449_369767.jpg
 | 
			
		||||
2025-05-19 21:24:49 | INFO     | utils.log_helper - ℹ️ 横向边缘检测结果: {'timestamp': '20250519_212449_369767', 'edge_point': (540, 907), 'distance_to_center': -420, 'slope': -0.12202852614896989, 'distance_to_bottom': 224.25198098256737, 'intersection_point': (960, 855), 'score': 0.5611365011519962, 'valid': True, 'reason': ''}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								logs/robot_2025-05-20.log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								logs/robot_2025-05-20.log
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
2025-05-20 09:24:31 | DEBUG    | utils.log_helper - 🐞 步骤1: 原始图像已加载
 | 
			
		||||
2025-05-20 09:24:32 | DEBUG    | utils.log_helper - 🐞 步骤2: 创建黄色掩码
 | 
			
		||||
2025-05-20 09:24:33 | DEBUG    | utils.log_helper - 🐞 步骤3: 提取黄色部分
 | 
			
		||||
2025-05-20 09:24:34 | DEBUG    | utils.log_helper - 🐞 检测底部和顶部边缘点
 | 
			
		||||
2025-05-20 09:24:35 | DEBUG    | utils.log_helper - 🐞 步骤4: 边缘检测
 | 
			
		||||
2025-05-20 09:24:36 | DEBUG    | utils.log_helper - 🐞 步骤5: 检测到 18 条直线
 | 
			
		||||
2025-05-20 09:24:37 | DEBUG    | utils.log_helper - 🐞 步骤6: 找到 3 条水平线
 | 
			
		||||
2025-05-20 09:24:38 | DEBUG    | utils.log_helper - 🐞 显示边缘斜率和中线交点
 | 
			
		||||
2025-05-20 09:24:39 | INFO     | utils.log_helper - ℹ️ 保存横向边缘检测结果图像到: logs/image/horizontal_edge_20250520_092439_823936.jpg
 | 
			
		||||
2025-05-20 09:24:39 | INFO     | utils.log_helper - ℹ️ 横向边缘检测结果: {'timestamp': '20250520_092439_823936', 'edge_point': (540, 907), 'distance_to_center': -420, 'slope': -0.12202852614896989, 'distance_to_bottom': 224.25198098256737, 'intersection_point': (960, 855), 'score': 0.5611365011519962, 'valid': True, 'reason': ''}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								res/path/test-2.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								res/path/test-2.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 118 KiB  | 
@ -44,7 +44,7 @@ def process_image(image_path, save_dir=None, show_steps=False):
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='黄色赛道检测演示程序')
 | 
			
		||||
    parser.add_argument('--input', type=str, default='res/path/test-1.jpg', help='输入图像或视频的路径')
 | 
			
		||||
    parser.add_argument('--input', type=str, default='res/path/test-2.jpg', help='输入图像或视频的路径')
 | 
			
		||||
    parser.add_argument('--output', type=str, default='res/path/test/result_image_20250514_024313.png', help='输出结果的保存路径')
 | 
			
		||||
    parser.add_argument('--type', type=str, choices=['image', 'video'], help='输入类型,不指定会自动检测')
 | 
			
		||||
    parser.add_argument('--show', default=True, action='store_true', help='显示处理步骤')
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,11 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
    bottom_bound = height
 | 
			
		||||
    top_bound = height - search_height
 | 
			
		||||
    
 | 
			
		||||
    # 定义合理的值范围
 | 
			
		||||
    valid_y_range = (height * 0.5, height)  # 有效的y坐标范围(下半部分图像)
 | 
			
		||||
    max_slope = 0.15  # 最大允许斜率(接近水平)
 | 
			
		||||
    min_line_length = width * 0.2  # 最小线长度
 | 
			
		||||
    
 | 
			
		||||
    if observe:
 | 
			
		||||
        debug("步骤1: 原始图像已加载", "加载")
 | 
			
		||||
        search_region_img = img.copy()
 | 
			
		||||
@ -118,8 +123,8 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
        cv2.imshow("边缘检测", edges)
 | 
			
		||||
        cv2.waitKey(delay)
 | 
			
		||||
    
 | 
			
		||||
    # 使用霍夫变换检测直线
 | 
			
		||||
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=30, 
 | 
			
		||||
    # 使用霍夫变换检测直线,降低阈值以检测更多线段
 | 
			
		||||
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=25, 
 | 
			
		||||
                           minLineLength=width*0.1, maxLineGap=30)
 | 
			
		||||
    
 | 
			
		||||
    if lines is None or len(lines) == 0:
 | 
			
		||||
@ -148,181 +153,62 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
        slope = (y2 - y1) / (x2 - x1)
 | 
			
		||||
        
 | 
			
		||||
        # 筛选接近水平的线 (斜率接近0),但容许更大的倾斜度
 | 
			
		||||
        if abs(slope) < 0.3:
 | 
			
		||||
        if abs(slope) < max_slope:
 | 
			
		||||
            # 确保线在搜索区域内
 | 
			
		||||
            if ((left_bound <= x1 <= right_bound and top_bound <= y1 <= bottom_bound) or
 | 
			
		||||
                (left_bound <= x2 <= right_bound and top_bound <= y2 <= bottom_bound)):
 | 
			
		||||
                # 计算线的中点y坐标
 | 
			
		||||
                mid_y = (y1 + y2) / 2
 | 
			
		||||
                line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
 | 
			
		||||
                # 保存线段、其y坐标和长度
 | 
			
		||||
                horizontal_lines.append((line[0], mid_y, slope, line_length))
 | 
			
		||||
                
 | 
			
		||||
                # 过滤掉短线段和太靠近图像上部的线
 | 
			
		||||
                if line_length >= min_line_length and mid_y >= valid_y_range[0]:
 | 
			
		||||
                    # 计算线段在图像中的位置得分(越靠近底部得分越高)
 | 
			
		||||
                    position_score = min(1.0, (mid_y - valid_y_range[0]) / (valid_y_range[1] - valid_y_range[0]))
 | 
			
		||||
                    
 | 
			
		||||
                    # 计算长度得分(越长越好)
 | 
			
		||||
                    length_score = min(1.0, line_length / (width * 0.5))
 | 
			
		||||
                    
 | 
			
		||||
                    # 计算斜率得分(越水平越好)
 | 
			
		||||
                    slope_score = max(0.0, 1.0 - abs(slope) / max_slope)
 | 
			
		||||
                    
 | 
			
		||||
                    # 计算线段位于图像中央的程度
 | 
			
		||||
                    mid_x = (x1 + x2) / 2
 | 
			
		||||
                    center_score = max(0.0, 1.0 - abs(mid_x - center_x) / (width * 0.3))
 | 
			
		||||
                    
 | 
			
		||||
                    # 计算综合得分
 | 
			
		||||
                    quality_score = position_score * 0.4 + length_score * 0.3 + slope_score * 0.2 + center_score * 0.1
 | 
			
		||||
                    
 | 
			
		||||
                    # 保存线段、其y坐标、斜率、长度和质量得分
 | 
			
		||||
                    horizontal_lines.append((line[0], mid_y, slope, line_length, quality_score))
 | 
			
		||||
    
 | 
			
		||||
    if not horizontal_lines:
 | 
			
		||||
        if observe:
 | 
			
		||||
            error("未检测到水平线", "失败")
 | 
			
		||||
            error("未检测到合格的水平线", "失败")
 | 
			
		||||
        return None, None
 | 
			
		||||
    
 | 
			
		||||
    if observe:
 | 
			
		||||
        debug(f"步骤6: 找到 {len(horizontal_lines)} 条水平线", "处理")
 | 
			
		||||
        h_lines_img = img.copy()
 | 
			
		||||
        for line_info in horizontal_lines:
 | 
			
		||||
            line, _, slope, _ = line_info
 | 
			
		||||
            line, _, slope, _, score = line_info
 | 
			
		||||
            x1, y1, x2, y2 = line
 | 
			
		||||
            cv2.line(h_lines_img, (x1, y1), (x2, y2), (0, 255, 255), 2)
 | 
			
		||||
            # 显示斜率
 | 
			
		||||
            cv2.putText(h_lines_img, f"{slope:.2f}", ((x1+x2)//2, (y1+y2)//2), 
 | 
			
		||||
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
 | 
			
		||||
            # 根据得分调整线的颜色,得分越高越绿
 | 
			
		||||
            color = (int(255 * (1-score)), int(255 * score), 0)
 | 
			
		||||
            cv2.line(h_lines_img, (x1, y1), (x2, y2), color, 2)
 | 
			
		||||
            # 显示斜率和得分
 | 
			
		||||
            cv2.putText(h_lines_img, f"{slope:.2f}|{score:.2f}", ((x1+x2)//2, (y1+y2)//2), 
 | 
			
		||||
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
 | 
			
		||||
        cv2.imshow("水平线", h_lines_img)
 | 
			
		||||
        cv2.waitKey(delay)
 | 
			
		||||
    
 | 
			
		||||
    # 将水平线分为上边缘线和下边缘线(按y坐标排序)
 | 
			
		||||
    bottom_line = None
 | 
			
		||||
    top_line = None
 | 
			
		||||
    is_truncated = False  # 标记下方线是否被截断
 | 
			
		||||
    # 根据质量得分排序水平线
 | 
			
		||||
    horizontal_lines.sort(key=lambda x: x[4], reverse=True)
 | 
			
		||||
    
 | 
			
		||||
    if len(horizontal_lines) > 1:
 | 
			
		||||
        # 按y坐标排序 (从大到小,底部的线排在前面)
 | 
			
		||||
        horizontal_lines.sort(key=lambda x: x[1], reverse=True)
 | 
			
		||||
        
 | 
			
		||||
        # 提取最底部和次底部的线段
 | 
			
		||||
        bottom_line = horizontal_lines[0]
 | 
			
		||||
        
 | 
			
		||||
        # 检查是否有明显的上下边缘
 | 
			
		||||
        y_coords = [line[1] for line in horizontal_lines]
 | 
			
		||||
        y_diffs = [y_coords[i] - y_coords[i+1] for i in range(len(y_coords)-1)]
 | 
			
		||||
        
 | 
			
		||||
        if len(y_diffs) > 0 and max(y_diffs) > height * 0.05:  # 如果有明显的高度差
 | 
			
		||||
            # 找到高度差最大的位置
 | 
			
		||||
            split_idx = y_diffs.index(max(y_diffs))
 | 
			
		||||
            
 | 
			
		||||
            # 分别获取下边缘线和上边缘线
 | 
			
		||||
            bottom_line = horizontal_lines[0]  # 最底部的线
 | 
			
		||||
            top_line = horizontal_lines[split_idx+1]  # 上边缘线
 | 
			
		||||
            
 | 
			
		||||
            # 检查上下两条线是否平行 - 计算斜率差异
 | 
			
		||||
            bottom_slope = bottom_line[2]
 | 
			
		||||
            top_slope = top_line[2]
 | 
			
		||||
            slope_diff = abs(bottom_slope - top_slope)
 | 
			
		||||
            
 | 
			
		||||
            # 计算两线的交点(如果存在)
 | 
			
		||||
            bottom_x1, bottom_y1, bottom_x2, bottom_y2 = bottom_line[0]
 | 
			
		||||
            top_x1, top_y1, top_x2, top_y2 = top_line[0]
 | 
			
		||||
            
 | 
			
		||||
            # 根据斜率差异判断是否平行
 | 
			
		||||
            # 如果斜率差异很小,认为基本平行
 | 
			
		||||
            if slope_diff > 0.05:  # 斜率差异超过阈值
 | 
			
		||||
                # 计算两条线延长后的交点
 | 
			
		||||
                # 线段方程: y = mx + b
 | 
			
		||||
                # 计算两条线的截距b
 | 
			
		||||
                bottom_b = bottom_y1 - bottom_slope * bottom_x1
 | 
			
		||||
                top_b = top_y1 - top_slope * top_x1
 | 
			
		||||
                
 | 
			
		||||
                # 检查交点是否在图像范围内或者附近
 | 
			
		||||
                # 求解 y = m1*x + b1 = m2*x + b2
 | 
			
		||||
                if abs(bottom_slope - top_slope) > 1e-6:  # 避免除以接近0的值
 | 
			
		||||
                    intersection_x = (top_b - bottom_b) / (bottom_slope - top_slope)
 | 
			
		||||
                    intersection_y = bottom_slope * intersection_x + bottom_b
 | 
			
		||||
                    
 | 
			
		||||
                    # 判断交点是否在图像宽度的2倍范围内
 | 
			
		||||
                    if -width <= intersection_x <= width * 2:
 | 
			
		||||
                        is_truncated = True
 | 
			
		||||
                        if observe:
 | 
			
		||||
                            debug(f"检测到上下边缘线不平行,交点: ({intersection_x:.1f}, {intersection_y:.1f})", "分析")
 | 
			
		||||
                            debug("判断下方线被截断", "分析")
 | 
			
		||||
                            
 | 
			
		||||
                            # 显示上下边缘线及其延长线和交点
 | 
			
		||||
                            intersect_img = img.copy()
 | 
			
		||||
                            # 画原始线段
 | 
			
		||||
                            cv2.line(intersect_img, (bottom_x1, bottom_y1), (bottom_x2, bottom_y2), (0, 255, 0), 2)
 | 
			
		||||
                            cv2.line(intersect_img, (top_x1, top_y1), (top_x2, top_y2), (255, 0, 255), 2)
 | 
			
		||||
                            
 | 
			
		||||
                            # 延长线段以显示交点
 | 
			
		||||
                            ext_left_x = max(0, int(intersection_x - width/2))
 | 
			
		||||
                            ext_right_x = min(width-1, int(intersection_x + width/2))
 | 
			
		||||
                            
 | 
			
		||||
                            # 计算延长线上的点
 | 
			
		||||
                            bottom_ext_left_y = int(bottom_slope * ext_left_x + bottom_b)
 | 
			
		||||
                            bottom_ext_right_y = int(bottom_slope * ext_right_x + bottom_b)
 | 
			
		||||
                            top_ext_left_y = int(top_slope * ext_left_x + top_b)
 | 
			
		||||
                            top_ext_right_y = int(top_slope * ext_right_x + top_b)
 | 
			
		||||
                            
 | 
			
		||||
                            # 绘制延长线
 | 
			
		||||
                            cv2.line(intersect_img, (ext_left_x, bottom_ext_left_y), 
 | 
			
		||||
                                    (ext_right_x, bottom_ext_right_y), (0, 255, 0), 1, cv2.LINE_DASHED)
 | 
			
		||||
                            cv2.line(intersect_img, (ext_left_x, top_ext_left_y), 
 | 
			
		||||
                                    (ext_right_x, top_ext_right_y), (255, 0, 255), 1, cv2.LINE_DASHED)
 | 
			
		||||
                            
 | 
			
		||||
                            # 标记交点
 | 
			
		||||
                            if 0 <= intersection_x < width and 0 <= intersection_y < height:
 | 
			
		||||
                                cv2.circle(intersect_img, (int(intersection_x), int(intersection_y)), 
 | 
			
		||||
                                        10, (0, 0, 255), -1)
 | 
			
		||||
                            
 | 
			
		||||
                            cv2.imshow("上下边缘线交点分析", intersect_img)
 | 
			
		||||
                            cv2.waitKey(delay)
 | 
			
		||||
            
 | 
			
		||||
            # 如果检测到下方线被截断,使用上边缘线来估计实际的下边缘线
 | 
			
		||||
            if is_truncated and top_line is not None:
 | 
			
		||||
                if observe:
 | 
			
		||||
                    debug("使用上边缘估计真实的下边缘", "处理")
 | 
			
		||||
                
 | 
			
		||||
                # 获取赛道平均宽度(可以是预先测量的固定值,或根据未截断部分测量)
 | 
			
		||||
                # 这里假设赛道宽度是固定的,可以根据实际情况调整
 | 
			
		||||
                track_width_pixels = height * 0.15  # 假设赛道宽度是图像高度的15%
 | 
			
		||||
                
 | 
			
		||||
                # 计算一个修正后的底部线段,方向与上边缘线平行,但位置下移
 | 
			
		||||
                corrected_bottom_slope = top_slope  # 使用上边缘的斜率
 | 
			
		||||
                
 | 
			
		||||
                # 计算上边缘线的方程: y = mx + b
 | 
			
		||||
                top_b = top_y1 - top_slope * top_x1
 | 
			
		||||
                
 | 
			
		||||
                # 计算修正后的下边缘线的截距,使其下移track_width_pixels距离
 | 
			
		||||
                # 由于是在图像坐标系,y轴向下,所以是加法
 | 
			
		||||
                corrected_bottom_b = top_b + track_width_pixels
 | 
			
		||||
                
 | 
			
		||||
                # 计算修正后的下边缘线的两个端点
 | 
			
		||||
                corrected_bottom_x1 = left_bound
 | 
			
		||||
                corrected_bottom_y1 = int(corrected_bottom_slope * corrected_bottom_x1 + corrected_bottom_b)
 | 
			
		||||
                corrected_bottom_x2 = right_bound
 | 
			
		||||
                corrected_bottom_y2 = int(corrected_bottom_slope * corrected_bottom_x2 + corrected_bottom_b)
 | 
			
		||||
                
 | 
			
		||||
                # 创建修正后的底部线段
 | 
			
		||||
                corrected_bottom_line = (
 | 
			
		||||
                    [corrected_bottom_x1, corrected_bottom_y1, corrected_bottom_x2, corrected_bottom_y2],
 | 
			
		||||
                    (corrected_bottom_y1 + corrected_bottom_y2) / 2,  # mid_y
 | 
			
		||||
                    corrected_bottom_slope,
 | 
			
		||||
                    np.sqrt((corrected_bottom_x2-corrected_bottom_x1)**2 + (corrected_bottom_y2-corrected_bottom_y1)**2)  # length
 | 
			
		||||
                )
 | 
			
		||||
                
 | 
			
		||||
                if observe:
 | 
			
		||||
                    # 显示修正后的线段
 | 
			
		||||
                    corrected_img = img.copy()
 | 
			
		||||
                    # 原始线段
 | 
			
		||||
                    cv2.line(corrected_img, (bottom_x1, bottom_y1), (bottom_x2, bottom_y2), (0, 255, 0), 2)
 | 
			
		||||
                    cv2.line(corrected_img, (top_x1, top_y1), (top_x2, top_y2), (255, 0, 255), 2)
 | 
			
		||||
                    # 修正后的线段
 | 
			
		||||
                    cv2.line(corrected_img, (corrected_bottom_x1, corrected_bottom_y1), 
 | 
			
		||||
                           (corrected_bottom_x2, corrected_bottom_y2), (0, 0, 255), 2)
 | 
			
		||||
                    
 | 
			
		||||
                    cv2.putText(corrected_img, "截断的底边", (bottom_x1, bottom_y1 - 10), 
 | 
			
		||||
                              cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
 | 
			
		||||
                    cv2.putText(corrected_img, "上边缘", (top_x1, top_y1 - 10), 
 | 
			
		||||
                              cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)
 | 
			
		||||
                    cv2.putText(corrected_img, "修正后的底边", (corrected_bottom_x1, corrected_bottom_y1 - 10), 
 | 
			
		||||
                              cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
 | 
			
		||||
                    
 | 
			
		||||
                    cv2.imshow("修正后的边缘线", corrected_img)
 | 
			
		||||
                    cv2.waitKey(delay)
 | 
			
		||||
                
 | 
			
		||||
                # 使用修正后的底部线作为选定的线
 | 
			
		||||
                bottom_line = corrected_bottom_line
 | 
			
		||||
    else:
 | 
			
		||||
        # 只有一条水平线
 | 
			
		||||
        bottom_line = horizontal_lines[0]
 | 
			
		||||
    
 | 
			
		||||
    # 使用底部线段作为最终选择
 | 
			
		||||
    selected_line = bottom_line[0]
 | 
			
		||||
    selected_slope = bottom_line[2]
 | 
			
		||||
    # 取质量最高的线段作为最终选择
 | 
			
		||||
    selected_line = horizontal_lines[0][0]
 | 
			
		||||
    selected_slope = horizontal_lines[0][2]
 | 
			
		||||
    selected_score = horizontal_lines[0][4]
 | 
			
		||||
    
 | 
			
		||||
    # 提取线段端点
 | 
			
		||||
    x1, y1, x2, y2 = selected_line
 | 
			
		||||
@ -338,6 +224,59 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
    else:
 | 
			
		||||
        bottom_edge_point = (x2, y2)
 | 
			
		||||
    
 | 
			
		||||
    # 如果得分过低,可能是错误识别,尝试使用边缘点拟合
 | 
			
		||||
    if selected_score < 0.4 and len(bottom_points) >= 5:
 | 
			
		||||
        if observe:
 | 
			
		||||
            debug(f"线段质量得分过低: {selected_score:.2f},尝试使用边缘点拟合", "处理")
 | 
			
		||||
        
 | 
			
		||||
        # 筛选下半部分的点
 | 
			
		||||
        valid_bottom_points = [p for p in bottom_points if p[1] >= valid_y_range[0]]
 | 
			
		||||
        
 | 
			
		||||
        if len(valid_bottom_points) >= 5:
 | 
			
		||||
            # 使用RANSAC拟合直线以去除异常值
 | 
			
		||||
            x_points = np.array([p[0] for p in valid_bottom_points]).reshape(-1, 1)
 | 
			
		||||
            y_points = np.array([p[1] for p in valid_bottom_points])
 | 
			
		||||
            
 | 
			
		||||
            ransac = linear_model.RANSACRegressor(residual_threshold=5.0)
 | 
			
		||||
            ransac.fit(x_points, y_points)
 | 
			
		||||
            
 | 
			
		||||
            # 获取拟合参数
 | 
			
		||||
            fitted_slope = ransac.estimator_.coef_[0]
 | 
			
		||||
            intercept = ransac.estimator_.intercept_
 | 
			
		||||
            
 | 
			
		||||
            # 检查斜率是否在合理范围内
 | 
			
		||||
            if abs(fitted_slope) < max_slope:
 | 
			
		||||
                # 计算拟合线的inliers比例
 | 
			
		||||
                inlier_mask = ransac.inlier_mask_
 | 
			
		||||
                inlier_ratio = sum(inlier_mask) / len(inlier_mask)
 | 
			
		||||
                
 | 
			
		||||
                # 如果有足够的内点,使用拟合的直线
 | 
			
		||||
                if inlier_ratio > 0.5:
 | 
			
		||||
                    # 使用拟合的直线参数计算线段端点
 | 
			
		||||
                    x1 = left_bound
 | 
			
		||||
                    y1 = int(fitted_slope * x1 + intercept)
 | 
			
		||||
                    x2 = right_bound
 | 
			
		||||
                    y2 = int(fitted_slope * x2 + intercept)
 | 
			
		||||
                    
 | 
			
		||||
                    selected_slope = fitted_slope
 | 
			
		||||
                    selected_line = [x1, y1, x2, y2]
 | 
			
		||||
                    
 | 
			
		||||
                    # 重新计算边缘点
 | 
			
		||||
                    if y1 > y2:
 | 
			
		||||
                        bottom_edge_point = (x1, y1)
 | 
			
		||||
                    else:
 | 
			
		||||
                        bottom_edge_point = (x2, y2)
 | 
			
		||||
                    
 | 
			
		||||
                    if observe:
 | 
			
		||||
                        debug(f"使用拟合直线,斜率: {fitted_slope:.4f}, 内点比例: {inlier_ratio:.2f}", "处理")
 | 
			
		||||
                        fitted_line_img = img.copy()
 | 
			
		||||
                        cv2.line(fitted_line_img, (x1, y1), (x2, y2), (0, 255, 255), 2)
 | 
			
		||||
                        for i, point in enumerate(valid_bottom_points):
 | 
			
		||||
                            color = (0, 255, 0) if inlier_mask[i] else (0, 0, 255)
 | 
			
		||||
                            cv2.circle(fitted_line_img, point, 3, color, -1)
 | 
			
		||||
                        cv2.imshow("拟合线和内点", fitted_line_img)
 | 
			
		||||
                        cv2.waitKey(delay)
 | 
			
		||||
    
 | 
			
		||||
    # 获取线上的更多点
 | 
			
		||||
    selected_points = []
 | 
			
		||||
    step = 5  # 每5个像素取一个点
 | 
			
		||||
@ -346,22 +285,34 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
        if top_bound <= y <= bottom_bound:
 | 
			
		||||
            selected_points.append((x, y))
 | 
			
		||||
    
 | 
			
		||||
    if observe:
 | 
			
		||||
        debug(f"步骤7: 找到边缘点 {bottom_edge_point}", "检测")
 | 
			
		||||
        edge_img = img.copy()
 | 
			
		||||
        # 画线
 | 
			
		||||
        cv2.line(edge_img, (x1, y1), (x2, y2), (0, 255, 0), 2)
 | 
			
		||||
        # 绘制所有点
 | 
			
		||||
        for point in selected_points:
 | 
			
		||||
            cv2.circle(edge_img, point, 3, (255, 0, 0), -1)
 | 
			
		||||
        # 标记边缘点
 | 
			
		||||
        cv2.circle(edge_img, bottom_edge_point, 10, (0, 0, 255), -1)
 | 
			
		||||
        cv2.imshow("选定的横向线和边缘点", edge_img)
 | 
			
		||||
        cv2.waitKey(delay)
 | 
			
		||||
    # 对结果进行合理性检查
 | 
			
		||||
    valid_result = True
 | 
			
		||||
    reason = ""
 | 
			
		||||
    
 | 
			
		||||
    # 检查边缘点是否在有效范围内
 | 
			
		||||
    if not (valid_y_range[0] <= bottom_edge_point[1] <= valid_y_range[1]):
 | 
			
		||||
        valid_result = False
 | 
			
		||||
        reason += "边缘点y坐标超出有效范围; "
 | 
			
		||||
    
 | 
			
		||||
    # 检查线段长度
 | 
			
		||||
    line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
 | 
			
		||||
    if line_length < min_line_length:
 | 
			
		||||
        valid_result = False
 | 
			
		||||
        reason += "线段长度不足; "
 | 
			
		||||
    
 | 
			
		||||
    # 检查是否有足够的点
 | 
			
		||||
    if len(selected_points) < 5:
 | 
			
		||||
        valid_result = False
 | 
			
		||||
        reason += "选定点数量不足; "
 | 
			
		||||
    
 | 
			
		||||
    # 计算这个点到中线的距离
 | 
			
		||||
    distance_to_center = bottom_edge_point[0] - center_x
 | 
			
		||||
    
 | 
			
		||||
    # 检查到中心的距离是否合理
 | 
			
		||||
    if abs(distance_to_center) > width * 0.8:
 | 
			
		||||
        valid_result = False
 | 
			
		||||
        reason += "到中心距离过大; "
 | 
			
		||||
    
 | 
			
		||||
    # 计算中线与检测到的横向线的交点
 | 
			
		||||
    # 横向线方程: y = slope * (x - x1) + y1
 | 
			
		||||
    # 中线方程: x = center_x
 | 
			
		||||
@ -370,14 +321,24 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
    intersection_y = selected_slope * (center_x - x1) + y1
 | 
			
		||||
    intersection_point = (int(intersection_x), int(intersection_y))
 | 
			
		||||
    
 | 
			
		||||
    # 检查交点的y坐标是否在有效范围内
 | 
			
		||||
    if not (valid_y_range[0] <= intersection_y <= valid_y_range[1]):
 | 
			
		||||
        valid_result = False
 | 
			
		||||
        reason += "交点y坐标超出有效范围; "
 | 
			
		||||
    
 | 
			
		||||
    # 计算交点到图像底部的距离(以像素为单位)
 | 
			
		||||
    distance_to_bottom = height - intersection_y
 | 
			
		||||
    
 | 
			
		||||
    # 如果结果无效,可能需要返回失败
 | 
			
		||||
    if not valid_result and observe:
 | 
			
		||||
        warning(f"检测结果不合理: {reason}", "警告")
 | 
			
		||||
    
 | 
			
		||||
    result_img = None
 | 
			
		||||
    if observe or save_log:
 | 
			
		||||
        slope_img = img.copy()
 | 
			
		||||
        # 画出检测到的线
 | 
			
		||||
        cv2.line(slope_img, (x1, y1), (x2, y2), (0, 255, 0), 2)
 | 
			
		||||
        line_color = (0, 255, 0) if valid_result else (0, 0, 255)
 | 
			
		||||
        cv2.line(slope_img, (x1, y1), (x2, y2), line_color, 2)
 | 
			
		||||
        # 标记边缘点
 | 
			
		||||
        cv2.circle(slope_img, bottom_edge_point, 10, (0, 0, 255), -1)
 | 
			
		||||
        # 画出中线
 | 
			
		||||
@ -389,16 +350,19 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
        cv2.line(slope_img, intersection_point, (intersection_x, height), (255, 255, 0), 2)
 | 
			
		||||
        
 | 
			
		||||
        cv2.putText(slope_img, f"Slope: {selected_slope:.4f}", (10, 30), 
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, line_color, 2)
 | 
			
		||||
        cv2.putText(slope_img, f"Distance to center: {distance_to_center}px", (10, 70), 
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, line_color, 2)
 | 
			
		||||
        cv2.putText(slope_img, f"Distance to bottom: {distance_to_bottom:.1f}px", (10, 110), 
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, line_color, 2)
 | 
			
		||||
        cv2.putText(slope_img, f"中线交点: ({intersection_point[0]}, {intersection_point[1]})", (10, 150), 
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
 | 
			
		||||
        if is_truncated:
 | 
			
		||||
            cv2.putText(slope_img, "下方线被截断(已修正)", (10, 190), 
 | 
			
		||||
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
 | 
			
		||||
                    cv2.FONT_HERSHEY_SIMPLEX, 1, line_color, 2)
 | 
			
		||||
        cv2.putText(slope_img, f"质量得分: {selected_score:.2f}", (10, 190),
 | 
			
		||||
                   cv2.FONT_HERSHEY_SIMPLEX, 1, line_color, 2)
 | 
			
		||||
        
 | 
			
		||||
        if not valid_result:
 | 
			
		||||
            cv2.putText(slope_img, f"警告: {reason}", (10, 230), 
 | 
			
		||||
                        cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
 | 
			
		||||
        
 | 
			
		||||
        if observe:
 | 
			
		||||
            debug("显示边缘斜率和中线交点", "显示")
 | 
			
		||||
@ -424,10 +388,16 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
            "slope": selected_slope,
 | 
			
		||||
            "distance_to_bottom": distance_to_bottom,
 | 
			
		||||
            "intersection_point": intersection_point,
 | 
			
		||||
            "is_truncated": is_truncated
 | 
			
		||||
            "score": selected_score,
 | 
			
		||||
            "valid": valid_result,
 | 
			
		||||
            "reason": reason if not valid_result else ""
 | 
			
		||||
        }
 | 
			
		||||
        info(f"横向边缘检测结果: {log_info}", "日志")
 | 
			
		||||
    
 | 
			
		||||
    # 如果结果无效,可能需要返回失败
 | 
			
		||||
    if not valid_result:
 | 
			
		||||
        return None, None
 | 
			
		||||
    
 | 
			
		||||
    # 创建边缘信息字典
 | 
			
		||||
    edge_info = {
 | 
			
		||||
        "x": bottom_edge_point[0],
 | 
			
		||||
@ -438,7 +408,7 @@ def detect_horizontal_track_edge(image, observe=False, delay=1000, save_log=True
 | 
			
		||||
        "points_count": len(selected_points),  # 该组中点的数量
 | 
			
		||||
        "intersection_point": intersection_point,  # 中线与横向线的交点
 | 
			
		||||
        "distance_to_bottom": distance_to_bottom,  # 交点到图像底部的距离
 | 
			
		||||
        "is_truncated": is_truncated,  # 下方线是否被截断并修正
 | 
			
		||||
        "score": selected_score,  # 线段质量得分
 | 
			
		||||
        # "points": selected_points  # 添加选定的点组
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user