草庐IT

树莓派+MediaPipe+PCA9685+自制摄像机云台实现人脸跟踪移动

rikeilong 2023-06-15 原文

目录


前言

博主闲得无聊,利用某宝几十块钱的机械臂自制了一个摄像头云台,使用了两个MG90S舵机和一块PCA9685驱动的16路舵机扩展板,再通过谷歌的MediaPipe库实现摄像机跟随人脸移动的功能,代码十分简单,快来给你的树莓派添加一个新玩法吧~


一、准备材料

①树莓派(这个肯定需要有的)

②摄像头

③PCA9685驱动的16路舵机扩展板(关于这部分的教程可以百度或谷歌一下,建议先调试成功后再开始这个项目,不然容易把舵机烧坏)


④舵机

⑤制作云台的工具(我是用某宝买的四自由度亚克力机械臂拆出来做的)


二、代码部分

前言

代码经过测试,Mediapipe项目部署在树莓派上的视频帧率只有十几帧左右,如果真的想流畅运行,就需要借助MJPG-streamer工具传输树莓派上的摄像头视频到PC端,然后在PC端进行脸部识别,这样可以实现几乎0延迟传输并控制云台移动,且PC端运算能力强,可以做更多处理。

具体实现步骤可以进这篇某乎上看看👇
树莓派利用MJPG-streamer传输摄像头视频


1.引入库

Mediapipe

sudo pip3 install mediapipe-rpi3

如果是4版本则使用用命令:

sudo pip3 install mediapipe-rpi4

导入控制舵机的PCA驱动(这部分工作可以网上搜一下“树莓派PCA控制舵机”)

sudo pip install adafruit-pca9685


2.客户端(即PC端)

client.py 用于定义客户端

import socket

class connect_Raspberry():
    def __init__(self,host,port):
        print("客户端开启")
        # 套接字接口
        self.mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置ip和端口

        try:
            self.mySocket.connect((host, port))  #连接到服务器
            print("连接到服务器")
        except:  #连接不成功,运行最初的ip
            print('连接RASP不成功')

    def send(self, words):
        # 发送消息
        msg = words
        # 编码发送
        self.mySocket.send(msg.encode("utf-8"))
        # print("成功发送消息")

    def close(self):
        self.mySocket.close()
        print("与树莓派丽连接中断\n")
        exit()


main.py 用于接收树莓派视频以及人脸识别,并发送识别位置到树莓派

import cv2
import mediapipe as mp
import numpy as np

import client

#检测脸部
mp_face_detection = mp.solutions.face_detection
mp_drawing = mp.solutions.drawing_utils

#通信传输
myRaspConnection = client.connect_Raspberry('你的树莓派ip', 8888)


if __name__ == "__main__":

    capture = cv2.VideoCapture("http://你的树莓派ip:8080/?action=stream")

    ref, frame = capture.read()
    fps = 0.0

    while(True):

        ref, frame = capture.read()
        h,w,_ = np.shape(frame)
        if not ref:
            break
        image = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

        #脸部检测
        with mp_face_detection.FaceDetection(model_selection=0, min_detection_confidence=0.8) as face_detection:
            results = face_detection.process(image)

            if results.detections:
                for detection in results.detections:
                    box=detection.location_data.relative_bounding_box
                    #cx,cy,cw,ch=box
                    cx=box.xmin
                    cy=box.ymin
                    cw=box.width
                    ch=box.height
                    
                    cv2.rectangle(image, (int(cx*w) , int(cy*h)), (int((cx+cw)*w) , int((cy+ch)*h)),(0, 255, 0), 2)
                
                #控制云台
                msg = str(int(cx*w)) + " " + str(int(cy*h)) + " " + str(int((cx+cw)*w)) + " " + str(int((cy+ch)*h))
                myRaspConnection.send(msg)



        frame = cv2.cvtColor(image,cv2.COLOR_RGB2BGR)
        # cv2.rectangle(frame, (int(cx*w) , int(cy*h)), (int((cx+cw)*w) , int((cy+ch)*h)),(0, 255, 0), 2)  
        
        cv2.imshow("video",frame)
        c= cv2.waitKey(1) & 0xff 

        if c==27:
            capture.release()
            break
    print("Video Detection Done!")
    capture.release()
    cv2.destroyAllWindows()


3.服务端(即树莓派端)

sever.py 用于定义服务端

import socket

print("服务开启")
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "你的树莓派ip"
port = 8888 #自己定义的端口号

mySocket.bind((host, port))
mySocket.listen(10)

main.py 用于接收pc端的人脸位置信息,并控制云台移动

