Merge branch 'main-v2' of ssh://120.27.199.238:222/Havoc420mac/mi-task into main-v2
@ -116,4 +116,91 @@ def run_task_1(ctrl, msg, time_sleep=5000):
 | 
			
		||||
    # add
 | 
			
		||||
    go_straight(ctrl, msg, distance=0.3, observe=observe)
 | 
			
		||||
 | 
			
		||||
    # section
 | 
			
		||||
    section('任务1-7:90度转弯', "旋转")
 | 
			
		||||
    radius = res['radius'] * 2 + 0.1
 | 
			
		||||
    info(f"任务1-7: 转弯半径: {radius}", "信息")
 | 
			
		||||
    turn_success, res = arc_turn_around_hori_line(
 | 
			
		||||
        ctrl=ctrl,
 | 
			
		||||
        msg=msg,
 | 
			
		||||
        radius=radius,
 | 
			
		||||
        angle_deg=85 if direction else -85,
 | 
			
		||||
        #
 | 
			
		||||
        pass_align=True,
 | 
			
		||||
        observe=observe,
 | 
			
		||||
        no_end_reset=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    section('任务1-8:直线移动', "移动")
 | 
			
		||||
    move_to_hori_line(ctrl, msg, target_distance=0.3, observe=observe)
 | 
			
		||||
 | 
			
		||||
    section('任务1-9:90度旋转', "旋转")
 | 
			
		||||
    turn_degree_v2(ctrl, msg, degree=0, absolute=True, precision=True)
 | 
			
		||||
 | 
			
		||||
    section('任务1-10: y校准,准备 task-2', "移动")
 | 
			
		||||
    # TODO
 | 
			
		||||
    
 | 
			
		||||
    success("任务1完成", "完成")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run_task_1_back(ctrl, msg, time_sleep=5000):
 | 
			
		||||
    section('任务1-11: 返回', "移动")
 | 
			
		||||
    go_straight(ctrl, msg, distance=0.2, observe=observe)
 | 
			
		||||
    turn_degree_v2(ctrl, msg, -90, absolute=True)  # 不确定 odo 效果如何;
 | 
			
		||||
 | 
			
		||||
    section('任务1-11: 直线移动', "移动")
 | 
			
		||||
    move_to_hori_line(ctrl, msg, target_distance=0.2, observe=observe)
 | 
			
		||||
 | 
			
		||||
    section('任务1-12: 180度旋转', "旋转")
 | 
			
		||||
    turn_success, res = arc_turn_around_hori_line(
 | 
			
		||||
        ctrl=ctrl,
 | 
			
		||||
        msg=msg,
 | 
			
		||||
        angle_deg=170 if direction else -170,
 | 
			
		||||
        target_distance=0.6,
 | 
			
		||||
        min_radius=0.3,
 | 
			
		||||
        max_radius=0.4,
 | 
			
		||||
        pass_align=True,
 | 
			
		||||
        observe=observe,
 | 
			
		||||
        no_end_reset=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    turn_degree_v2(ctrl, msg, degree=90, absolute=True)
 | 
			
		||||
 | 
			
		||||
    section('任务1-13: 直线移动', "移动")
 | 
			
		||||
    move_distance = 0.5
 | 
			
		||||
    go_straight(ctrl, msg, distance=move_distance, observe=observe)
 | 
			
		||||
 | 
			
		||||
    section('任务1-14: 模拟装货', "停止")
 | 
			
		||||
    info('机器人躺下,模拟装货过程', "信息")
 | 
			
		||||
    start_time = time.time()
 | 
			
		||||
    ctrl.base_msg.lie_down(wait_time=time_sleep)
 | 
			
		||||
    elapsed = time.time() - start_time
 | 
			
		||||
    timing("装货过程", elapsed)
 | 
			
		||||
 | 
			
		||||
    section('任务1-15: 站起来', "移动")
 | 
			
		||||
    ctrl.base_msg.stand_up()
 | 
			
		||||
 | 
			
		||||
    section('任务1-16: 返回', "移动")
 | 
			
		||||
    go_straight(ctrl, msg, distance=-(move_distance + res['radius']), observe=observe)
 | 
			
		||||
 | 
			
		||||
    turn_degree_v2(ctrl, msg, degree=179, absolute=True)
 | 
			
		||||
 | 
			
		||||
    section('任务1-17: 90度转弯', "旋转")
 | 
			
		||||
    turn_success, res = arc_turn_around_hori_line(
 | 
			
		||||
        ctrl=ctrl,
 | 
			
		||||
        msg=msg,
 | 
			
		||||
        angle_deg=-85 if direction else 85,
 | 
			
		||||
        radius=res['radius'] * 2,
 | 
			
		||||
        pass_align=True,
 | 
			
		||||
        observe=observe,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    section('任务1-18: 直线移动', "移动")
 | 
			
		||||
    move_to_hori_line(ctrl, msg, target_distance=0.4, observe=observe)
 | 
			
		||||
 | 
			
		||||
    section('任务1-19: 90度旋转', "旋转")
 | 
			
		||||
    turn_degree_v2(ctrl, msg, degree=0, absolute=True)
 | 
			
		||||
 | 
			
		||||
    go_straight(ctrl, msg, distance=-1.3, observe=observe)
 | 
			
		||||
    # go_to_xy(ctrl, msg, target_x=-0.2, target_y=0, observe=observe)  # TEST
 | 
			
		||||
 | 
			
		||||
    success("任务1-back完成", "完成")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								test/text-image/imgs/1_process_1_原始图片.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 164 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								test/text-image/imgs/1_process_2_HSV-V通道.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 241 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								test/text-image/imgs/1_process_3_低亮度区域掩码.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 78 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								test/text-image/imgs/1_process_4_轮廓检测.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 171 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								test/text-image/imgs/1_process_5_最终结果.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 164 KiB  | 
| 
		 Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 164 KiB  | 
| 
		 Before Width: | Height: | Size: 180 KiB  | 
@ -1,3 +1,2 @@
 | 
			
		||||
opencv-python>=4.5.0
 | 
			
		||||
numpy>=1.19.0
 | 
			
		||||
pathlib
 | 
			
		||||
opencv-python
 | 
			
		||||
numpy
 | 
			
		||||
 | 
			
		||||
@ -1,89 +1,149 @@
 | 
			
		||||
import cv2
 | 
			
		||||
import numpy as np
 | 
			
		||||
import os
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
def preprocess_image(image):
 | 
			
		||||
    """
 | 
			
		||||
    预处理图像:转换为HSV色彩空间,检测白色区域
 | 
			
		||||
    预处理图像:转换为HSV色彩空间,提取V通道(明度通道)中的低亮度区域
 | 
			
		||||
    """
 | 
			
		||||
    # 转换为HSV色彩空间
 | 
			
		||||
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
 | 
			
		||||
    
 | 
			
		||||
    # 定义白色的HSV范围 - 放宽范围
 | 
			
		||||
    # 白色在HSV中:饱和度低,明度高
 | 
			
		||||
    # 原来的范围:lower_white = np.array([0, 0, 200]), upper_white = np.array([180, 30, 255])
 | 
			
		||||
    # 放宽后的范围:
 | 
			
		||||
    lower_white = np.array([0, 0, 150])    # 降低明度下限,从200降到150
 | 
			
		||||
    upper_white = np.array([180, 60, 255]) # 提高饱和度上限,从30提高到60
 | 
			
		||||
    # 提取V通道(明度通道)
 | 
			
		||||
    v_channel = hsv[:, :, 2]
 | 
			
		||||
    
 | 
			
		||||
    # 创建白色掩码
 | 
			
		||||
    white_mask = cv2.inRange(hsv, lower_white, upper_white)
 | 
			
		||||
    # 对V通道进行二值化,提取低亮度区域(蓝色部分)
 | 
			
		||||
    # 使用较低的阈值来提取暗色区域
 | 
			
		||||
    _, binary = cv2.threshold(v_channel, 120, 255, cv2.THRESH_BINARY_INV)
 | 
			
		||||
    
 | 
			
		||||
    # 形态学操作:开运算去除小噪点,闭运算填充小孔
 | 
			
		||||
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
 | 
			
		||||
    cleaned = cv2.morphologyEx(white_mask, cv2.MORPH_OPEN, kernel)
 | 
			
		||||
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
 | 
			
		||||
    cleaned = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
 | 
			
		||||
    cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, kernel)
 | 
			
		||||
    
 | 
			
		||||
    return cleaned
 | 
			
		||||
    return cleaned, v_channel
 | 
			
		||||
 | 
			
		||||
def find_white_rectangles(binary_image):
 | 
			
		||||
def find_text_regions(binary_image):
 | 
			
		||||
    """
 | 
			
		||||
    查找白色矩形区域
 | 
			
		||||
    查找可能的文字区域
 | 
			
		||||
    """
 | 
			
		||||
    contours, _ = cv2.findContours(
 | 
			
		||||
        binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
 | 
			
		||||
    )
 | 
			
		||||
    
 | 
			
		||||
    # 筛选合适的矩形轮廓
 | 
			
		||||
    valid_rectangles = []
 | 
			
		||||
    # 筛选合适的文字区域轮廓
 | 
			
		||||
    valid_text_regions = []
 | 
			
		||||
    for contour in contours:
 | 
			
		||||
        area = cv2.contourArea(contour)
 | 
			
		||||
        if area > 200:  # 过滤太小的区域,从500降低到200
 | 
			
		||||
        if area > 100:  # 过滤太小的区域
 | 
			
		||||
            # 计算轮廓的边界矩形
 | 
			
		||||
            x, y, w, h = cv2.boundingRect(contour)
 | 
			
		||||
            
 | 
			
		||||
            # 计算轮廓的近似多边形
 | 
			
		||||
            epsilon = 0.02 * cv2.arcLength(contour, True)
 | 
			
		||||
            approx = cv2.approxPolyDP(contour, epsilon, True)
 | 
			
		||||
            # 计算宽高比
 | 
			
		||||
            aspect_ratio = w / h
 | 
			
		||||
            
 | 
			
		||||
            # 检查是否为四边形(矩形)
 | 
			
		||||
            if len(approx) == 4:
 | 
			
		||||
                # 计算宽高比
 | 
			
		||||
                aspect_ratio = w / h
 | 
			
		||||
                # 矩形应该有合理的宽高比(不是太细长)
 | 
			
		||||
                if 0.3 < aspect_ratio < 3.0:
 | 
			
		||||
                    valid_rectangles.append((contour, (x, y, w, h), approx))
 | 
			
		||||
            # 文字区域通常有合理的宽高比
 | 
			
		||||
            if 0.1 < aspect_ratio < 10.0:
 | 
			
		||||
                valid_text_regions.append((contour, (x, y, w, h)))
 | 
			
		||||
    
 | 
			
		||||
    return valid_rectangles
 | 
			
		||||
    return valid_text_regions
 | 
			
		||||
 | 
			
		||||
def analyze_white_region(roi, original_roi):
 | 
			
		||||
def analyze_text_region(roi, original_roi):
 | 
			
		||||
    """
 | 
			
		||||
    分析白色区域的特征
 | 
			
		||||
    分析文字区域的特征
 | 
			
		||||
    """
 | 
			
		||||
    # 计算白色像素比例
 | 
			
		||||
    # 计算黑色像素比例
 | 
			
		||||
    total_pixels = roi.shape[0] * roi.shape[1]
 | 
			
		||||
    white_pixels = np.sum(roi == 255)
 | 
			
		||||
    white_ratio = white_pixels / total_pixels
 | 
			
		||||
    black_pixels = np.sum(roi == 255)
 | 
			
		||||
    black_ratio = black_pixels / total_pixels
 | 
			
		||||
    
 | 
			
		||||
    # 计算区域的形状特征
 | 
			
		||||
    height, width = roi.shape
 | 
			
		||||
    aspect_ratio = width / height
 | 
			
		||||
    
 | 
			
		||||
    # 计算边缘强度(白色区域应该有清晰的边缘)
 | 
			
		||||
    # 计算边缘强度
 | 
			
		||||
    edges = cv2.Canny(original_roi, 50, 150)
 | 
			
		||||
    edge_density = np.sum(edges > 0) / total_pixels
 | 
			
		||||
    
 | 
			
		||||
    return {
 | 
			
		||||
        'white_ratio': white_ratio,
 | 
			
		||||
        'black_ratio': black_ratio,
 | 
			
		||||
        'aspect_ratio': aspect_ratio,
 | 
			
		||||
        'edge_density': edge_density,
 | 
			
		||||
        'area': total_pixels
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
def detect_white_rectangles_in_image(image_path):
 | 
			
		||||
def classify_digit_1_or_2(roi):
 | 
			
		||||
    """
 | 
			
		||||
    检测图片中的白色矩形区域
 | 
			
		||||
    使用OpenCV基本方法判断是数字1还是2
 | 
			
		||||
    """
 | 
			
		||||
    # 调整ROI大小到统一尺寸进行分析
 | 
			
		||||
    roi_resized = cv2.resize(roi, (20, 20))
 | 
			
		||||
    
 | 
			
		||||
    # 计算像素密度特征
 | 
			
		||||
    total_pixels = roi_resized.shape[0] * roi_resized.shape[1]
 | 
			
		||||
    black_pixels = np.sum(roi_resized == 255)
 | 
			
		||||
    density = black_pixels / total_pixels
 | 
			
		||||
    
 | 
			
		||||
    # 计算宽高比
 | 
			
		||||
    aspect_ratio = roi_resized.shape[1] / roi_resized.shape[0]
 | 
			
		||||
    
 | 
			
		||||
    # 计算水平投影(每行的黑色像素数)
 | 
			
		||||
    horizontal_projection = np.sum(roi_resized == 255, axis=1)
 | 
			
		||||
    
 | 
			
		||||
    # 计算垂直投影(每列的黑色像素数)
 | 
			
		||||
    vertical_projection = np.sum(roi_resized == 255, axis=0)
 | 
			
		||||
    
 | 
			
		||||
    # 计算中心区域的像素分布
 | 
			
		||||
    center_region = roi_resized[5:15, 5:15]
 | 
			
		||||
    center_density = np.sum(center_region == 255) / (10 * 10)
 | 
			
		||||
    
 | 
			
		||||
    # 计算垂直投影的方差(数字1方差较小,数字2方差较大)
 | 
			
		||||
    vertical_variance = np.var(vertical_projection)
 | 
			
		||||
    
 | 
			
		||||
    # 计算水平投影的方差
 | 
			
		||||
    horizontal_variance = np.var(horizontal_projection)
 | 
			
		||||
    
 | 
			
		||||
    # 基于多个特征的综合判断
 | 
			
		||||
    digit1_score = 0
 | 
			
		||||
    digit2_score = 0
 | 
			
		||||
    
 | 
			
		||||
    # 数字1的判断条件
 | 
			
		||||
    if vertical_variance < 15:  # 垂直投影方差小
 | 
			
		||||
        digit1_score += 2
 | 
			
		||||
    if center_density < 0.3:  # 中心区域密度较低
 | 
			
		||||
        digit1_score += 1
 | 
			
		||||
    if density < 0.4:  # 整体密度较低
 | 
			
		||||
        digit1_score += 1
 | 
			
		||||
    if aspect_ratio < 0.8:  # 数字1通常较细
 | 
			
		||||
        digit1_score += 1
 | 
			
		||||
    
 | 
			
		||||
    # 数字2的判断条件
 | 
			
		||||
    if vertical_variance > 15:  # 垂直投影方差大
 | 
			
		||||
        digit2_score += 2
 | 
			
		||||
    if center_density > 0.3:  # 中心区域密度较高
 | 
			
		||||
        digit2_score += 1
 | 
			
		||||
    if density > 0.4:  # 整体密度较高
 | 
			
		||||
        digit2_score += 1
 | 
			
		||||
    if horizontal_variance > 8:  # 水平投影方差大
 | 
			
		||||
        digit2_score += 1
 | 
			
		||||
    if aspect_ratio > 0.8:  # 数字2通常较宽
 | 
			
		||||
        digit2_score += 1
 | 
			
		||||
    
 | 
			
		||||
    # 返回得分更高的数字
 | 
			
		||||
    if digit1_score > digit2_score:
 | 
			
		||||
        return 1
 | 
			
		||||
    elif digit2_score > digit1_score:
 | 
			
		||||
        return 2
 | 
			
		||||
    else:
 | 
			
		||||
        # 如果得分相同,使用更复杂的判断
 | 
			
		||||
        if vertical_variance < 12:
 | 
			
		||||
            return 1
 | 
			
		||||
        else:
 | 
			
		||||
            return 2
 | 
			
		||||
 | 
			
		||||
def detect_text_in_image(image_path, show_process=True):
 | 
			
		||||
    """
 | 
			
		||||
    检测图片中的文字区域
 | 
			
		||||
    """
 | 
			
		||||
    # 读取图像
 | 
			
		||||
    image = cv2.imread(image_path)
 | 
			
		||||
@ -92,87 +152,130 @@ def detect_white_rectangles_in_image(image_path):
 | 
			
		||||
        return []
 | 
			
		||||
    
 | 
			
		||||
    # 预处理
 | 
			
		||||
    white_mask = preprocess_image(image)
 | 
			
		||||
    binary, v_channel = preprocess_image(image)
 | 
			
		||||
    
 | 
			
		||||
    # 查找白色矩形
 | 
			
		||||
    valid_rectangles = find_white_rectangles(white_mask)
 | 
			
		||||
    # 查找文字区域
 | 
			
		||||
    valid_text_regions = find_text_regions(binary)
 | 
			
		||||
    
 | 
			
		||||
    results = []
 | 
			
		||||
    
 | 
			
		||||
    for contour, (x, y, w, h), approx in valid_rectangles:
 | 
			
		||||
    for contour, (x, y, w, h) in valid_text_regions:
 | 
			
		||||
        # 提取ROI
 | 
			
		||||
        roi_mask = white_mask[y:y+h, x:x+w]
 | 
			
		||||
        roi_binary = binary[y:y+h, x:x+w]
 | 
			
		||||
        roi_original = image[y:y+h, x:x+w]
 | 
			
		||||
        
 | 
			
		||||
        # 分析特征
 | 
			
		||||
        features = analyze_white_region(roi_mask, roi_original)
 | 
			
		||||
        features = analyze_text_region(roi_binary, roi_original)
 | 
			
		||||
        
 | 
			
		||||
        # 判断是否为有效的白色矩形
 | 
			
		||||
        is_valid_white_rectangle = (
 | 
			
		||||
            features['white_ratio'] > 0.4 and  # 白色像素比例要求降低,从0.6降到0.4
 | 
			
		||||
            features['edge_density'] > 0.005    # 边缘密度要求降低,从0.01降到0.005
 | 
			
		||||
        # 判断是否为有效的低亮度区域
 | 
			
		||||
        is_valid_text_region = (
 | 
			
		||||
            features['black_ratio'] > 0.05 and   # 低亮度像素比例要求降低
 | 
			
		||||
            features['edge_density'] > 0.003     # 边缘密度要求降低
 | 
			
		||||
        )
 | 
			
		||||
        
 | 
			
		||||
        if is_valid_white_rectangle:
 | 
			
		||||
        if is_valid_text_region:
 | 
			
		||||
            # 使用OpenCV方法识别数字1或2
 | 
			
		||||
            predicted_digit = classify_digit_1_or_2(roi_binary)
 | 
			
		||||
            
 | 
			
		||||
            results.append({
 | 
			
		||||
                'type': 'white_rectangle',
 | 
			
		||||
                'type': 'digit_region',
 | 
			
		||||
                'position': (x, y, w, h),
 | 
			
		||||
                'digit': predicted_digit,
 | 
			
		||||
                'features': features,
 | 
			
		||||
                'confidence': 'high' if features['white_ratio'] > 0.8 else 'medium'
 | 
			
		||||
                'confidence': 'high' if features['black_ratio'] > 0.3 else 'medium'
 | 
			
		||||
            })
 | 
			
		||||
            
 | 
			
		||||
            # 在图像上绘制结果
 | 
			
		||||
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
 | 
			
		||||
            cv2.putText(image, f"白色矩形", (x, y - 10), 
 | 
			
		||||
            cv2.putText(image, f"数字{predicted_digit}", (x, y - 10), 
 | 
			
		||||
                       cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
 | 
			
		||||
    
 | 
			
		||||
    # 如果需要显示中间过程
 | 
			
		||||
    if show_process:
 | 
			
		||||
        # 创建过程图像
 | 
			
		||||
        process_images = []
 | 
			
		||||
        
 | 
			
		||||
        # 1. 原始图片
 | 
			
		||||
        process_images.append(("原始图片", image.copy()))
 | 
			
		||||
        
 | 
			
		||||
        # 2. HSV-V通道(明度通道)
 | 
			
		||||
        v_display = cv2.applyColorMap(v_channel, cv2.COLORMAP_JET)
 | 
			
		||||
        process_images.append(("HSV-V通道", v_display))
 | 
			
		||||
        
 | 
			
		||||
        # 3. 二值化后的低亮度区域
 | 
			
		||||
        process_images.append(("低亮度区域掩码", binary))
 | 
			
		||||
        
 | 
			
		||||
        # 4. 轮廓检测结果
 | 
			
		||||
        contour_image = image.copy()
 | 
			
		||||
        for contour, (x, y, w, h) in valid_text_regions:
 | 
			
		||||
            cv2.rectangle(contour_image, (x, y), (x + w, y + h), (0, 0, 255), 2)
 | 
			
		||||
        process_images.append(("轮廓检测", contour_image))
 | 
			
		||||
        
 | 
			
		||||
        # 5. 最终结果
 | 
			
		||||
        process_images.append(("最终结果", image))
 | 
			
		||||
        
 | 
			
		||||
        # 保存过程图像
 | 
			
		||||
        img_dir = Path(image_path).parent
 | 
			
		||||
        base_name = Path(image_path).stem
 | 
			
		||||
        
 | 
			
		||||
        for i, (title, img) in enumerate(process_images):
 | 
			
		||||
            if len(img.shape) == 2:  # 如果是灰度图,转换为BGR
 | 
			
		||||
                img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
 | 
			
		||||
            
 | 
			
		||||
            # 绘制轮廓点
 | 
			
		||||
            cv2.drawContours(image, [approx], -1, (255, 0, 0), 2)
 | 
			
		||||
            output_path = img_dir / f"{base_name}_process_{i+1}_{title}.jpg"
 | 
			
		||||
            cv2.imwrite(str(output_path), img)
 | 
			
		||||
            print(f"过程图像已保存: {output_path}")
 | 
			
		||||
    
 | 
			
		||||
    return image, results
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    """
 | 
			
		||||
    主函数:测试白色矩形检测
 | 
			
		||||
    主函数:测试文字区域检测
 | 
			
		||||
    """
 | 
			
		||||
    # 图片路径
 | 
			
		||||
    img_dir = Path("imgs")
 | 
			
		||||
    img1_path = img_dir / "1.jpg"
 | 
			
		||||
    img2_path = img_dir / "2.jpg"
 | 
			
		||||
    
 | 
			
		||||
    print("开始检测图片中的白色矩形区域...")
 | 
			
		||||
 
 | 
			
		||||
    print("开始检测图片中的文字区域...")
 | 
			
		||||
    print("=" * 50)
 | 
			
		||||
    
 | 
			
		||||
    # 检测第一张图片
 | 
			
		||||
    if img1_path.exists():
 | 
			
		||||
        print(f"\n检测图片: {img1_path}")
 | 
			
		||||
        result_img1, results1 = detect_white_rectangles_in_image(str(img1_path))
 | 
			
		||||
        print("检测过程包括以下步骤:")
 | 
			
		||||
        print("1. 原始图片")
 | 
			
		||||
        print("2. HSV色彩空间转换")
 | 
			
		||||
        print("3. 明度通道提取")
 | 
			
		||||
        print("4. 二值化(低亮度区域)")
 | 
			
		||||
        print("5. 轮廓检测")
 | 
			
		||||
        print("6. 特征分析")
 | 
			
		||||
        print("7. 数字识别")
 | 
			
		||||
        print("8. 最终结果")
 | 
			
		||||
        print("-" * 30)
 | 
			
		||||
        
 | 
			
		||||
        print("检测结果:")
 | 
			
		||||
        for result in results1:
 | 
			
		||||
            print(f"  类型: {result['type']}, 位置: {result['position']}, 置信度: {result['confidence']}")
 | 
			
		||||
            print(f"  特征: 白色比例={result['features']['white_ratio']:.2f}, "
 | 
			
		||||
                  f"宽高比={result['features']['aspect_ratio']:.2f}")
 | 
			
		||||
        result_img1, results1 = detect_text_in_image(str(img1_path), show_process=True)
 | 
			
		||||
        
 | 
			
		||||
        print("\n检测结果:")
 | 
			
		||||
        if results1:
 | 
			
		||||
            for i, result in enumerate(results1):
 | 
			
		||||
                print(f"  文字区域 {i+1}:")
 | 
			
		||||
                print(f"    位置: {result['position']}")
 | 
			
		||||
                print(f"    识别数字: {result['digit']}")
 | 
			
		||||
                print(f"    置信度: {result['confidence']}")
 | 
			
		||||
                print(f"    黑色比例: {result['features']['black_ratio']:.2f}")
 | 
			
		||||
                print(f"    宽高比: {result['features']['aspect_ratio']:.2f}")
 | 
			
		||||
                print(f"    边缘密度: {result['features']['edge_density']:.4f}")
 | 
			
		||||
                print(f"    面积: {result['features']['area']}")
 | 
			
		||||
        else:
 | 
			
		||||
            print("  未检测到文字区域")
 | 
			
		||||
        
 | 
			
		||||
        # 保存结果图片
 | 
			
		||||
        output_path1 = img_dir / "result_1.jpg"
 | 
			
		||||
        cv2.imwrite(str(output_path1), result_img1)
 | 
			
		||||
        print(f"结果图片已保存到: {output_path1}")
 | 
			
		||||
    
 | 
			
		||||
    # 检测第二张图片
 | 
			
		||||
    if img2_path.exists():
 | 
			
		||||
        print(f"\n检测图片: {img2_path}")
 | 
			
		||||
        result_img2, results2 = detect_white_rectangles_in_image(str(img2_path))
 | 
			
		||||
        
 | 
			
		||||
        print("检测结果:")
 | 
			
		||||
        for result in results2:
 | 
			
		||||
            print(f"  类型: {result['type']}, 位置: {result['position']}, 置信度: {result['confidence']}")
 | 
			
		||||
            print(f"  特征: 白色比例={result['features']['white_ratio']:.2f}, "
 | 
			
		||||
                  f"宽高比={result['features']['aspect_ratio']:.2f}")
 | 
			
		||||
        
 | 
			
		||||
        # 保存结果图片
 | 
			
		||||
        output_path2 = img_dir / "result_2.jpg"
 | 
			
		||||
        cv2.imwrite(str(output_path2), result_img2)
 | 
			
		||||
        print(f"结果图片已保存到: {output_path2}")
 | 
			
		||||
        print(f"\n最终结果图片已保存到: {output_path1}")
 | 
			
		||||
        print("中间过程图像也已保存到imgs目录")
 | 
			
		||||
    else:
 | 
			
		||||
        print(f"图片文件不存在: {img1_path}")
 | 
			
		||||
    
 | 
			
		||||
    print("\n检测完成!")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||