HumansXドキュメントセンター 公式サイトへ ↗

2.20 HSV と画像の輪郭・中心点の描画

実験の目的

  1. 画像の HSV の範囲値を取得します。

  2. モルフォロジー処理によるノイズ除去、輪郭検出の方法、輪郭の中心点の描画を習得します。

機能要件

スライダーで HSV しきい値を動的に調整して色分割を行い、検出した物体を元画像上に赤い輪郭で表示し、中心点を黄色で描画します。

ハードウェアの準備

No. 名称 数量 備考
1 RDK X5 1 組み込みメインボード(32GB メモリーカード付き)。上位機(PC 側)システムとして動作します。
2 カードリーダー 1 システムイメージの書き込みに使用します。
3 USB カメラ 1 画像を取得します。
4 電源ケーブル 1 電源供給用です。
5 LAN ケーブル 1 ネットワーク接続用です。

回路接続

ソフトウェア設計

設計フローチャート

ソースコードのダウンロード

ソースコードファイル:05_get_hsv_strip_counters_limit.rar

プログラムコード

完全なプロジェクトコードは(ソースコードファイル)をクリックしてダウンロードしてください。

"""
---------------------------------------------------------------
程序功能: 使用托条工具,显示hsv处理之后,标出满足条件轮廓图片的中心点

---------------------------------------------------------------
"""

import cv2
import numpy as np

# ==================== 初始化摄像头 ====================
# 打开默认摄像头(使用udev规则)
# "/dev/mycamera" 是通过udev规则创建的符号链接,指向固定的物理摄像头
cap = cv2.VideoCapture("/dev/mycamera")
#cap = cv2.VideoCapture(0)  # 打开默认摄像头(设备索引通常是 0)

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("错误:无法打开摄像头")
    exit()

# ==================== 创建HSV控制窗口 ====================
# 创建名为 "HSV Control" 的窗口,用于放置滑动条
cv2.namedWindow("HSV Control")

# ==================== 创建6个滑动条 ====================
# 每个滑动条对应 HSV 的一个分量的下限或上限
cv2.createTrackbar("H Lower", "HSV Control", 0, 179, lambda x: None)   # 色调下限
cv2.createTrackbar("H Upper", "HSV Control", 179, 179, lambda x: None)  # 色调上限
cv2.createTrackbar("S Lower", "HSV Control", 0, 255, lambda x: None)   # 饱和度下限
cv2.createTrackbar("S Upper", "HSV Control", 255, 255, lambda x: None)  # 饱和度上限
cv2.createTrackbar("V Lower", "HSV Control", 0, 255, lambda x: None)   # 明度下限
cv2.createTrackbar("V Upper", "HSV Control", 255, 255, lambda x: None)  # 明度上限

# ==================== 设置滑动条初始值(绿色范围) ====================
# 设置 H 分量的初始范围为 35~85(绿色的色调范围)
cv2.setTrackbarPos("H Lower", "HSV Control", 35)
cv2.setTrackbarPos("H Upper", "HSV Control", 85)

# ==================== 定义颜色常量 ====================
# 橙色(BGR格式),用于绘制中心点
# 注意:OpenCV 使用 BGR 格式,所以 (0, 165, 255) 实际上是橙黄色
ORANGE = (0, 165, 255)
# 红色(BGR格式),用于绘制轮廓
RED = (0, 0, 255)