import time
import sever
import Adafruit_PCA9685
 
def set_servo_angle(channel, angle):#输入角度转换成12^精度的数值
    date=int(4096*((angle*11)+500)/20000)#进行四舍五入运算 date=int(4096*((angle*11)+500)/(20000)+0.5)    
    pwm.set_pwm(channel, 0, date)

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(50)

if __name__ == '__main__':
    print("等待连接")
    client,address = sever.mySocket.accept()
    print("新连接")
    print("IP is %s" % address[0])
    print("port is %d\n" % address[1])
    
    beangle = 100 #每个人的初始角度不同,建议先自己测试好角度
    beangle0 = 60

	#舵机插的通道口
    channel1 = 4 #上下
    channel2 = 8 #左右
	
	#变化幅度(这个越大,舵机动的幅度就越大)
    angleFreq = 1
	#超出屏幕范围(这个调大后,脸部离视频边界检测更灵敏)
 	changeFreq = 20
 	
    #初始化角度
    set_servo_angle(channel1,beangle)
    set_servo_angle(channel2,beangle0)
    
    while True:
        msg = client.recv(1024)
        msg = msg.decode("utf-8")
        if msg != "":
            mess = msg.split(' ')
            
            x0 = int(mess[0])#左上角x
            y0 = int(mess[1])#左上角y
            x1 = int(mess[2])#右下角x
            y1 = int(mess[3])#右下角y

			#超出屏幕外
            if x0 < changeFreq:
                beangle += angleFreq
                if beangle >= 180:
                    beangle = 180
                set_servo_angle(channel1,beangle)
            
            if y0 < changeFreq:
                beangle0 += angleFreq
                if beangle0 >= 180:
                    beangle0 = 180
                set_servo_angle(channel2,beangle0)

            if x1 > 640 - changeFreq: #窗口宽为640
                beangle -= angleFreq
                if beangle <= 30:
                    beangle = 30
                set_servo_angle(channel1,beangle)
            
            if y1 > 480 - changeFreq: #窗口高为480
                beangle0 -= angleFreq
                if beangle0 <= 30:
                    beangle0 = 30
                set_servo_angle(channel2,beangle0)

演示

B站演示

