树莓派 OpenCV 自动视觉跟踪:云台舵机实时锁定彩色目标
项目简介
基于计算机视觉的云台舵机系统,自动跟踪指定颜色物体。
项目背景
引言
上一教程学习了控制云台舵机定位树莓派摄像头。本教程进阶实现:摄像头自主跟踪彩色物体。这是我首次实战 OpenCV,深感这开源视觉库的强大。
OpenCV 学术/商业免费,提供 C++/C/Python/Java 接口,跨平台 (Windows/Linux/macOS/iOS/Android)。本系列聚焦树莓派 (Raspbian) + Python,因 OpenCV 专为计算效率与实时应用设计,完美契合物理计算项目。
步骤 1:物料清单 (BOM)
- 树莓派 3 – $32
- 500万像素 1080p OV5647 摄像头 – $13
- TowerPro SG90 9g 180° 微型舵机 ×2 – $4
- 云台防震平台含双舵机 (*) – $8
- 红色 LED、220Ω 电阻、1kΩ 电阻 ×2 (可选)
- 杂项:金属件、扎带等 (自制云台用)
(*) 可购买成品云台或自制。
步骤 2:安装 OpenCV 3
Raspbian Stretch 上最靠谱方案:遵循 Adrian Rosebrock 教程 从源码编译并建立专用 Python 虚拟环境。完成后激活并验证:
source ~/.profile
workon cv
python
import cv2
print(cv2.__version__)
应显示 3.3.0+,确认 cv 环境就绪。
步骤 3:测试摄像头
import cv2
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
frame = cv2.flip(frame, -1) # 垂直翻转 (按需)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', frame)
cv2.imshow('gray', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
按 q 或 Ctrl+C 退出。正常显示彩色与灰度双画面。
步骤 4:OpenCV HSV 颜色检测
OpenCV 使用 HSV (色相、饱和度、明度) 空间,更符合人眼颜色感知。检测特定颜色:先获取 BGR 值,转 HSV 确定上下界。
示例:跟踪黄色物体。用取色器 (如 PPT) 得 BGR (71, 234, 213),转 HSV 脚本:
import sys, numpy as np, cv2
blue, green, red = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
color = np.uint8([[[blue, green, red]]])
hsv = cv2.cvtColor(color, cv2.COLOR_BGR2HSV)
hue = hsv[0][0][0]
print('Lower bound:', [hue-10, 100, 100])
print('Upper bound:', [hue+10, 255, 255])
运行 python bgr_hsv_converter.py 71 234 213 输出:
Lower bound: [24, 100, 100] Upper bound: [44, 255, 255]
掩膜提取目标颜色:
import cv2, numpy as np
img = cv2.imread('yellow_object.JPG', 1)
img = cv2.resize(img, (0,0), fx=0.2, fy=0.2)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower = np.array([24, 100, 100], dtype=np.uint8)
upper = np.array([44, 255, 255], dtype=np.uint8)
mask = cv2.inRange(hsv, lower, upper)
cv2.imshow('mask', mask)
cv2.imshow('image', img)
while True:
k = cv2.waitKey(0)
if k == 27: break
cv2.destroyAllWindows()
保存为 colorDetection.py 运行测试。
步骤 5:实时物体跟踪
基于掩膜逐帧计算质心。代码参考 Adrian Rosebrock Ball Tracking 教程并融合上述 HSV 阈值。先装 imutils:
pip install imutils
运行 ball_tracking.py,检测到目标时绘制圆与质心。
步骤 6:GPIO 测试 — LED 指示
接线:LED 阴极接 GPIO 21,阳极经 220Ω 接地。cv 环境装 RPi.GPIO:
pip install RPi.GPIO
测试脚本 LED_simple_test.py:
import sys, time, RPi.GPIO as GPIO
led = int(sys.argv[1])
freq = int(sys.argv[2])
GPIO.setmode(GPIO.BCM)
GPIO.setup(led, GPIO.OUT)
GPIO.setwarnings(False)
print(f'Blinking LED on GPIO {led} every {freq}s, 5 times.')
for _ in range(5):
GPIO.output(led, GPIO.LOW)
time.sleep(freq)
GPIO.output(led, GPIO.HIGH)
time.sleep(freq)
GPIO.cleanup()
运行 python LED_simple_test.py 21 1 验证 LED 闪烁 5 次/秒。
步骤 7:颜色识别联动 GPIO
融合跟踪逻辑与 GPIO 控制:检测到目标颜色点亮 LED。核心增量:
import RPi.GPIO as GPIO
led = 21
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led, GPIO.OUT)
GPIO.output(led, GPIO.LOW)
ledOn = False
检测循环中确认有效半径后:
if not ledOn:
GPIO.output(led, GPIO.HIGH)
ledOn = True
完整脚本 object_detection_LED.py,运行后仅当物体颜色落在 HSV 范围内 LED 才亮。
步骤 8:云台机构接线
舵机外接 5V 供电。数据引脚:
- GPIO 17 → 俯仰舵机
- GPIO 27 → 偏航舵机
树莓派、舵机、电源共地。可选:Pi GPIO 与舵机信号脚串联 1kΩ 电阻防浪涌。
测试脚本 angleServoCtrl.py:
from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
def setServoAngle(servo, angle):
pwm = GPIO.PWM(servo, 50)
pwm.start(8)
duty = angle / 18. + 3.
pwm.ChangeDutyCycle(duty)
sleep(0.3)
pwm.stop()
if __name__ == '__main__':
import sys
servo = int(sys.argv[1])
GPIO.setup(servo, GPIO.OUT)
setServoAngle(servo, int(sys.argv[2]))
GPIO.cleanup()
示例:python angleServoCtrl.py 17 45 俯仰舵机转 45°。
步骤 9:实时获取目标坐标
修改 objectDetect_LED.py 打印质心 x, y:
def mapObjectPosition(x, y):
print(f'[INFO] Object center at X={x}, Y={y}')
坐标范围:x ∈ [0,500] (左→右),y ∈ [0,350] (上→下)。移动物体观察实时输出。
步骤 10:目标位置跟踪控制系统
定义“中心区” (如 220 < x < 280 且 160 < y < 210)。超出则调整舵机:
def mapServoPosition(x, y):
global panAngle, tiltAngle
if x < 220:
panAngle = min(panAngle + 10, 140)
positionServo(panServo, panAngle)
if x > 280:
panAngle = max(panAngle - 10, 40)
positionServo(panServo, panAngle)
if y < 160:
tiltAngle = min(tiltAngle + 10, 140)
positionServo(tiltServo, tiltAngle)
if y > 210:
tiltAngle = max(tiltAngle - 10, 40)
positionServo(tiltServo, tiltAngle)
辅助函数 positionServo 调用 angleServoCtrl.py:
import os
def positionServo(servo, angle):
os.system(f'python angleServoCtrl.py {servo} {angle}')
print(f'[INFO] Positioning servo GPIO {servo} to {angle}°')
所有脚本同目录,完整实现见 objectDetectTrack.py。
步骤 11:结语
本项目演示 OpenCV + 树莓派 GPIO + 云台舵机实现自主彩色物体跟踪。可尝试不同颜色、形状、舵机速度。
完整代码与资源:GitHub 与 MJRoBot.org 博客。
阅读愉快,下期见!
制造工艺