# ==================== 主循环:实时采集并处理 ====================
while True:
    # 从摄像头读取一帧图像
    ret, frame = cap.read()

    # 检查是否成功读取到图像
    if not ret:
        break

    # ========== 1. 颜色空间转换 ==========
    # 将 BGR 图像转换为 HSV 颜色空间(更适合基于颜色的分割)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # ========== 2. 读取滑动条值 ==========
    h_low = cv2.getTrackbarPos("H Lower", "HSV Control")
    h_high = cv2.getTrackbarPos("H Upper", "HSV Control")
    s_low = cv2.getTrackbarPos("S Lower", "HSV Control")
    s_high = cv2.getTrackbarPos("S Upper", "HSV Control")
    v_low = cv2.getTrackbarPos("V Lower", "HSV Control")
    v_high = cv2.getTrackbarPos("V Upper", "HSV Control")

    # ========== 3. 创建掩膜 ==========
    lower = np.array([h_low, s_low, v_low])   # HSV 下限
    upper = np.array([h_high, s_high, v_high]) # HSV 上限
    mask = cv2.inRange(hsv, lower, upper)    # 二值掩膜(白色=在范围内)

    # ========== 4. 形态学去噪(使轮廓更干净) ==========
    kernel = np.ones((5, 5), np.uint8)       # 创建 5x5 的核
    # 闭运算(先膨胀后腐蚀):填补小孔,连接邻近区域
    mask_clean = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    # 开运算(先腐蚀后膨胀):去除小噪点,平滑边缘
    mask_clean = cv2.morphologyEx(mask_clean, cv2.MORPH_OPEN, kernel)

    # ========== 5. 轮廓检测 ==========
    # cv2.findContours() 查找图像中的轮廓
    # 参数说明:
    #   mask_clean: 输入的二值图像
    #   cv2.RETR_EXTERNAL: 只检测最外层轮廓
    #   cv2.CHAIN_APPROX_SIMPLE: 压缩存储,只保存端点
    contours, hierarchy = cv2.findContours(mask_clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # ========== 6. 创建输出图像(带轮廓和中心点) ==========
    # 复制原图,用于绘制轮廓和中心点
    output_frame = frame.copy()

    # 存储满足面积条件的轮廓(用于统一绘制)
    valid_contours = []

    # ========== 7. 遍历每个轮廓,计算中心点 ==========
    for cnt in contours:
        # 计算轮廓的面积
        # cv2.contourArea(contour): 计算轮廓的面积(像素数)
        area = cv2.contourArea(cnt)

        # 面积过滤:只处理面积大于 1000 像素的轮廓
        # 这样可以过滤掉小的噪点轮廓
        if area > 1000:
            valid_contours.append(cnt)  # 添加到有效轮廓列表

            # ========== 计算轮廓的矩(Moments) ==========
            # 图像的矩可以用于计算轮廓的中心、面积、方向等特征
            # 参考:https://en.wikipedia.org/wiki/Image_moment
            M = cv2.moments(cnt)

            # 避免除零错误(当 M["m00"]=0 时,轮廓面积为0)
            if M["m00"] != 0:
                # 计算轮廓中心点的 x 坐标
                # 公式:cx = M10 / M00
                cx = int(M["m10"] / M["m00"])

                # 计算轮廓中心点的 y 坐标
                # 公式:cy = M01 / M00
                cy = int(M["m01"] / M["m00"])

                # 在输出图像上绘制中心点
                # cv2.circle(img, center, radius, color, thickness)
                #   thickness = -1 表示实心圆
                cv2.circle(output_frame, (cx, cy), radius=8, color=ORANGE, thickness=-1)

    # ========== 8. 绘制所有有效轮廓 ==========
    # cv2.drawContours() 绘制轮廓
    # 参数说明:
    #   output_frame: 目标图像
    #   valid_contours: 有效轮廓列表
    #   -1: 绘制所有轮廓
    #   RED: 红色 (BGR格式)
    #   2: 线宽(像素)
    cv2.drawContours(output_frame, valid_contours, -1, RED, thickness=2)

    # ========== 9. 横屏拼接显示 ==========
    # 将掩膜(单通道)转换为 BGR 三通道,以便拼接
    mask_bgr = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

    # 水平拼接:输出图像(左)和掩膜(右)
    combined = np.hstack((output_frame, mask_bgr))

    # ========== 10. 显示 HSV 参数 ==========
    text = f"H:{h_low}-{h_high} S:{s_low}-{s_high} V:{v_low}-{v_high}"
    cv2.putText(combined, text, (10, 30), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

    # ========== 11. 显示结果 ==========
    cv2.imshow("Original | Mask", combined)

    # ========== 12. 键盘控制 ==========
    # 按 'q' 键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# ==================== 资源释放 ====================
cap.release()          # 释放摄像头设备
cv2.destroyAllWindows()  # 关闭所有OpenCV创建的窗口

操作手順

  1. ターミナルを開き、Python プログラムのディレクトリに移動してプログラムを実行します。以下のコマンドを入力してください。
python  05_get_hsv_strip_counters_limit.py

実験結果

スライダーで HSV しきい値を動的に調整して色分割を行い、検出した物体を元画像上に赤い輪郭で表示し、中心点を黄色で描画します。

お問い合わせ

資料のダウンロード・技術サポートについては、HumansX株式会社までお問い合わせください。