树莓派简易人脸追踪云台

前言:

这篇文章属于此系列:

一个用树莓派做的会聊天,能人脸识别(支持云台追踪)和发送邮件的小玩具

https://blog.csdn.net/yonglisikao/article/details/82804318

硬件

树莓派及基本配件,摄像头(Picamera或Webcam),双舵机小云台

语言

Python

云台控制

请参考这篇文章:

http://shumeipai.nxez.com/2018/06/21/pan-tilt-multi-servo-control.html

算法设计

我想到的算法是:

1.拍一张照片;

2.确定照片里脸的中心到照片中心的水平和垂直距离;

3.照片里的距离与实际的角度有一定的对应关系,根据这个关系得到相应的角度;

4.控制云台转动相应的角度,实现人脸追踪。

算法实现

脸位置的确定:使用face_recognition库里的face_locations()函数,这个函数在我的其他文章里介绍过,它能够返回一个元组类型的数据,具体信息是这样的:(上,右,下,左)到图片右上顶点的距离,单位是像素。分别把上下和左右取平均即得到脸中心的位置。

对应关系的确定:因为我们要实现简易的人脸追踪,所以对精度要求不高。假设它们是线性关系,即

α(角度) = k(比例系数) * d(距离)

然后我们来确定比例系数,如果你知道你使用的摄像头的视野角度,直接用视野角度除以照片的对应维度的像素点的数量即得到比例系数,即

k(比例系数) = β(视野角度) / D(对应维度的像素点的个数)

如果不知道,可以像我这样粗略估计一下

1.制作一个像下图这样的东西,像对准待测摄像头;

2.用待测摄像头拍一张照片,如下图;

3.根据拍摄的照片,像下图这样作图,并测出角度,我得到的视野角度大致是50°;

4.我用摄像头拍摄的照片的分辨率是640×480,因为我刚测的水平的视野角度,所以像素点的个数取640;

5.50 / 640 = 0.078125 就是所求的比例系数。

具体代码

需要注意,你可能会想在while语句前创建视频对象,然后在每次循环中读取一次,但是因为它实际上堆积了之前的数据,也就是说,它会读到很久之前的数据,而我们希望它读到实时的数据,所以我们只能在每次循环中都创建然后释放对象,这导致差不多一秒才能读取一次数据,将来或许可以想到其他办法来解决速度的问题。

# coding = utf-8
import face_recognition
import cv2
import RPi.GPIO as GPIO
import time

def setServoAngle(servo, angle):
    '''
    :param servo 控制舵机的引脚编号,这取决于你,我用的分别是17和27
    :param angle 舵机的位置,范围是:0到180,单位是度
    return: None
    '''
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(servo, GPIO.OUT)
    pwm = GPIO.PWM(servo, 50)
    pwm.start(8)
    dutyCycle = angle / 18. + 3.
    pwm.ChangeDutyCycle(dutyCycle)
    time.sleep(0.3)
    pwm.stop()
    GPIO.cleanup()


# 设置舵机的初始位置
x0, y0 = 80, 30
setServoAngle(27, x0)
setServoAngle(17, y0)

while True:
    # 创建视频对象,打开摄像头
    video_capture = cv2.VideoCapture(0)
    ret, pframe = video_capture.read()
    # 释放视频对象
    video_capture.release()
    frame = cv2.resize(pframe, (0, 0), fx=0.25, fy=0.25)  # 这里将分辨率缩小为1/4,故比例系数增大为4倍,现在是0.078125*4 = 0.3125
    output = frame[:, :, ::-1]
    
    # 确定脸的位置
    face_locations = face_recognition.face_locations(output)
    if face_locations:
        x = (face_locations[0][1] + face_locations[0][3])/2
        y = (face_locations[0][0] + face_locations[0][2])/2
        print(x, y)  # 输出脸中心到右上顶点的水平和垂直距离
    else:
        x, y = 80, 60  # 如果没有脸则让舵机保持不动,相当于脸在中央(这时的分辨率为160*120)
        # 计算出舵机应该移动的角度,正负与你舵机的安装方式有关
    dx = (80 - x) * 0.3125
    dy = -(60 - y) * 0.3125

    if abs(dx) >= 3:  # 设置一个阈值,当角度大于3时,才移动,避免舵机一直在原地抖动,下同
        x0 += dx
        if x0 > 180:  # 设置界限,超出范围不再转动,下同
            x0 = 180
        elif x0 < 0:
            x0 = 0
        setServoAngle(27, x0) # 水平方向的舵机控制
    
    if abs(dy) >= 3:  # 设置阈值
        y0 += dy
        if y0 > 180:
            y0 = 180
        elif y0 < 0:
            y0 = 0
        setServoAngle(17, y0)  # 垂直方向的舵机控制

总结

总体效果:准确度上还不错,速度上较慢。

代码

https://github.com/LoveThinkinghard/Raspibot

  • 17
    点赞
  • 186
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
下面是一个使用OpenCV在树莓派上进行人脸追踪的示例代码: ```python import cv2 # Load the Haar Cascade classifier for face detection face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # Initialize the video capture object cap = cv2.VideoCapture(0) # Set the frame width and height cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: # Read a frame from the video stream ret, frame = cap.read() # Convert the frame to grayscale gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Detect faces in the grayscale frame faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5) # Draw bounding boxes around the detected faces for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # Display the resulting frame cv2.imshow('Face Tracking', frame) # Wait for a key press and check if it is the 'q' key to exit if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the video capture object and close all windows cap.release() cv2.destroyAllWindows() ``` 在上述代码中,我们首先加载了OpenCV的人脸检测分类器,然后初始化了一个视频捕捉对象。在每个循环迭代中,我们读取一帧视频流,并将其转换为灰度图像。然后,我们使用分类器检测灰度图像中的所有人脸,并在每个检测到的人脸周围绘制矩形边界框。最后,我们显示带有矩形边界框的帧,并等待用户按下“q”键退出。 请注意,上述代码只是一个简单的示例,可能需要根据您的具体需求进行修改和调整。例如,您可能需要调整分类器的参数以提高检测精度,或者使用多个分类器来检测不同角度和大小的人脸
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值