有关树莓派+MediaPipe+PCA9685+自制摄像机云台实现人脸跟踪移动的更多相关文章

  1. 萤石开放平台——怎么通过API接口远程添加摄像头? - 2

    高科技摄像头特别是海康萤石摄像头,已经不再只局限于简单的视频功能,特别是智能AI的普及,摄像头也华丽变身成了一个个独立的智能个体,可以实现人脸抓拍,人形检测,客流统计等店铺值守场景,也可以实现安全帽识别,车辆识别,非法入侵识别等智慧工地场景。但用户也许会问,摄像头又不会说话,他得知的这些信息怎么告诉我们,还是说需要配一个主机去处理,这成本又有点太高了。这点正是萤石云要为大家解决的,下面来介绍下如何让设备更简便智能的说话。API(应用程序编程接口)提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力。形象一点API可以理解为一个管道,通过该管道,可以传入约定好的命令,来获得摄像头的反馈,

  2. ruby - 录像机不录制磁带 - 2

    我有一个非常简单的模块,我正在使用VCRgem对Ruby进行测试。我已经根据文档配置了VCR,但似乎无法在cassette目录中获取要录制的磁带。为了以防万一,我什至将cassette目录的权限更改为777。真正奇怪的是,我已经完全删除了cassette目录,运行specs,然后创建了一个新的cassette目录。我正在使用Typhoeus0.4.2和Hydra。我目前无法升级Typhoeus。相关代码:require'rspec'require'vcr'require_relativeFile.join("..","crawl_handler")VCR.configuredo|c|c

  3. (问题解决)(自制脚本)Ubuntu20.04 键盘会突然失灵、键盘延迟突然很大怎么办 - 2

    问题描述:最近在写毕业论文,代码在ubuntu上跑的,得一边跑代码,一边写论文。但用一段时间,或者电脑静置一段时间后,键盘输入延迟突然变得很大,这期间鼠标是正常的,只是输不了字,得等几分钟才能恢复正常,非常耽误时间。解决方法后来参考下面这篇博客,说是ibus拼音输入法的问题,重启一下就行。ubuntuibus输入法突然无法输入(延迟过高)解决方法_q779的博客-CSDN博客_ubuntu键盘无法输入重启方法:终端输入"ibusrestart",键盘又可以正常使用了。ibusrestart自制脚本方法但是问题又来了,键盘有问题,输入延迟大,这样就没法在终端输入重启命令。因此我写了个脚本方式,每

  4. ruby - 带 capybara -webkit 的录像机 - 2

    我正在使用capybara-webkit来测试与第三方网站的集成(我需要javascript)。我想使用vcr来记录在集成测试期间发出的请求,但capybara-webkit不通过nethttp,因此vcr无法记录它们。我将如何着手编写一个允许我记录请求的vcr适配器? 最佳答案 不幸的是,VCR与capybara-webkit非常不兼容。事实上,capybarawebkit正在使用webkit,它是在c中。作为VCR基础的Webmock和Fakeweb只能用于Rubyweb请求。让两者协同工作可能是一项艰巨的任务。我用两种方法解决

  5. javascript - 使用网络摄像头捕捉图像 - 2

    我正在使用Asp.netMVC4开发一个项目。我需要用网络摄像头拍照。此应用程序应该可以配置为任何平板电脑。目前在台式机上运行该应用程序,在平板电脑上没有。我正在使用jscam.swf和jscam_canvas_only.swf。在平板电脑上,我在这些设备上使用SamsungGalaxy安装adobeflashplayer无法正常工作...有人知道其他一些拍照技术,或者如果有人可以帮助我解决这个问题,我将不胜感激 最佳答案 Flash在Android平板电脑上的支持有限,在iOS设备上不支持。更好的解决方案可能是转向100%HTML

  6. javascript - WebRTC/getUserMedia API 教程 - 多个摄像头 - 2

    有谁知道可以让两个用户通过网络摄像头相互连接的WebRTC/getUserMediaAPI脚本的好教程?一个恰当的例子应该是Chatroulette,只是它不需要那么大。并且应该可以在本地主机上创建它。希望有人能帮帮我! 最佳答案 使用SimpleWebRTC与Signallingserver实现你的目标。在mainsite找到更多信息您将需要nodejs来运行信令服务器,或者您可以使用simplewebrtcsignallingserver用于测试目的。虽然屏幕共享仅适用于HTTPS。工作DEMOSimpleWebRTCDemoS

  7. javascript - 水平翻转 .​​getUserMedia 的网络摄像头图像流 - 2

    所以我一直在搞乱这个页面:https://tutorialzine.github.io/pwa-photobooth/基本上它的作用是激活您的网络摄像头并让您直接从流中拍摄快照,我为我的网络借用了它,但视频流被翻转了,我想镜像视频流以便感觉更好。注意:我是一个js新手,所以欢迎详细解释。这是代码,您可能必须使用Firefox而不是Chrome:$('.closecam').click(function(){$('.webcam__overlay').hide();}); $('.camera').click(function(){$('.webcam__overlay').show()

  8. javascript - 如何使对象在 three.js 场景中仅对一个摄像机可见 - 2

    我使用three.js创建了一个用于3D场景的嵌入式轨迹球相机Controller。目前,这使用一个小立方体、一个圆和一个放置在世界原点的正交相机。然而,这三个对象在场景本身中仍然可见,如通过主摄像机所见。(在我下面的演示代码中,我特意将立方体设为10x10x10,以便清晰可见,但它可以做得更小。)此外,作为主场景一部分的穿过原点的元素在插图中可见。例如:插图中可以看到属于主场景的AxisHelper。是否可以在three.js/webgl中使某些对象仅对某些相机可见?如果没有,那么一个解决方法是将轨迹球功能所需的对象放置在远离深空的地方,主摄像头看不到它们,但如果可能的话我更喜欢更纯

  9. javascript - 在树莓派上使用 node.js 进行和弦音频播放 - 2

    我一直在尝试在运行最新raspbian的树莓派3上使用node.js创建和弦WAV播放:shellingouttoaplay/mpg123/someotherprogram-让我一次只能播放一个声音我尝试了https://github.com/sebpiq/node-web-audio-api的组合和https://github.com/TooTallNate/node-speaker(下面的示例代码)但音频质量很低,有很多失真这里有什么我遗漏的吗?我知道我可以用另一种编程语言轻松地做到这一点(我能够用SDL编写C++代码,用pygame编写Python),但问题是node.js是否可

  10. 基于树莓派的智能家居设计 - 2

    文章目录前言一、整体系统框图二、代码部分二、APP客户端1.MainActivity.java2.NetUtils.java三、实物展示前言一个简易的小项目,以下是代码部分和实物效果展示。一、整体系统框图二、代码部分main.c#include#include#include#include#include#include#include#include#include#include#include#include#include#include"contrlDevices.h"#include"inputCommand.h"pthread_tvoiceThread; //注意:定义线程不使

随机推荐