精华内容
下载资源
问答
  • 2020-3-16 之前舵机开门关门逻辑有点混乱,不太合乎常理,现对树莓派人脸识别代码进行修改,以及对Arduino控制代码有所调整;在上一篇文章中小雨:树莓派调用百度人脸识别API实现人脸识别​zhuanlan.zhihu.com我们...

    ea8449c6ca84c79fac2ee7b18a591735.png

    2020-3-16 之前舵机开门关门逻辑有点混乱,不太合乎常理,现对树莓派人脸识别代码进行修改,以及对Arduino控制代码有所调整;


    在上一篇文章中

    小雨:树莓派调用百度人脸识别API实现人脸识别​zhuanlan.zhihu.com
    c2b859fabf31d7eb14be56c71cda2a6c.png

    我们完成了树莓派人脸识别的基础环境配置,人脸识别功能也测试成功了,现在我们做一个小小的案例来实际应用一下,我们想树莓派人脸识别成功后,发送蓝牙串口数据给Arduino的HC-05模块,让Arduino控制舵机开门。

    准备

    设备材料

    • 树莓派3b
    • Arduino UNO R3
    • HC-05
    • 舵机SG90(或者MG995)
    • 杜邦线若干

    连接图

    e8d963f748cbd50f18ac11000f60ae41.png

    一、树莓派端配置

    树莓派自带蓝牙功能,我们可以调用系统指令发送蓝牙信号,

    1.1 安装树莓派蓝牙模块pybluez

    安装完成后再继续下一步操作; 若想让树莓派使用bluetooth,必须给树莓派安装pybluez模块

    sudo 

    1.2 将树莓派手动连接至HC-05

    打开树莓派桌面端,点击蓝牙图标后点击add device

    45427f3a198718d4dac1d1497562848e.png

    选择HC-05模块,配对密码是1234;

    92b2b33d91c106c021bdc69243da4607.png

    配对成功后,后面程序就可以直接运行了

    1.3 定义树莓派蓝牙控制功能

    创建一个bluetooth_test.py文件,分别定义初始化指令、开门指令、关门指令,分别发送字符串’1‘,’2’,‘3’;

    import 

    二、Arduino连接方式

    2.1 Arduino与HC-05蓝牙模块的连接

    由于我们用的是Arduino UNO R3没有蓝牙模块,要接收蓝牙数据,可以通过外接HC-05蓝牙模块解决。

    HC-05===Arduino

    • RXD<==>TX
    • TXD<==>RX
    • VCC<==>5v
    • GND<==>GND

    注意:HC-05的vcc一定要接5v,如果接3.3v,虽然可以亮灯工作,但是接收一次数据后会自动断开连接,刚开始我找半天没找到原因,原来是电压给低了,这是一个小细节要注意一下。

    2.2 Arduino与舵机模块的连接

    SG90 舵机导线三种颜色,含义分别是: 棕色:GND 红色:VCC

    黄色:DATA

    舵机SG90===Arduino

    • DATA<==>D9
    • VCC<==>5v
    • GND<==>GND

    三、Arduino控制代码

    创建工程烧录到Arduino开发板中即可

    #include 

    四、树莓派控制代码

    按照上一篇文章,我们的树莓派已经准备妥当了,在test.py的基础上,我们再修改一下:

    # 2020-3-16修正版本
        

    注意:

    运行程序后,如果报错

        bluetooth.btcommon.BluetoothError: [Errno 112] Host is down 

    你则需要回到桌面端,将树莓派与HC-05重新配对一下,再运行一下就好了。

    最后

    至此,当我们运行该代码,把脸凑到摄像头前,舵机自动开门,把脸移开则舵机自动关门,智能门禁系统就做好啦!


    我还拍了一个演示效果的视频

    5fa2bbd590bf378e448ab243a1c1592b.png
    家庭环境监测演示视频_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
    9dbc8189bb2481f05200502452f34d96.png

    配套视频教程:

    树莓派人脸识别门禁系统快速上手系列教程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
    d4781346883902066461d555e021aace.png

    全部代码开源在GitHub上:

    源码GitHub地址​github.com

    440281db17e9bf098d1790e069c5772d.png

    点个赞再走?

    展开全文
  • 树莓派人脸识别树莓派人脸识别
  • 树莓派人脸识别实际应用:人脸识别门禁

    千次阅读 多人点赞 2020-02-27 16:07:59
    在上一篇文章树莓派调用百度人脸识别API实现人脸识别,我们完成了树莓派人脸识别的基础环境配置,人脸识别功能也测试成功了,现在我们做一个小小的案例来实际应用一下,我们想树莓派人脸识别成功后,发送蓝牙串口...

    2020-3-16 之前舵机开门关门逻辑有点混乱,不合乎常理,现对树莓派人脸识别代码进行修改,以及Arduino控制代码有所调整;


    在上一篇文章树莓派调用百度人脸识别API实现人脸识别,我们完成了树莓派人脸识别的基础环境配置,人脸识别功能也测试成功了,现在我们做一个小小的案例来实际应用一下,我们想树莓派人脸识别成功后,发送蓝牙串口数据给Arduino的HC-05模块,让Arduino控制舵机开门。
    ###准备
    #####设备材料

    • 树莓派3b
    • Arduino UNO R3
    • HC-05
    • 舵机SG90(或者MG995)
    • 杜邦线若干
      #####连接图
      连接图.png

    ###一、树莓派端配置
    树莓派自带蓝牙功能,我们可以调用系统指令发送蓝牙信号,

    1.1安装树莓派蓝牙模块pybluez

    安装完成后再继续下一步操作;
    若想让树莓派使用bluetooth,必须给树莓派安装pybluez模块

    sudo apt-get install libbluetooth-dev  //安装蓝牙开发库
    python3 -m pip install pybluez    //安装pybluez
    
    1.2 将树莓派手动连接至HC-05

    打开树莓派桌面端,点击蓝牙图标后点击add device
    图片.png
    选择HC-05模块,配对密码是1234;
    图片.png

    配对成功后,后面程序就可以直接运行了

    1.3 定义树莓派蓝牙控制功能

    创建一个bluetooth_test.py文件,分别定义初始化指令、开门指令、关门指令,分别发送字符串’1‘,’2’,‘3’;

    import bluetooth
     
    def servo_init():#初始化指令
    	bd_addr = "20:16:08:08:39:75" #arduino连接的蓝牙模块的地址
    	port = 1
    	 
    	sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
    	sock.connect((bd_addr, port)) #创建连接
    	 
    	sock.send("1") #发送数据
    	sock.close()  #关闭连接
    	
    def bt_open():#开门指令
    	bd_addr = "20:16:08:08:39:75" 
    	port = 1
    	 
    	sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
    	sock.connect((bd_addr, port)) 
    	 
    	sock.send("2") 
    	sock.close()  
    
    def bt_close():#关门指令
    	bd_addr = "20:16:08:08:39:75" 
    	port = 1
    	 
    	sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
    	sock.connect((bd_addr, port)) 
    	 
    	sock.send("3") 
    	sock.close()  	
    

    ###二、Arduino连接方式
    #####2.1 Arduino与HC-05蓝牙模块的连接
    由于我们用的是Arduino UNO R3没有蓝牙模块,要接收蓝牙数据,可以通过外接HC-05蓝牙模块解决。


    HC-05===Arduino

    • RXD<==>TX
    • TXD<==>RX
    • VCC<==>5v
    • GND<==>GND

    注意:HC-05的vcc一定要接5v,如果接3.3v,虽然可以亮灯工作,但是接收一次数据后会自动断开连接,刚开始我找半天没找到原因,原来是电压给低了,这是一个小细节要注意一下。
    #####2.2 Arduino与舵机模块的连接
    SG90 舵机导线三种颜色,含义分别是:
    棕色:GND
    红色:VCC
    黄色:DATA

    舵机SG90===Arduino

    • DATA<==>D9
    • VCC<==>5v
    • GND<==>GND

    ###三、Arduino控制代码
    创建工程烧录到Arduino开发板中即可

    #include <Servo.h>
    Servo myservo;  
    
    void setup() {
      mySerial.begin(9600); //监听软串口
      myservo.attach(9); //舵机控制
      myservo.write(0);
    //  delay(10000); 
    }
    
    void loop() {
      while(Serial.available())
      {
        char c;
        c = Serial.read();  //读取串口数据
        Serial.println(c);
        switch(c)
        {
          case '1':servo_init();
          break;
          case '2':open_the_door();
          break;
          case '3':close_the_door();
        }
      }
    
    }
    
    
    void open_the_door()  //舵机开门
    {
      myservo.write(170);
    }
    void close_the_door()  //舵机关门
    {
      myservo.write(0);
    }
    void servo_init()  //舵机初始化
    {
      myservo.write(10);
    }
    

    ###四、树莓派控制代码
    按照上一篇文章,我们的树莓派已经准备妥当了,在test.py的基础上,我们再修改一下:

    # 2020-3-16修正版本
    from aip import AipFace
    from picamera import PiCamera
    import urllib.request
    import RPi.GPIO as GPIO
    import base64
    import time
    import bluetooth
    
    from bluetooth_test import bt_open,servo_init,bt_close
    
    
    #百度人脸识别API账号信息
    APP_ID = '18332624'
    API_KEY = '2QoqxCzAsZGT9k5CMeaIlPBs'
    SECRET_KEY ='9wOlqd4sPvLc7ZKtLxMlBVkcikXHZ4rz'
    client = AipFace(APP_ID, API_KEY, SECRET_KEY)#创建一个客户端用以访问百度云
    #图像编码方式
    IMAGE_TYPE='BASE64'
    camera = PiCamera()#定义一个摄像头对象
    #用户组
    GROUP = 'yusheng01'
     
    #照相函数
    def getimage():
        camera.resolution = (1024,768)#摄像界面为1024*768
        camera.start_preview()#开始摄像
        time.sleep(2)
        camera.capture('faceimage.jpg')#拍照并保存
        time.sleep(2)
    #对图片的格式进行转换
    def transimage():
        f = open('faceimage.jpg','rb')
        img = base64.b64encode(f.read())
        return img
    #上传到百度api进行人脸检测
    def go_api(image):
        result = client.search(str(image, 'utf-8'), IMAGE_TYPE, GROUP);#在百度云人脸库中寻找有没有匹配的人脸
        if result['error_msg'] == 'SUCCESS':#如果成功了
            name = result['result']['user_list'][0]['user_id']#获取名字
            score = result['result']['user_list'][0]['score']#获取相似度
            if score > 80:#如果相似度大于80
                if name == 'yin_danli':
                    print("欢迎%s !" % name)
                    time.sleep(1)
                if name == 'danli':
                    print("欢迎%s !" % name)
                    time.sleep(3)
                if name == "yusheng_02":
                    print("欢迎%s !" % name)
                    time.sleep(3)
         
            else:
                print("对不起,我不认识你!")
                name = 'Unknow'
                return 0
            curren_time = time.asctime(time.localtime(time.time()))#获取当前时间
     
            #将人员出入的记录保存到Log.txt中
            f = open('Log.txt','a')
            f.write("Person: " + name + "     " + "Time:" + str(curren_time)+'\n')
            f.close()
            return 1
        if result['error_msg'] == 'pic not has face':
            print('检测不到人脸')
            time.sleep(3)
            return -1
        else:
            print(result['error_code']+' ' + result['error_code'])
            return 0
    #主函数
    if __name__ == '__main__':
        servo_init()    #舵机复位,初始化一次就够了
        while True:
            
            print('准备开始,请面向摄像头 ^_^')
    
            if True:
                getimage()#拍照
                img = transimage()  #转换照片格式
                res = go_api(img)   #将转换了格式的图片上传到百度云
                if(res == 1):   #是人脸库中的人
                    bt_open()
                    print("欢迎回家,门已打开")
                elif(res == -1):
                    print("我没有看见你,我要关门了")
                    time.sleep(3)
                    bt_close()    
                else:
                    print("关门")
                    bt_close()
                time.sleep(3)
                print('好了')
                time.sleep(5)
    
    
    注意:

    运行程序后,如果报错

    bluetooth.btcommon.BluetoothError: [Errno 112] Host is down 
    

    你则需要回到桌面端,将树莓派与HC-05重新配对一下,再运行一下就好了。
    ###最后
    至此,当我们运行该代码,把脸凑到摄像头前,舵机自动开门,把脸移开则舵机自动关门,智能门禁系统就做好啦!


    我还拍了一个演示效果的视频
    效果

    视频演示效果传送门
    视频教程传送门
    源码GitHub地址
    更多内容欢迎关注我的gongzhong号:xiaoxiaoyu1926


    展开全文
  • 树莓派人脸识别,跳帧识别树
  • 树莓派人脸识别门禁

    2021-06-13 11:18:32
    树莓派人脸识别门禁树莓派人脸识别门禁需求环境搭建安装Cmake安装OpenCV安装dlib安装face_recognition人脸检测和跟踪获取视频人脸检测人脸跟踪识别人脸识别方法的选取业务逻辑完整代码和成果展示 树莓派人脸识别门禁...

    树莓派人脸识别门禁需求

    人脸识别门禁应用已经很普及,本文将详细讲述如何用树莓派实现人脸识别门禁应用。需要实现功能有两个:
    1.检测人脸,绘制识别框,并实时跟踪
    2.识别人脸

    环境搭建

    在树莓派中实现人脸识别,使用编程语言为python,版本可以是python2也可以是python3。需要用到opencvface_recognition库。

    安装Cmake

    在安装opencvface_recognition之前,要确认树莓派中是否已经安装了较新版本的cmake,使用以下指令安装最新版本的cmake

    sudo apt install cmake
    

    安装OpenCV

    如果是基于python2,且安装了pip,那么直接时使用以下指令即可安装:

    sudo pip install opencv-python  -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    如果是使用python3pip3,那么使用以下指令即可:

    sudo pip3 install opencv-python  -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    如果不幸遇到安装失败,有可能最新版本opencv不支持树莓派,可以尝试指定版本。为了避免国外镜像源网速慢的问题,本文的安装都基于清华镜像源。

    sudo pip3 install opencv-python==3.4.3.18  -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    如果是缺失lib依赖,那么需要先安装依赖:

    sudo apt install libatlas-base-dev
     
    sudo apt install libjasper-dev
     
    sudo apt install libqtgui4
     
    sudo apt install libqt4-test
    
    sudo apt install libhdf5-dev
    

    还可以参考cmake 安装 opencv的文章,非常麻烦,而且不容易成功。

    安装dlib

    在安装face_recognition之前需要先安装dlib。为了确定face_recognition需求的dlib版本,可以前往github查看,也可以尝试安装:

    sudo pip install face_recognition #如果为python3记得更换为pip3,本文将不在赘述
    

    虽然安装face_recognition时会自动安装dlib,但是基本不会成功,如果成功了那么得恭喜你,完成了环境搭建这一阶段。否则,需要前往官网下载dlib的对应版本,选择最新版本基本不会错,最低也要超过face_recognition要求的版本。
    dlib官网
    下载到本地后,进行以下几个步骤:

    1. 打开终端输入指令查看虚拟内存大小
     sudo nano /etc/dphys-swapfile
    

    因为安装dlib需要占用较大的内存,如果开着桌面GUI那么本身的1GB内存是不够用的,需要在磁盘中划出一部分作为虚拟内存。默认的虚拟内存大小为100MB是不够用的,如图,会安装dlib失败。
    在这里插入图片描述
    建议改为2048MB,如果你开着GUI进行dlib的安装。改完后,Ctrl+O保存,再输入回车,Ctrl+X退出。

    1. 更新虚拟内存配置
    sudo /etc/init.d/dphys-swapfile stop
    sudo /etc/init.d/dphys-swapfile start
    
    1. 解压下载的dlib文件并进入解压后的文件夹
    sudo python setup.py install
    
    1. 耐心等待即可,安装及其耗时,可先去喝一杯咖啡。

    安装face_recognition

    由于前面的步骤,到了这一步非常简单,只需要输入以下指令即可。

    sudo pip install face_recognition
    

    检查是否安装好了:

    pip list
    

    到此,环境搭建就完成了,如果不想看我絮叨,那么可以直接跳转到完整代码和成果展示

    人脸检测和跟踪

    获取视频

    一段视频可以看作一帧帧连续的图片。从摄像头中获取视频即获取一帧帧图片,首先程序需要获取摄像头资源,代码如下。

    import cv2
    camera = cv2.VideoCapture(0)
    

    参数0即默认的摄像头,如果有多个摄像头可改为/dev中对应的驱动编号。

    ret,frame = camera.read()
    cv2.flip(frame,1)
    

    frame即从摄像头中读到的图片,由于摄像头的自拍镜像问题,我对他进行了一个水平翻转,可有可无,并不影响结果。

    cv2.imshow("window_name",frame)#窗口名任意
    cv2.waitKey(1)
    

    imshow函数可以将获取到的图片在窗口中显示,树莓派中必须要加上waitKey函数,否则可能创建不了窗口。通过一个while死循环即可不断从摄像头读取一帧帧图片,在window显示,即构成了视频。如果在window上显示的图片数量低于24FPS,则会出现人眼可察的卡顿。这个帧数也是考量性能的一个指标,帧数越高越流畅,识别算法速度越快,性能越好。

    人脸检测

    人脸检测和跟踪的需求就是在图片中找到人脸的位置并标记出来。实现该功能有多种办法:

    1. 利用face_recognition库的函数
    • 检测人脸获取人脸位置,返回值为list类型
    faces = face_recognition.face_locations(frame)
    
    • 在图片上绘制矩形框标识人脸位置
    cv2.rectangle(frame,(faces[0][1],faces[0][0]),(faces[0][3],faces[0][2]),(255,255,0),2)
    
    1. 利用opencv中的haarcascade来实现人脸检测:
    • 首先加载harr级联分类器xml模型,可在github中下载,也可自行训练一个模型。
    faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
    
    • 人脸检测
    def get_faces(frame):
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)#将图片转为灰度图,减少计算量
        faces = faceCascade.detectMultiScale(gray)
        return faces, frame
    
    • 在图片上绘制矩形框标识人脸位置
     cv2.rectangle(img, (faces[0][0],faces[0][1]),(faces[0][2]+faces[0][0],faces[0][3]+faces[0][1]),(255,255,0),2)
    

    小结:face_recognition是基于神经网络模型,而harr级联分类器则可以理解为:

    Haar分类器 = Haar-like特征 + 积分图方法 + AdaBoost +级联;
    a) 使用Haar-like特征做检测。
    b) 使用积分图(IntegralImage)对Haar-like特征求值进行加速。
    c) 使用AdaBoost算法训练区分人脸和非人脸的强分类器。
    d) 使用筛选式级联把分类器级联到一起,提高准确率。

    harr级联分类器存在重识别和误识别较高的问题,即一张人脸识别多次和非人脸识别为人脸,在此统称为错误率(漏识别此处不考虑)。错误率可参见harr级联分类器github上的几个xml模型的比较

    人脸跟踪

    实现了在图片上的人脸检测,还需进一步实现视频上的人脸跟踪,其最大的难点在于如何在保证视频流畅性的同时,确保跟踪上人脸。这里采用帧数来衡量流畅性。

    1. 单线程
    • harr级联分类器的测试代码:
    import cv2
    import time
    
    
    ######################
    ########config########
    ######################
    
    faceCascade = cv2.CascadeClassifier('/home/pi/haarcascade_frontalface_default.xml')
    start = time.time()
    frame_num = 0 
    
    
    #check the exist and location of the face
    
    def get_faces(frame):
       gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
       faces = faceCascade.detectMultiScale(gray)
       return faces, frame
       
       
    #sign the face location in the image
    
    def sign_faces(img,faces):
      for (x,y,w,h) in faces:
        cv2.rectangle(img, (x,y),(x+w,y+h),(255,0,0),2)
        cv2.imshow("frame",img)
        cv2.waitKey(1)
    
    
    # main function
        
    if __name__ == "__main__":
       camera = cv2.VideoCapture(0)
       while True:
            ret,frame = camera.read()
            faces,frame=get_faces(frame)
            sign_faces(frame,faces)
            frame_num = frame_num+1
            fps = frame_num/(time.time()-start)
            print(fps)
    

    帧数在6-10帧范围内波动,视频出现明显卡顿。
    在这里插入图片描述

    • face_recognition的测试代码:
    import cv2
    import face_recognition
    import time
    
    ######################
    ########config########
    ######################
    
    start = time.time()
    frame_num = 0
    
    
    # check the exist and location of the face
    
    def get_faces(frame):
        faces = face_recognition.face_locations(frame)
        return faces, frame
    
    
    # sign the face location in the image
    
    def sign_faces(img, faces):
        if(len(faces)>0):
            cv2.rectangle(frame, (faces[0][1], faces[0][0]), (faces[0][3], faces[0][2]), (255, 255, 0), 2)
            cv2.imshow("frame", img)
            cv2.waitKey(1)
    
    
    # main function
    
    if __name__ == "__main__":
        camera = cv2.VideoCapture(0)
        while True:
            ret, frame = camera.read()
            faces, frame = get_faces(frame)
            sign_faces(frame, faces)
            frame_num = frame_num + 1
            fps = frame_num / (time.time() - start)
            print(fps)
    

    fps<1,视频和ppt差不多了,但几乎不会出现检测错误(不包含漏识别)的情况。
    小结:单线程在摄像头最大像素的情况下,无法达到24帧每秒,不能满足需求。所以需要通过降低每帧图片像素和抽帧的方式来提高帧数。

    • 降低画质和每4张图片检测一张
    def get_faces(frame):
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = faceCascade.detectMultiScale(gray)
        return faces, frame
    
    
    # sign the face location in the image
    
    def sign_faces(img, faces):
        for (x, y, w, h) in faces:
            cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
            cv2.imshow("frame", img)
            cv2.waitKey(1)
    
    
    # main function
    
    if __name__ == "__main__":
        camera = cv2.VideoCapture(0)
        #降低画质
        camera.set(3,320)
        camera.set(4,240)
    
        i = 0
        while True:
            ret, frame = camera.read()
            if(i==0):
                faces, frame = get_faces(frame)
            sign_faces(frame, faces)
            frame_num = frame_num + 1
            fps = frame_num / (time.time() - start)
            print(fps)
            i=(i+1)%4
    

    帧数跳到了近30,但是由于print函数抢进程的缘故,画面并不显示,注释掉计算fps的代码,视频依然没有达到理想中的流畅程度,帧数的计算存在一定的误差,考虑到人脸识别功能,所以帧数还要有较大的裕量才行。

    • 四线程

    考虑到树莓派是4核的cpu,所以还可以通过多线程来提高帧数。代码有点长就不在此处贴代码了。
    测试结果:帧数并没有想象中那么大的提升,但最主要的是在进行人脸检测时并不会阻塞导致视频卡在某一帧画面,如果采用face_recognition的人脸检测则只能采用多线程,否则无法满足需求。

    识别人脸

    识别方法的选取

    识别人脸同样可以采用harr级联分类器face_recognition两种方法。前者是传统计算机视觉算法,后者是神经网络模型。

    识别速度错误率
    harr<2s较高
    face_recognition约2秒较低

    分析业务逻辑可知,从一个用户开始进入摄像头画面到离开出画为一个识别任务,在同一个识别任务中只需要对其进行一次人脸识别,而非每帧图片都进行人脸识别。那么两种实现方法识别速度的差距并非决定项,而考虑到安全性等需求,错误率则是最关键的考虑因素。所以face_recognition要优于harr级联分类器

    业务逻辑

    在这里插入图片描述

    这样的业务逻辑还解决了harr级联分类器重识别的问题,但对于误识别依旧无法解决。如果树莓派性能较好,可以使用face_recognition进行人脸检测,在多线程+抽帧+降像素的方案下,可以满足视频的流畅性,但在人脸识别时卡顿较为明显。

    完整代码和成果展示

    • config 模块中配置了用户脸的照片(文件夹)的存储路径和xml模型存储路径。
    • Init 模块中的代码功能为读取用户脸的照片,并编码。
    • 注意:用户脸的照片仅支持 jpg 格式,如果有需求可以在 Init 模块中修改代码。
    import multiprocessing as mp
    import cv2
    import face_recognition
    import os
    
    ######################
    ########config########
    ######################
    
    face_path="/home/pi/Pictures"  #your_bface_dir
    faceCascade = cv2.CascadeClassifier('/home/pi/haarcascade_frontalface_default.xml')
    
    
    ######################
    ########Init##########
    ######################
    
    faces = [] # face  list
    names = [] # name  list
    flist = os.listdir(face_path)
    for fstr in flist:
      s = fstr.split('.')
      if s[len(s)-1]=="jpg":
        face = face_recognition.load_image_file(face_path+"/"+fstr) # load jpg file in face_path
        face_code = face_recognition.face_encodings(face)[0]#get face code 
        face_name = s[0]#get face name 
        faces.append(face_code)#put into faces
        names.append(face_name)#put into names
    
    
    
    
    
    #check the exist and location of the face by harr
    #def get_faces(frame):
     #   gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
      #  faces = faceCascade.detectMultiScale(gray)
       # return faces, frame
    
    
    #check the exist and location of the face by face_recognition
    def get_faces(frame):
        
        faces = face_recognition.face_locations(frame)
        return faces, frame
    
    #sign the face location in the image
    def sign_faces(img,faces,name):
        if(len(faces)==1):
          for (x,y,w,h) in faces:
            #cv2.rectangle(img, (x,y),(x+w,y+h),(255,0,0),2)   # harr 用这个
            cv2.rectangle(img, (y,x),(h,w),(255,0,0),2)#face_recognition人脸检测用这行
            if(name!="not a face"):
              # cv2.putText(img,name,(x,y),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)  # harr用这行
               cv2.putText(img,name,(y,x),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)#face_recognition人脸检测用这行
            else:
                name = "not a face"
        cv2.imshow("frame",img)
        cv2.waitKey(1)
    
    #detect face and recognition  
    def face_recog(frame):
    
       name = "not a face"
       #encoding 
       frame_codes = face_recognition.face_encodings(frame)#encoding frame
       # if frmae not face ,skip
       if(len(frame_codes)>0):
         uface_code = frame_codes[0]#get uface code 
         name = "unkonw"
         result = face_recognition.compare_faces(faces,uface_code,tolerance=0.45)
         for index,i in enumerate(result):
           if i:
             name = names[index]
             break
         #show face_location and recognition_result 
       return name
    
    
    
    # main function
        
    if __name__ == "__main__":
        global name
        name = "not a face"
        pool = mp.Pool(processes=4)
        i = 0
        r = [None] * 4 
        facesList = [None] * 4
        frame = [None] * 4
        imageList = [None] * 16
        
        cap = cv2.VideoCapture(0)
        #decrease its scale
        cap.set(3,320)
        cap.set(4,240)
        
        #assignment the process first
        ret,frame[0] = cap.read()    
        r[0] = pool.apply_async(get_faces,[frame[0]])
        ret,frame[1] = cap.read()
        r[1] = pool.apply_async(get_faces,[frame[1]])
        ret,frame[2] = cap.read()
        r[2] = pool.apply_async(get_faces,[frame[2]])
        ret,frame[3] = cap.read()
        r[3] = pool.apply_async(get_faces,[frame[3]])
        
        facesList[0],imageList[0] = r[0].get()
        facesList[1],imageList[4] = r[1].get()
        facesList[2],imageList[8] = r[2].get()
        facesList[3],imageList[12] = r[3].get()
        
        for j in range(4):
            imageList[4*j+1] = imageList[j]
            imageList[4*j+2] = imageList[j]
            imageList[4*j+3] = imageList[j]
            
        while(1):
            #whether to quit
            if cv2.waitKey(1) & 0xFF == ord('q'):
                #cv2.imwrite("camera.jpg",frame) #write image to file
                break
            
            
            if(i==0):
                ret,frame[0] = cap.read()
                r[0] = pool.apply_async(get_faces,[frame[0]])
                sign_faces(imageList[i+1],facesList[0],name)
            elif(i==1):
                ret,frame[0] = cap.read()
                imageList[i] = frame[0]
                sign_faces(imageList[i+1],facesList[0],name)
            elif(i==2):
                ret,frame[0] = cap.read()
                imageList[i] = frame[0]
                sign_faces(imageList[i+1],facesList[0],name)
            
            elif(i==3):
                ret,frame[1] = cap.read()
                imageList[i] = frame[1]
                facesList[1],imageList[i+1] = r[1].get()
                sign_faces(imageList[i+1],facesList[1],name)
            elif(i==4):
                ret,frame[1] = cap.read()
                r[1] = pool.apply_async(get_faces,[frame[1]],)
                sign_faces(imageList[i+1],facesList[1],name)
            elif(i==5):
                ret,frame[1] = cap.read()
                imageList[i] = frame[1]
                sign_faces(imageList[i+1],facesList[1],name)
            elif(i==6):
                ret,frame[1] = cap.read()
                imageList[i] = frame[1]
                sign_faces(imageList[i+1],facesList[1],name)
                
            elif(i==7):
                ret,frame[2] = cap.read()
                imageList[i] = frame[2]
                facesList[2],imageList[i+1] = r[2].get()
                sign_faces(imageList[i+1],facesList[2],name)
            elif(i==8):
                ret,frame[2] = cap.read()
                r[2] = pool.apply_async(get_faces,[frame[2]])
                sign_faces(imageList[i+1],facesList[2],name)
            elif(i==9):
                ret,frame[2] = cap.read()
                imageList[i] = frame[2]
                sign_faces(imageList[i+1],facesList[2],name)
            elif(i==10):
                ret,frame[2] = cap.read()
                imageList[i] = frame[2]
                sign_faces(imageList[i+1],facesList[2],name)
                
            elif(i==11):
                ret,frame[3] = cap.read()
                imageList[i] = frame[3]
                facesList[3],imageList[i+1] = r[3].get()
                sign_faces(imageList[i+1],facesList[3],name)
            elif(i==12):
                ret,frame[3] = cap.read()
                r[3] = pool.apply_async(get_faces,[frame[3]])
                sign_faces(imageList[i+1],facesList[3],name)
            elif(i==13):
                ret,frame[3] = cap.read()
                imageList[i] = frame[3]
                sign_faces(imageList[i+1],facesList[3],name)
            elif(i==14):
                ret,frame[3] = cap.read()
                imageList[i] = frame[3]
                sign_faces(imageList[i+1],facesList[3],name)
                
            elif(i==15):
                ret,frame[0] = cap.read()
                imageList[i] = frame[0]
                facesList[0],imageList[0] = r[0].get()
                if(name=="not a face"):
                    if(len(facesList[0])==1):
                        name = face_recog(imageList[0])
                else:
                    if(len(facesList[0])!=1):
                        name = "not a face"
                sign_faces(imageList[0],facesList[0],name)
                i = -1
            
            i += 1
            
    
        cap.release()
        cv2.destroyAllWindows()  
    
    
    

    结果展示

    zxPi (raspberrypi) - VNC Viewer 2021-06-14 00-09-33

    展开全文
  • 2020-3-16 之前舵机开门关门逻辑有点混乱,不合乎常理,现对树莓派人脸识别代码进行修改,以及Arduino控制代码有所调整;在上一篇文章树莓派调用百度人脸识别API实现人脸识别,我们完成了树莓派人脸识别的基础环境...

    2020-3-16 之前舵机开门关门逻辑有点混乱,不合乎常理,现对树莓派人脸识别代码进行修改,以及Arduino控制代码有所调整;


    在上一篇文章树莓派调用百度人脸识别API实现人脸识别,我们完成了树莓派人脸识别的基础环境配置,人脸识别功能也测试成功了,现在我们做一个小小的案例来实际应用一下,我们想树莓派人脸识别成功后,发送蓝牙串口数据给Arduino的HC-05模块,让Arduino控制舵机开门。

    准备

    设备材料

    • 树莓派3b
    • Arduino UNO R3
    • HC-05
    • 舵机SG90(或者MG995)
    • 杜邦线若干

    连接图

    ca10fbfa1341db30c4765d9362d1c7c6.png

    一、树莓派端配置

    树莓派自带蓝牙功能,我们可以调用系统指令发送蓝牙信号,

    1.1安装树莓派蓝牙模块pybluez

    安装完成后再继续下一步操作; 若想让树莓派使用bluetooth,必须给树莓派安装pybluez模块

    sudo apt-get install libbluetooth-dev  //安装蓝牙开发库python3 -m pip install pybluez    //安装pybluez

    1.2 将树莓派手动连接至HC-05

    打开树莓派桌面端,点击蓝牙图标后点击add device

    31ea92621b9994f0a686de05c9de5353.png

    选择HC-05模块,配对密码是1234;

    ec5b96aa4f854f3c4a07ea6c9c7021e7.png

    配对成功后,后面程序就可以直接运行了

    1.3 定义树莓派蓝牙控制功能

    创建一个bluetooth_test.py文件,分别定义初始化指令、开门指令、关门指令,分别发送字符串’1‘,’2’,‘3’;

    import bluetooth def servo_init():#初始化指令bd_addr = "20:16:08:08:39:75" #arduino连接的蓝牙模块的地址port = 1 sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )sock.connect((bd_addr, port)) #创建连接 sock.send("1") #发送数据sock.close()  #关闭连接def bt_open():#开门指令bd_addr = "20:16:08:08:39:75" port = 1 sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )sock.connect((bd_addr, port))  sock.send("2") sock.close()  def bt_close():#关门指令bd_addr = "20:16:08:08:39:75" port = 1 sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )sock.connect((bd_addr, port))  sock.send("3") sock.close()  

    二、Arduino连接方式

    2.1 Arduino与HC-05蓝牙模块的连接

    由于我们用的是Arduino UNO R3没有蓝牙模块,要接收蓝牙数据,可以通过外接HC-05蓝牙模块解决。


    HC-05===Arduino

    • RXD<==>TX
    • TXD<==>RX
    • VCC<==>5v
    • GND<==>GND

    注意:HC-05的vcc一定要接5v,如果接3.3v,虽然可以亮灯工作,但是接收一次数据后会自动断开连接,刚开始我找半天没找到原因,原来是电压给低了,这是一个小细节要注意一下。

    2.2 Arduino与舵机模块的连接

    SG90 舵机导线三种颜色,含义分别是: 棕色:GND 红色:VCC

    黄色:DATA

    舵机SG90===Arduino

    • DATA<==>D9
    • VCC<==>5v
    • GND<==>GND

    三、Arduino控制代码

    创建工程烧录到Arduino开发板中即可

    #include Servo myservo;  void setup() {  mySerial.begin(9600); //监听软串口  myservo.attach(9); //舵机控制  myservo.write(0);//  delay(10000); }void loop() {  while(Serial.available())  {    char c;    c = Serial.read();  //读取串口数据    Serial.println(c);    switch(c)    {      case '1':servo_init();      break;      case '2':open_the_door();      break;      case '3':close_the_door();    }  }}void open_the_door()  //舵机开门{  myservo.write(170);}void close_the_door()  //舵机关门{  myservo.write(0);}void servo_init()  //舵机初始化{  myservo.write(10);}

    四、树莓派控制代码

    按照上一篇文章,我们的树莓派已经准备妥当了,在test.py的基础上,我们再修改一下:

    # 2020-3-16修正版本from aip import AipFacefrom picamera import PiCameraimport urllib.requestimport RPi.GPIO as GPIOimport base64import timeimport bluetoothfrom bluetooth_test import bt_open,servo_init,bt_close#百度人脸识别API账号信息APP_ID = '18332624'API_KEY = '2QoqxCzAsZGT9k5CMeaIlPBs'SECRET_KEY ='9wOlqd4sPvLc7ZKtLxMlBVkcikXHZ4rz'client = AipFace(APP_ID, API_KEY, SECRET_KEY)#创建一个客户端用以访问百度云#图像编码方式IMAGE_TYPE='BASE64'camera = PiCamera()#定义一个摄像头对象#用户组GROUP = 'yusheng01' #照相函数def getimage():    camera.resolution = (1024,768)#摄像界面为1024*768    camera.start_preview()#开始摄像    time.sleep(2)    camera.capture('faceimage.jpg')#拍照并保存    time.sleep(2)#对图片的格式进行转换def transimage():    f = open('faceimage.jpg','rb')    img = base64.b64encode(f.read())    return img#上传到百度api进行人脸检测def go_api(image):    result = client.search(str(image, 'utf-8'), IMAGE_TYPE, GROUP);#在百度云人脸库中寻找有没有匹配的人脸    if result['error_msg'] == 'SUCCESS':#如果成功了        name = result['result']['user_list'][0]['user_id']#获取名字        score = result['result']['user_list'][0]['score']#获取相似度        if score > 80:#如果相似度大于80            if name == 'yin_danli':                print("欢迎%s !" % name)                time.sleep(1)            if name == 'danli':                print("欢迎%s !" % name)                time.sleep(3)            if name == "yusheng_02":                print("欢迎%s !" % name)                time.sleep(3)             else:            print("对不起,我不认识你!")            name = 'Unknow'            return 0        curren_time = time.asctime(time.localtime(time.time()))#获取当前时间         #将人员出入的记录保存到Log.txt中        f = open('Log.txt','a')        f.write("Person: " + name + "     " + "Time:" + str(curren_time)+'')        f.close()        return 1    if result['error_msg'] == 'pic not has face':        print('检测不到人脸')        time.sleep(3)        return -1    else:        print(result['error_code']+' ' + result['error_code'])        return 0#主函数if __name__ == '__main__':    servo_init()    #舵机复位,初始化一次就够了    while True:                print('准备开始,请面向摄像头 ^_^')        if True:            getimage()#拍照            img = transimage()  #转换照片格式            res = go_api(img)   #将转换了格式的图片上传到百度云            if(res == 1):   #是人脸库中的人                bt_open()                print("欢迎回家,门已打开")            elif(res == -1):                print("我没有看见你,我要关门了")                time.sleep(3)                bt_close()                else:                print("关门")                bt_close()            time.sleep(3)            print('好了')            time.sleep(5)

    注意:

    运行程序后,如果报错

    bluetooth.btcommon.BluetoothError: [Errno 112] Host is down 

    你则需要回到桌面端,将树莓派与HC-05重新配对一下,再运行一下就好了。

    最后

    至此,当我们运行该代码,把脸凑到摄像头前,舵机自动开门,把脸移开则舵机自动关门,智能门禁系统就做好啦!


    有遇到什么问题,可以直接私信我^-^


    展开全文
  • 树莓派人脸识别

    千次阅读 2017-01-31 15:22:44
    网上很多人脸识别教程并没有haarcascades的xml文件,现在给出这个文件和人脸识别的python代码,可惜树莓派计算速度有点慢具体多慢自己试试就知道了别忘了在代码中修改xml文件路径
  • 基于树莓派人脸识别算法包含电路原理图;结构框图
  • 树莓派人脸识别系统的开发与研究.pdf
  • 树莓派人脸识别,跳帧,多核CPU识别
  • // 命令行安装桌面,Crtl + Alt + F1 进入命令行模式,需要输入login和password sudo apt-get install ubuntu-desktop sudo reboot
  • 基于PCANet的树莓派人脸识别系统的研究开发.pdf
  • 树莓派进行简易人脸识别前言简易介绍树莓派树莓派是尺寸仅有信用卡大小的一个小型电脑,您可以将树莓派连接电视、显示器、键盘鼠标等设备使用。树莓派能替代日常桌面计算机的多种用途,包括文字处理、电子表格、...
  • 硬件要求树莓派及基本配件,树莓派摄像头模块(Picamera)或USB摄像头(Webcam)。二.系统要求Raspbian系统(其他Linux系统应该也可以,没试过)三.软件要求Python及一些库——opencv,dlib, face_recognition,...
  • 童话树莓派第十一集-进入AI世界-人脸识别(防疫检测)【人脸识别...先打开,今天魔法卡片树莓派人脸识别 魔法卡片相信你看完今天的魔法卡片,很快就能找到人脸识别的所有命令啦如果没找到,也没关系,叔叔把人脸识别命...
  • pi-detector, 基于 AWS Rekognition和 Pi Timolo的树莓派 人脸识别 引脚检测器基于 AWS Rekognition和 pi timolo的树莓派 人脸识别描述pi检测器与 pi timolo 一起使用,利用 AWS Rekognition来搜索生成的图像的运动...
  • 树莓派人脸识别代码

    2018-04-22 20:50:12
    树莓派python人脸识别代码,通过树莓派命令行运行.py程序,从而识别出图片中的人脸并用框框出来
  • 树莓派搭载usb摄像头,进行人脸识别 详细的记录https://blog.csdn.net/singular_man/article/details/88890939
  • 树莓派人脸识别.rar

    2021-04-22 16:51:36
    可以通过本项目来实现一个人脸门锁
  • 树莓派3B × 1 面包板 × 1 12伏直流电动门 × 1 双通道5V继电器模块 × 1 直流电源适配器 × 1 12V 5A开关电源任何高于3A应该工作。必须是12V。 × 1 网络摄像头网络摄像头保证工作。 × 1 通用键盘和鼠标任何键盘...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,387
精华内容 954
关键字:

树莓派人脸识别