树莓派,opencv,Picamera2利用舵机云台追踪人脸

一、需要准备的硬件

  1. Raspiberry 4b
  2. 两个SG90 180度舵机(注意舵机的角度,最好是180度且带限位的,切勿选360度舵机)
  3. 二自由度舵机云台(如下图)
  4. Raspiberry CSI 摄像头
    组装后的效果:
    在这里插入图片描述

二、项目目标

追踪人脸:
当人脸移动时,摄像头通过控制两个伺服电机(分别是偏航和俯仰)把该人脸放到视界的中心位置
(备注:没有采用PID控制伺服电机)

三、具体步骤

3.1 下载用于人脸识别的级联分类器

下载级联分类器“haarcascade_frontalface_default.xml”,下载地址:haarcascade_frontalface_default.xml
下载完成后将其与后面的所有文件放到同一目录中。

3.2人脸追踪代码

  1. 创建文件“face_tracking_noPID.py” ,代码如下:
import cv2
from picamera2 import Picamera2
import time
import numpy as np
from servo import Servo
from time import sleep
picam2 = Picamera2()

#偏航伺服电机连接上GPIO19脚,俯仰伺服电机信号线连接到GPIO16脚上
pan=Servo(pin=19)
tilt=Servo(pin=16)

panAngle=0
tiltAngle=0

pan.set_angle(panAngle)
tilt.set_angle(tiltAngle)

#初始化pi camera
dispW=1280
dispH=720
picam2.preview_configuration.main.size = (dispW,dispH)
picam2.preview_configuration.main.format = "RGB888"
picam2.preview_configuration.controls.FrameRate=30
picam2.preview_configuration.align()
picam2.configure("preview")
picam2.start()
fps=0
pos=(30,60)
font=cv2.FONT_HERSHEY_SIMPLEX
height=1.5
weight=3
myColor=(0,0,255)


while True:
    tStart=time.time()
    #获取取摄像头图片
    frame= picam2.capture_array()
    frame=cv2.flip(frame,1)
    gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    #设置人脸识别参数
    face_cascade=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    rects = face_cascade.detectMultiScale(gray, scaleFactor=1.05,
			minNeighbors=9, minSize=(30, 30),
			flags=cv2.CASCADE_SCALE_IMAGE)
    if len(rects) > 0:
        # 获取矩形的参数
        # x,y为左上角点坐标,w,h为宽度和高度
        # 计算图像中心
        (x, y, w, h) = rects[0]
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),3)
        errorX=dispW/2-(x+w/2)
        if errorX>30:
            panAngle=panAngle-3 #调整此代码中的数字可以提高追踪速度
            if panAngle<-90:
                panAngle=-90
            pan.set_angle(panAngle)
        if errorX<-30:
            panAngle=panAngle+3 #调整此代码中的数字可以提高追踪速度
            if panAngle>90:
                panAngle=90
            pan.set_angle(panAngle)
        #俯仰电机纠偏Y轴方向上的偏差,大于30度,俯仰角度减小,小于-30度,俯仰角度增加
        errorY=dispH/2-(y+h/2)
        if errorY>30:
            tiltAngle=tiltAngle-3 #调整此代码中的数字可以提高追踪速度
            if tiltAngle<-90:
                tiltAngle=-90
            tilt.set_angle(tiltAngle)
        if errorY<-30:
            tiltAngle=tiltAngle+3 #调整此代码中的数字可以提高追踪速度
            if tiltAngle>90:
                tiltAngle=90
            tilt.set_angle(tiltAngle)   
            
    cv2.imshow('Camera',frame)
    #按q键退出,释放伺服电机和摄像头
    if cv2.waitKey(1)==ord('q'):
        pan.stop()
        tilt.stop()
        picam2.stop()
        print('stop') 
        sleep(1)        
        break
    tEnd=time.time()
    loopTime=tEnd-tStart
    fps=.9*fps + .1*(1/loopTime)
cv2.destroyAllWindows()
  1. 上述代码中的from servo import Servo导入servo,这个库是没有的,我们要手动创建这个库,在object_tracking.py所在的目录下新建servo.py文件,复制下面的代码到文件中
