如何在OpenCV Python中限制cv2.rectangle()生成的矩形数量以检测最近障碍物?
问题解决:定位最近的橙色障碍物
核心思路
仅靠面积筛选障碍物的方案在多个大型障碍物同时出现时会失效,正确的做法是利用深度图的真实数值判断距离:MiDaS模型输出的深度值越小,代表物体距离镜头越近。我们需要:
- 先筛选出符合面积要求的橙色物体轮廓
- 计算每个候选轮廓对应的平均深度值(或最小深度值)
- 选择深度值最小的轮廓(最近的障碍物)绘制矩形
修改后的完整代码
import cv2 import torch import time import numpy as np #model_type = "DPT_Large" # MiDaS v3 - Large (最高精度,最慢推理速度) model_type = "DPT_Hybrid" # MiDaS v3 - Hybrid (中等精度,中等推理速度) #model_type = "MiDaS_small" # MiDaS v2.1 - Small (最低精度,最快推理速度) midas = torch.hub.load("intel-isl/MiDaS", model_type) device = torch.device("cuda") midas.to(device) midas.eval() midas_transforms = torch.hub.load("intel-isl/MiDaS", "transforms") if model_type == "DPT_Large" or model_type == "DPT_Hybrid": transform = midas_transforms.dpt_transform else: transform = midas_transforms.small_transform cap = cv2.VideoCapture(0) while cap.isOpened(): success, img = cap.read() if not success: break start = time.time() img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) input_batch = transform(img_rgb).to(device) # 预测深度并恢复原始分辨率 with torch.no_grad(): prediction = midas(input_batch) prediction = torch.nn.functional.interpolate( prediction.unsqueeze(1), size=img_rgb.shape[:2], mode="bilinear", align_corners=False, ).squeeze() # 保存原始深度图(未归一化、未伪彩色),用于计算真实距离 raw_depth_map = prediction.cpu().numpy() # 归一化后的深度图用于可视化 vis_depth_map = cv2.normalize(raw_depth_map, None, 0, 1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_64F) end = time.time() totalTime = end - start fps = 1 / totalTime img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR) # 生成伪彩色深度图用于显示和颜色识别 vis_depth_map = (vis_depth_map*255).astype(np.uint8) vis_depth_map = cv2.applyColorMap(vis_depth_map, cv2.COLORMAP_MAGMA) dim = (192*3, 108*4) img_resized = cv2.resize(img_bgr, dim, interpolation=cv2.INTER_AREA) cv2.imshow('Image', img_resized) cv2.imshow('Depth Map', vis_depth_map) # 识别橙色物体(HSV范围) hsvFrame = cv2.cvtColor(vis_depth_map, cv2.COLOR_BGR2HSV) orange_lower = np.array([10, 100, 20], np.uint8) orange_upper = np.array([25, 255, 255], np.uint8) orange_mask = cv2.inRange(hsvFrame, orange_lower, orange_upper) kernal = np.ones((5, 5), "uint8") orange_mask = cv2.dilate(orange_mask, kernal) res_orange = cv2.bitwise_and(vis_depth_map, vis_depth_map, mask=orange_mask) contours, hierarchy = cv2.findContours(orange_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 收集符合面积要求的候选轮廓及其深度信息 candidate_obstacles = [] for contour in contours: area = cv2.contourArea(contour) if area > 18500: x, y, w, h = cv2.boundingRect(contour) # 提取该轮廓区域内的原始深度值 roi_depth = raw_depth_map[y:y+h, x:x+w] # 计算区域内的平均深度(也可以用最小深度,更敏感) avg_depth = np.mean(roi_depth) candidate_obstacles.append((avg_depth, x, y, w, h)) # 如果有候选障碍物,选择深度最小的(最近的)绘制矩形 if candidate_obstacles: # 按深度值升序排序,第一个就是最近的 candidate_obstacles.sort(key=lambda x: x[0]) closest_depth, x, y, w, h = candidate_obstacles[0] vis_depth_map = cv2.rectangle(vis_depth_map, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.putText(vis_depth_map, f"Closest Obstacle (Depth: {closest_depth:.2f})", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imshow("Obstacle Map", vis_depth_map) if cv2.waitKey(5) & 0xFF == 27: break cap.release() cv2.destroyAllWindows()
关键修改点
- 保留原始深度图
raw_depth_map:未做归一化和伪彩色处理,用于计算真实深度数值 - 新增
candidate_obstacles列表:收集所有符合面积要求的障碍物的深度与位置信息 - 按深度值排序候选障碍物:选择深度最小的(最近的)进行矩形绘制
- 修正原代码中
imageFrame未定义的错误 - 优化颜色识别的标注,匹配实际检测的橙色物体
内容的提问来源于stack exchange,提问作者EkronShoo
相关产品推荐
相关产品推荐

