2.23 LAB 値処理による画像の輪郭・中心点の表示
実験の目的
-
スライダーを使って画像の LAB 値を取得します。
-
画像の輪郭と中心点を表示できるようになります。
-
色分割、モルフォロジー処理によるノイズ除去、輪郭検出、面積フィルタリングの方法を理解します。
機能要件
スライダーで LAB しきい値を動的に調整して色分割を行い、検出した物体を元画像上に赤い輪郭で表示し、中心点を黄色で描画します。
ハードウェアの準備
| No. | 名称 | 数量 | 備考 |
|---|---|---|---|
| 1 | RDK X5 | 1 | 組み込みメインボード(32GB メモリーカード付き)。上位機(PC 側)システムとして動作します。 |
| 2 | カードリーダー | 1 | システムイメージの書き込みに使用します。 |
| 3 | USB カメラ | 1 | 画像を取得します。 |
| 4 | 電源ケーブル | 1 | 電源供給用です。 |
| 5 | LAN ケーブル | 1 | ネットワーク接続用です。 |
回路接続

ソフトウェア設計
設計フローチャート

ソースコードのダウンロード
ソースコードファイル:08_get_lab_strip_counters_limit.rar
プログラムコード
完全なプロジェクトコードは(ソースコードファイル)をクリックしてダウンロードしてください。
"""
---------------------------------------------------------------
程序功能: 使用托条工具,显示lab处理之后,标出满足条件轮廓图片的中心点
---------------------------------------------------------------
"""
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()
# ==================== 创建 Lab 控制窗口 ====================
# 创建名为 "Lab Control" 的窗口,用于放置滑动条
cv2.namedWindow("Lab Control")
# ==================== 创建6个滑动条 ====================
# 每个滑动条对应 Lab 的一个分量的下限或上限
# Lab 各分量的取值范围:L:0~255, a:0~255, b:0~255
# 注意:理论上 a 和 b 是有负值的,但 OpenCV 中映射到 0~255 范围
cv2.createTrackbar("L Lower", "Lab Control", 0, 255, lambda x: None) # 亮度下限
cv2.createTrackbar("L Upper", "Lab Control", 255, 255, lambda x: None) # 亮度上限
cv2.createTrackbar("a Lower", "Lab Control", 0, 255, lambda x: None) # 绿-红轴下限
cv2.createTrackbar("a Upper", "Lab Control", 255, 255, lambda x: None) # 绿-红轴上限
cv2.createTrackbar("b Lower", "Lab Control", 0, 255, lambda x: None) # 蓝-黄轴下限
cv2.createTrackbar("b Upper", "Lab Control", 255, 255, lambda x: None) # 蓝-黄轴上限
# ==================== 设置滑动条初始值(浅绿色/黄绿色范围) ====================
# 这些值是通过实验7(鼠标点击查看Lab值)获取的参考值
# 用于分割浅绿色/黄绿色的物体
cv2.setTrackbarPos("L Lower", "Lab Control", 125) # 亮度下限:不选太暗的区域
cv2.setTrackbarPos("L Upper", "Lab Control", 255) # 亮度上限:亮部全选
cv2.setTrackbarPos("a Lower", "Lab Control", 82) # a 下限:偏红方向
cv2.setTrackbarPos("a Upper", "Lab Control", 120) # a 上限:偏绿方向
cv2.setTrackbarPos("b Lower", "Lab Control", 70) # b 下限:偏蓝方向
cv2.setTrackbarPos("b Upper", "Lab Control", 123) # b 上限:偏黄方向
# ==================== 定义颜色常量 ====================
ORANGE = (0, 165, 255) # 橙色(BGR格式),用于绘制中心点
RED = (0, 0, 255) # 红色(BGR格式),用于绘制轮廓
# ==================== 主循环:实时采集并处理 ====================
while True:
# 从摄像头读取一帧图像
ret, frame = cap.read()
# 检查是否成功读取到图像
if not ret:
break
# ========== 1. 颜色空间转换 ==========
# 将 BGR 图像转换为 Lab 颜色空间
# Lab 颜色空间更接近人眼感知,颜色距离计算更均匀
lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)
# ========== 2. 读取滑动条值 ==========
# 获取每个滑动条的位置(用户通过拖动滑动条调整的值)
L_low = cv2.getTrackbarPos("L Lower", "Lab Control") # 亮度下限
L_high = cv2.getTrackbarPos("L Upper", "Lab Control") # 亮度上限
a_low = cv2.getTrackbarPos("a Lower", "Lab Control") # a轴下限(绿-红)
a_high = cv2.getTrackbarPos("a Upper", "Lab Control") # a轴上限
b_low = cv2.getTrackbarPos("b Lower", "Lab Control") # b轴下限(蓝-黄)
b_high = cv2.getTrackbarPos("b Upper", "Lab Control") # b轴上限
# ========== 3. 构建 Lab 阈值范围数组 ==========
# 注意:dtype=np.uint8 确保数据类型正确
lower = np.array([L_low, a_low, b_low], dtype=np.uint8) # Lab 下限
upper = np.array([L_high, a_high, b_high], dtype=np.uint8) # Lab 上限
# ========== 4. 创建掩膜(二值图像) ==========
# cv2.inRange() 检查每个像素是否在 [lower, upper] 范围内
# - 在范围内:输出 255(白色)
# - 不在范围内:输出 0(黑色)
mask = cv2.inRange(lab, lower, upper)
# ========== 5. 形态学去噪(使轮廓更干净) ==========
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)
# ========== 6. 轮廓检测 ==========
# cv2.findContours() 查找图像中的轮廓
# mask_clean: 输入的二值图像
# cv2.RETR_EXTERNAL: 只检测最外层轮廓
# cv2.CHAIN_APPROX_SIMPLE: 压缩存储,只保存端点
contours, hierarchy = cv2.findContours(mask_clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# ========== 7. 创建输出图像 ==========
# 复制原图,用于绘制轮廓和中心点
output_frame = frame.copy()
valid_contours = [] # 存储满足面积条件的轮廓
# ========== 8. 遍历轮廓,计算中心点 ==========
for cnt in contours:
# 计算轮廓面积(像素数)
area = cv2.contourArea(cnt)
# 面积过滤:只处理面积大于 1000 像素的轮廓
# 过滤掉小噪点,只保留有效物体
if area > 1000:
valid_contours.append(cnt) # 添加到有效轮廓列表
# 计算轮廓的矩
M = cv2.moments(cnt)
# 避免除零错误
if M["m00"] != 0:
# 计算轮廓中心点坐标
cx = int(M["m10"] / M["m00"]) # 质心 x 坐标
cy = int(M["m01"] / M["m00"]) # 质心 y 坐标
# 绘制中心点(橙色实心圆,半径8像素)
cv2.circle(output_frame, (cx, cy), radius=8, color=ORANGE, thickness=-1)
# ========== 9. 绘制轮廓 ==========
# 在原图上绘制所有有效轮廓(红色,线宽2像素)
cv2.drawContours(output_frame, valid_contours, -1, RED, thickness=2)
# ========== 10. 横屏拼接显示 ==========
# 将掩膜(单通道)转换为 BGR 三通道,以便拼接
mask_bgr = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
# 水平拼接:输出图像(左)和掩膜(右)
combined = np.hstack((output_frame, mask_bgr))
# ========== 11. 显示 Lab 参数 ==========
text = f"L:{L_low}-{L_high} a:{a_low}-{a_high} b:{b_low}-{b_high}"
cv2.putText(combined, text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# ========== 12. 显示结果 ==========
cv2.imshow("Original | Mask", combined)
# ========== 13. 键盘控制 ==========
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ==================== 资源释放 ====================
cap.release() # 释放摄像头设备
cv2.destroyAllWindows() # 关闭所有OpenCV创建的窗口
操作手順
- ターミナルを開き、Python プログラムのディレクトリに移動してプログラムを実行します。以下のコマンドを入力してください。
python 08_get_lab_strip_counters_limit.py
実験結果
スライダーで LAB しきい値を動的に調整して色分割を行い、検出した物体を元画像上に赤い輪郭で表示し、中心点を黄色で描画します。
参考結果:
お問い合わせ
資料のダウンロード・技術サポートについては、HumansX株式会社までお問い合わせください。
ドキュメント