#!/usr/bin/env python3
import pigpio
from time import sleep
# Start the pigpiod daemon
import subprocess
result = None
status = 1
for x in range(3):
    p = subprocess.Popen('sudo pigpiod', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    result = p.stdout.read().decode('utf-8')
    status = p.poll()
    if status == 0:
        break
    sleep(0.2)
if status != 0:
    print(status, result)
'''
> Use the DMA PWM of the pigpio library to drive the servo
> Map the servo angle (0 ~ 180 degree) to (-90 ~ 90 degree)

'''

class Servo():
    MAX_PW = 1250  # 0.5/20*100
    MIN_PW = 250 # 2.5/20*100
    _freq = 50 # 50 Hz, 20ms
 
    def __init__(self, pin, min_angle=-90, max_angle=90):

        self.pi = pigpio.pi()
        self.pin = pin 
        self.pi.set_PWM_frequency(self.pin, self._freq)
        self.pi.set_PWM_range(self.pin, 10000)      
        self.angle = 0
        self.max_angle = max_angle
        self.min_angle = min_angle
        self.pi.set_PWM_dutycycle(self.pin, 0)

    def set_angle(self, angle):
        if angle > self.max_angle:
            angle = self.max_angle
        elif angle < self.min_angle:
            angle = self.min_angle
        self.angle = angle
        duty = self.map(angle, -90, 90, 250, 1250)
        self.pi.set_PWM_dutycycle(self.pin, duty)


    def get_angle(self):
        return self.angle
    
    def stop(self):
        self.pi.set_PWM_dutycycle(self.pin, 0)
        self.pi.stop()

    # will be called automatically when the object is deleted
    # def __del__(self):
    #     pass

    def map(self, x, in_min, in_max, out_min, out_max):
        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min


if __name__ =='__main__':
    from vilib import Vilib
    # Vilib.camera_start(vflip=True,hflip=True) 
    # Vilib.display(local=True,web=True)

    pan = Servo(pin=13, max_angle=90, min_angle=-90)
    tilt = Servo(pin=12, max_angle=30, min_angle=-90)
    panAngle = 0
    tiltAngle = 0
    pan.set_angle(panAngle)
    tilt.set_angle(tiltAngle)
    sleep(1)

    while True:
        for angle in range(0, 90, 1):
            pan.set_angle(angle)
            tilt.set_angle(angle)
            sleep(.01)
        sleep(.5)
        for angle in range(90, -90, -1):
            pan.set_angle(angle)
            tilt.set_angle(angle)
            sleep(.01)
        sleep(.5)
        for angle in range(-90, 0, 1):
            pan.set_angle(angle)
            tilt.set_angle(angle)
            sleep(.01)
        sleep(.5)

  1. 在文件目录中输入python face_tracking_noPID.py ,即可实现对人脸对象自动追踪
<think>好的,我现在需要帮助用户找到如何使用Picamera2OpenCV树莓派上编写录制视频的Python代码示例。首先,我得回忆一下用户提供的引用内容,看看有没有相关的信息。 用户提到了引用[2]和引用[4],其中引用[2]提到了Picamera2类和Preview类,以及time模块。引用[4]则指出树莓派专用CSI摄像头在OpenCV中直接使用cv2.VideoCapture(0)会出现问题,可能需要其他方法。这说明用户可能需要通过Picamera2库来捕获视频流,然后结合OpenCV进行处理和保存。 接下来,我需要确认如何将Picamera2的视频流传递给OpenCV。根据之前的经验,Picamera2可以配置摄像头并捕获帧,然后将这些帧转换为OpenCV可以处理的格式,比如numpy数组。用户之前可能使用过imdecode来处理静态图像,但视频需要连续捕获帧。 然后,视频录制的部分需要使用OpenCV的VideoWriter类。需要设置正确的编解码器(比如MJPG或H264)、帧率和分辨率。同时,要确保树莓派上安装了对应的编解码器支持。用户提到的引用[3]中安装的依赖项可能包括必要的编解码器,但可能需要确认。 另外,用户可能还需要在代码中实现开始录制、逐帧写入和停止录制的逻辑。需要注意正确释放资源,比如在结束时关闭VideoWriter和停止摄像头。 最后,可能需要处理一些常见的陷阱,比如确保帧的大小VideoWriter的设置匹配,颜色空间的转换(因为OpenCV默认使用BGR,而Picamera2可能输出RGB或其他格式),以及性能优化,避免丢帧。 现在,综合这些信息,我应该提供一个示例代码,展示如何初始化Picamera2,配置预览,捕获帧,转换为OpenCV格式,然后使用VideoWriter保存视频。同时,添加必要的注释,解释每个步骤的作用,并提醒用户可能的注意事项,比如安装依赖、摄像头权限、编解码器选择等。</think>以下是如何使用Picamera2OpenCV树莓派上录制视频的代码示例及说明: ```python from picamera2 import Picamera2 import cv2 import time # 初始化Picamera2并配置参数 picam2 = Picamera2() video_config = picam2.create_video_configuration( main={"size": (640, 480), "format": "RGB888"}, controls={"FrameRate": 30} ) picam2.configure(video_config) # 创建OpenCV视频写入器 fourcc = cv2.VideoWriter_fourcc(*'MJPG') # 或使用'H264'编码 out = cv2.VideoWriter('output.avi', fourcc, 30.0, (640, 480)) # 开始捕捉 picam2.start() start_time = time.time() try: while time.time() - start_time < 10: # 录制10秒 frame = picam2.capture_array("main") # 获取numpy数组格式帧 frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 转换颜色空间 out.write(frame) # 可选:实时预览 cv2.imshow('Preview', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break finally: # 释放资源 out.release() picam2.stop() cv2.destroyAllWindows() ``` 关键点说明: 1. 通过`create_video_configuration`设置视频参数时: - `format`必须OpenCV兼容,推荐使用`RGB888`或`BGR888` - 帧率设置应VideoWriter参数一致[^2] 2. 颜色空间转换: - Picamera2默认输出RGB格式,而OpenCV使用BGR格式 - 必须通过`cv2.cvtColor`进行转换才能正确显示颜色[^1] 3. 编解码器选择: - 树莓派推荐使用`MJPG`或`H264`编码 - 需要确保已安装对应编码器:`sudo apt install libopenjp2-7 libh264-155`[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值