4. 基于颜色空间的物体检测

任务目标

在Jetson平台上,使用OpenCV读取摄像头或图像,将BGR图像转换到HSV颜色空间,通过设定颜色阈值生成掩膜,检测特定颜色物体(以红色为例),输出物体的像素坐标(质心)与轮廓信息。

环境依赖

需要安装OpenCV及其Python绑定,Jetson设备(如Orin Nano/NX)自带Python环境,执行以下命令安装依赖:

sudo apt update
sudo apt install python3-opencv python3-numpy

完整实现代码

以下代码实现从摄像头实时读取画面,检测红色物体并绘制轮廓与质心,同时打印坐标信息。若没有摄像头,可改用静态图像文件(代码中已包含注释切换方式)。

import cv2
import numpy as np

# 若使用静态图像,取消下一行注释并注释cap部分
# frame = cv2.imread("test_red.jpg")

cap = cv2.VideoCapture(0)  # 使用CSI摄像头时改为 cv2.VideoCapture("nvarguscamerasrc ! video/x-raw(memory:NVMM), width=640, height=480, format=NV12, framerate=30/1 ! nvvidconv ! video/x-raw, format=BGRx ! videoconvert ! video/x-raw, format=BGR ! appsink", cv2.CAP_GSTREAMER)

# 红色HSV阈值范围(可调)
lower_red1 = np.array([0, 100, 100])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([160, 100, 100])
upper_red2 = np.array([179, 255, 255])

while True:
    ret, frame = cap.read()
    if not ret:
        break

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # 红色在HSV色环上跨越0度,需两个区间合并
    mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
    mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
    mask = cv2.bitwise_or(mask1, mask2)

    # 形态学去噪
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)

    # 查找轮廓
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area < 500:  # 过滤小面积噪声
            continue

        # 计算质心
        M = cv2.moments(cnt)
        if M["m00"] != 0:
            cx = int(M["m10"] / M["m00"])
            cy = int(M["m01"] / M["m00"])
        else:
            continue

        # 绘制轮廓与质心
        cv2.drawContours(frame, [cnt], -1, (0, 255, 0), 2)
        cv2.circle(frame, (cx, cy), 5, (255, 0, 0), -1)
        cv2.putText(frame, f"({cx}, {cy})", (cx + 10, cy - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)

        # 输出像素坐标与轮廓点数量
        print(f"质心: ({cx}, {cy}), 轮廓点数: {len(cnt)}, 面积: {int(area)}")

    cv2.imshow("Frame", frame)
    cv2.imshow("Mask", mask)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

运行与验证

运行方式:将代码保存为 color_detect.py,在终端执行:

python3 color_detect.py

验证步骤:

  1. 在摄像头前放置一个红色物体(如红色小球或积木),确保背景无大面积红色干扰。
  2. 观察弹出的两个窗口:Frame窗口显示绿色轮廓包围红色物体且质心处有蓝色圆点;Mask窗口显示白色区域对应红色物体位置。
  3. 终端持续打印质心坐标、轮廓点数和面积,坐标值随物体移动而变化。
  4. 按键盘 q 键退出程序。

通过条件:红色物体被稳定检测并框出,质心坐标与物体实际位置一致;当物体移出画面或遮挡时,不再输出该物体的轮廓信息。

关键参数调整说明

HSV阈值范围是检测效果的核心。若检测不到目标,可适当放宽lower_red1/2中的S和V下限(如从100降至50);若误检背景,则收紧阈值或增大面积过滤值(代码中为500)。不同光照环境下需重新调节阈值,建议先用cv2.createTrackbar动态调试,再固定最终值。