You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:50:34