精华内容
下载资源
问答
  • 树莓派人脸识别门禁

    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

    展开全文
  • 使用树莓派+python+Opencv+face_confignition来实现一个人脸识别系统。 1.安装树莓派系统 1.1配置树莓派需要的设备和工具 SD卡,读卡器,SDimage和SD 2.配置python虚拟环境 3.安装opencv库 4.安装face_confignition...

    使用树莓派+python+Opencv+face_confignition来实现人脸识别系统。该文章为树莓派系统配置

    1.安装树莓派系统

    1.1配置树莓派需要的设备和工具
    SD卡,读卡器,SD Card Formatter和Win32 Disk Imager
    1.2格式化SD卡
    使用SD Card Formatter,.
    在这里插入图片描述
    直接按照图片操作两步,便可以将SD卡格式化
    1.3.给SD卡写入系统
    树莓派系统下载地址下载镜像文件。如果下载下来是zip格式的,需要将其解压。个人建议下载:Raspbian-buster-full
    下载下来系统后使用Win32 Disk Imager工具,将镜像文件写入SD卡
    在这里插入图片描述
    按照图片执行,需要提前下载树莓派系统,下载网址为:

    2.更新系统库

    首先需要连接网络,使用WiFi连接

    sudo apt-get clean
    sudo apt-get purge wolfram-engine
    sudo apt-get purge libreoffice*
    sudo apt-get autoremove
    sudo apt-get update && sudo apt-get upgrade
    sudo apt-get install python-dev -y
    sudo apt-get install aptitude -y
    sudo apt-get install python-serial -y
    sudo apt-get install build-essential  -y
    sudo apt-get install cmake -y
    sudo apt-get install git -y
    sudo apt-get install pkg-config -y
    sudo apt-get install libjpeg-dev -y
    sudo apt-get install libtiff5-dev -y
    sudo apt-get install libjasper-dev -y
    sudo apt-get install libpng12-dev -y
    sudo apt-get install libavcodec-dev -y
    sudo apt-get install libavformat-dev -y
    sudo apt-get install libgtk2.0-dev -y
    sudo apt-get install libgtk-3-dev -y
    sudo apt-get install libatlas-base-dev -y
    sudo apt-get install libqtgui4 -y
    sudo apt-get install libqt4-test -y
    sudo apt-get install libcanberra-gtk* -y
    

    2.配置python虚拟环境

    sudo apt-get install virtualenv -y
    sudo apt-get install virtualenvwrapper -y
    sudo pip3 install virtualenv  virtualenvwrapper
    sudo nano ~/.bashrc
    

    将以下内容写入到文件最后:

    	export WORKON_HOME=$HOME/.virtualenv
    	source /usr/share/virtualenvwwrapper/virtualenvwwrapper.sh
    

    ctrl+o保存更改 -》enter-》ctrl+x退出

    source ~/.bashrc
    cd ~
    mkvirtualenv -p /usr/bin/python3   ~/my_python3
    source ~/my_python3/bin/activate    //开启python虚拟环境
    

    以下过程都是在虚拟环境下进行的

    3.安装opencv库

    pip install numpy
    pip install matplotlib
    pip install pandas
    pip install scipy==1.2.1
    pip install pillow==7.1.0
    pip install opencv-python==4.3.0.38
    

    4.安装face_confignition库

    pip install face-recognition==1.0.0  
    

    5.安装Rpi.gpio库

    sudo apt-get install python-rpi.gpio
    pip install rpi.gpio
    

    6.设置程序自启动

    直接简单粗暴:

    sudo nano /ect/rc.local
    

    在 exit 0 语句上方加入一句话:

    /home/pi/my_python3/bin/python  /home/pi/Desktop/face_recognize/face_recognize.py
    
    展开全文
  • 玩转树莓派2017-07-17 18:59毕业论文基于微型计算机的人脸识别门禁系统设计1. 课题意义及目标随科技的不断发展,安全性的要求也不断提高,IC卡等传统身份识别工具已不能满足社会需求。所以从通用性、安全性、成熟性...

    玩转树莓派2017-07-17 18:59

    毕业论文

    基于微型计算机的人脸识别门禁系统设计

    e00f89a67da6?utm_campaign=maleskine

    e00f89a67da6?utm_campaign=maleskine

    e00f89a67da6?utm_campaign=maleskine

    1. 课题意义及目标

    随科技的不断发展,安全性的要求也不断提高,IC卡等传统身份识别工具已不能满足社会需求。所以从通用性、安全性、成熟性和造价性等多方面综合考虑,研究新的识别工具是一个必然的趋势。基于人脸识别的门禁系统的设计,能够提高传统安保行业的安全性、方便性、直观性等,最为有效的杜绝了门禁管理中的人为因素,充分体现了门禁管理的人工智能性,避免不必要的安全隐患和人员纠纷。因此本次毕业设计选择了人脸识别门禁系统的研究与实现,以保证门禁数据的真实性,真正做到安全、方便和直观的门禁管理,从而进一步提高公司、仓库、家庭等地的安保水平和管理稳定性。

    本次设计将以微型计算机为核心,需选择合适的电源模块、检测模块、、数据存储模块、键盘模块、显示模块和声光报警模块,完成人脸识别系统的检测并报警处理的设计。要求能够将出入门禁系统的人员面部进行识别,能够在人脸数据匹配预存数据库资料时启动门禁系统中开门系统,当人脸数据不匹配预存数据库资料时启动门禁系统中闭门系统,实现防范防盗的作用,创造安全良好的生活工作环境。

    2.主要任务

    (1)查阅资料,了解人脸识别门禁系统的原理和基本构成,提出系统总体设计方案。

    (2)通过学习完成的各个控制硬件电路设计(如检测模块,A/D转换模块,声光报警模块,系统电源模块等)。

    (3)完成人脸识别门禁系统的软件设计。

    (4)完成人脸识别门禁系统的调试、仿真和实物制作。

    (5)完成设计说明书。

    基于微型计算机(树莓派)的人脸识别门禁系统

    摘 要

    随科技的不断发展,社会不断的进步,人们的自身安全意识和要求也再不断提高,IC卡等传统身份识别工具已不能满足社会需求。所以从通用性、安全性、成熟性和造价性等多方面综合考虑,研究新的识别工具是一个必然的趋势。为能够提高传统安保行业的安全性、方便性、直观性和有效的杜绝了门禁管理中的人为因素,通过人工智能方式,避免不必要的安全隐患和人员纠纷。

    提出一种基于微型计算机(树莓派)的人脸识别门禁系统,该系统通过使用人脸识别云服务可以实时对人员进行分析辨认,以保证门禁数据的真实性,真正做到安全、方便和直观的门禁管理,从而进一步提高公司、仓库、家庭等地的安保水平和管理稳定性。文中详细描述了该系统的搭建和实现过程,为相关产品提供了一套很好的解决方案。对所设计的系统进行了模拟测试,其测试结果达到了设计目标。

    关键词: 微型计算机(树莓派),人脸识别,云服务,Python

    目录

    第 1 章 绪 论

    1.1 研究背景

    随着社会的发展,安全教育不断的深化,人们的安全防范意识也逐渐赠强,这里面不光包括个人安全,还涉及到了财产和知识产权的保护,安检的高效,贸易的顺利流通等方面的需求增加,这种生物

    由此可设计出人脸识别门禁系统的总体结构框图,如图2-1所示:

    e00f89a67da6?utm_campaign=maleskine

    图2.1 人脸识别门禁系统的总结构框图

    本次设计中测试及最终使用,一直采用Python2.7编程语言对微型计算机(树莓派)系统进行开发和设计,其中人脸识别调用了face++的API, 官网提供了基于Python的SDK,该语言的可读性高很适合本系统的开发。本系统总体结构图如上。本地终端为微型计算机(树莓派),云服务采用了FACE++人工智能开发平台。

    2.2系统主要功能实现

    本论文中所设计的系统是对人脸图像进行处理识别并与门禁系统配合起到安全防盗的基本功能。工作原理是首先将三张待检测人员的照片存储到树莓派文件系统,执行此段程序时,调用face++的detectAPI将三张照片中的人脸信息存储在开发者账号,然后执行search的API,对现在进行的人脸识别程序中拍摄的照片进行处理,检测照片中的人脸信息并与之前上传的人脸信息对比,并返回相似度最高的人脸信息。我们在程序中只提取confidence的值,即人脸相似度。当触摸开关被按下,程序会发出警报LED闪烁,接着进行一张人脸的采集。并将此照片与已经上传的三张照片做对比。判断出相似的人脸。当相似度大于70%,则开门(电机正转开门 、停止并发出警报声、电机反转关门)。

    系统由微型计算机(树莓派),驱动模块,检测模块,显示模块,报警模块,电源模块等组成。系统带有按键,用户可以通过按键触发人脸识别功能;系统具有采集和检测人脸功能,可以当进入人员匹配成功时,开启大门,同时报警装置启动;当进入人员匹配失败时,大门不开启以保障安全。

    在本设计中,系统主要模块各自的功能如下:

    (1)主控模块。在本设计中主要起到集中分配的作用,不仅需要即时采集人脸图像,调用API处理图像,同时还要提供摄像头检测、驱动芯片、显示屏等数字器件的工作信号。

    (2)按键模块。系统的输入部分,实现人机交互。通过接收触控按键的电平信息,使得微型计算机(树莓派)得到需要的数据。

    (3)驱动模块。厂门电极作为大门开闭的过程控制的控制元件,其驱动主要由驱动芯片实现。通过操纵大门电机正转和反转,实现对大门的开闭控制。

    (4)显示模块。以连接一台电脑显示器即可

    (5)系统电源模块。系统电源模块主要负责给系统提供符合要求的电流与电压,由于微型计算机(树莓派)使用低压直流电压,就需要将两节锂电池18650电源7V转换为符合要求的电压、电流。从而使整个系统有持续的供电保证。[4]

    本系统的设计具有半自动门禁系统的特点。待检测人员需要用手按下触摸开关,进而触发人脸识别。系统将对其进行摄像并将图像发送至云端服务进行处理,待处理完之后微型计算机(树莓派)对返回的比对数据结果进行判断。如果对比成功,则驱动步进电机开始旋转。系统的实时性是用户体验的关键要素,系统正常工作时待识别的人员感觉不到卡顿状况 ,实时性良好。

    第3章人脸识别门禁系统硬件设计

    3.1主控模块

    e00f89a67da6?utm_campaign=maleskine

    图3.1 主控模板实物图

    本次设计的主控模块是使用微型计算机──树莓派3代B型主板。树莓派3代B型主板,该主控板模块的优势是拥有良好的标准模块扩展性,主板上预留的接口可完美对接与之配套的树莓派500万像素专用摄像头、7英寸液晶触摸屏、Sense Hat传感器模块等。除了可以在爱好者论坛下载网民大神们做好的系统包之外,如今还可以直接购买预装了树莓派代3代B型主板专用NOOBs系统的MicroSD卡。说到这里就又促生了树莓派代3代B型主板的进一步优势,那便是与微软的结合,微软为该产品推出了与之适配的Windows 10 IoT版操作系统,用户可以使用到更加熟悉的UI,使得通过标准扩展模块和GPIO接口扩展模块操作变得简单,IP等协议的配置也变得更加简单,同时驱动又在不断更新,不断完善,所以不用再去考虑重新开发Windows的驱动程序,以上这些与树莓派代3代B型主板的结合,对新入门的玩家以及互联网开发者来说是意义非凡的。

    主要包括以下几点:

    【Raspberry Pi 3 Model B】

    · BCM2837

    · 64位的1.2GHz四核ARM Cortex-A53

    · 1GB内存

    · 10/100自适应网卡

    · 802.11n WiFi无线网卡

    · 低功耗蓝牙4.1 (BLE)

    · HDMI接口

    · USB 2.0接口 x 4

    · MicroSD 卡插槽

    · 3.5 mm 音频输出接口

    · 40PIN GPIO接口

    · CSI摄像头接口

    · DSI显示接口

    · 升级后的电源管理系统,以便使用更多耗电的外设(须用2.5A以上电源供电) 树莓派3代B型是一款基于ARM的微型计算机主板,以SD/MicroSD卡进行存储,该主板提供USB接口和以太网接口,可以连接键盘、鼠标和网线,该主板具备所有PC的基本功能,例如:高清视频播放、电子表格书写、玩游戏等诸多功能,还整合了视频模拟信号的电视输出接口和HDMI高清视频输出接口。 树莓派将Python作为主要编程语言,支持Java、BBC BASIC (通过 RISC OS 映像或者Linux的"Brandy Basic"克隆)、C 和Perl等编程语言。本设计使用的是最新树莓派官方系统。是基于debian的一种linux32位操作系统。本次设计使用系统中安装的python2.7运行程序。

    3.2检测模块

    3.2摄像头模块实物图

    本次设计的检测模块是使用树莓派专用500W像素摄像头。该摄像头提供了三个应用程序,分别为:raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv 非常相似,并且都是用于捕捉图像,而 raspivid 用于捕捉视频。

    应用程序使用了四个 OpenMAX(mmal)组件:camera(摄像)、preview(预览)、encoder(编码)、null_sink。所有应用程序均使用了摄像组件,raspistill 使用了图像编码组件,raspivid 使用了视频编码组件,raspistillyuv 没有使用编码组件,而是直接将 YUV 或 RGB 从摄像组件输出到文件。所有应用程序均基于命令行方式运行,通过 OpenMAX 的 mmal API 进行编写。我们在设计中结合Opencv调用摄像头进行拍照操作。

    摄像头电路板与树莓派通过一条 15 芯的排线进行连接。具体连接操作如下:先将树莓派上连接座两端卡扣拉起,再把排线插入座中,并竖直,然后按下两端的卡扣。摄像头电路板连接同上。

    3.3 驱动模块

    当输入信号相对而言比较微弱时,相应功率较小无法正常工作。驱动模块实质是通过放大功率,从而满足负载额定功率使得负载可以正常工作,从而可以响应微弱的输入信号。微型计算机(树莓派)上有IN1, IN2, IN3, IN4四个接口,根据资料,设置为低电平就可以驱动,用杜邦线分别将IN1,IN2,IN3,IN4和GPIO 21(Pin 40),GPIO 20(Pin 38), GPIO 16(Pin 36), GPIO 19(Pin 35)进行连接。每次将四个GPIO端口按下表依次设置好电平后,可以sleep几十毫秒来控制转速

    图3.3 步进电机驱动原理

    e00f89a67da6?utm_campaign=maleskine

    图3.4 树莓派GPIO编码图

    3.3.1 步进电机工作原理

    在不超过额定负载时,脉冲信号的频率控制电机转动的速度、脉冲数决定电机止步的位置,均不会因为负载变化而受到任何的影响[8]。步进电机每走一步,就要加一个激磁信号,假如适当的信号,转子以一定的步数转动;无激磁信号输入时,转子保持一定的位置。步进电机工作的基本原理如下:

    (1)换相顺序的控制

    电机通电后,主要通过脉冲分配来实现工作相序的变化。以步进电机四相八拍工作方式为例,要求各相按照A-AB-B-BC-C-CD-D-DA的顺序来工作,控制脉冲就要按照该顺序来控制A、B、C、D相的通断。

    (2)步进电机转向的改变

    按照既定工作方式正向转动的顺序来给电机通电,电机就会正向转动;但是按照相反顺序来通电的话,电机会向相反方向转动。

    (3)步进电机转动速度的改变

    步进电机每一次接收到一个控制脉冲,它就会相应转动一步,转动固定角度。因此步进电机的转动速度就由两脉冲的间隔长短来决定,即是两脉冲发送间隔越长,相应的步进电机转动就越慢。如果要实现对步进电机转动速度调节,就需要改变单位时间内控制模块发出的脉冲个数。

    步进电机驱动方法有四相四拍运行方式,即AB-BC-CD-DA-AB;四相八拍运行方式,即A-AB-B-BC-C-CD-D-DA-A。

    四相步进电机,供电电源为5伏,5伏电源的正极性端连接电机公共端,而 5伏电源的接地端需要分别和电机剩余的四根控制线顺次接触,可以发现电源地线与电机控制线每接触一下,步进电机就会转动一定角度,电机转动完整一圈的时间,恰好需要如此来回转动的次数可以达到5次。由此可以计算出该步进电机的步进角度为

    度。若四条控制线与电源地线接触的顺序恰好相反,那么电机也就随之向相反方向转动。

    3.3.2 步进电机驱动电路

    由于步进电机的驱动电流的数值相对较高,所以单片机与步进电机不能直接连接,常常采用专门的接口及驱动电路。驱动器可以采用功率比较高的复合管,如ULN2003,L298N,或者购买专用的步进电机驱动器。驱动电路的工作状态是由控制信号来决定的,控制信号需要由主控模块,即单片机来产生。期望实现以下的步进电机驱动要求:

    (1)期望驱动电路提供的电流上升和下降速度可以比较快,这样可以使电流的波形尽可能的接近矩形波。

    (2)期望驱动电路功率和效率相对比较高,提高运行经济性。

    单片机的输出电流太小,无法直接连接步进电机,需要加驱动电路。对于电流小于0.5A的步进电机,可以采用ULN2003类的驱动IC。驱动芯片ULN2003内部结构如图3.4所示。

    e00f89a67da6?utm_campaign=maleskine

    图3.4 ULN2003内部结构框图

    ULN2003是由复合达林顿晶体管排列组成,使耐受电压比较高,允许通过电流较大。共有7对NPN达林顿管,分别为芯片7个控制单元,包括功率驱动单元、保护单元等。ULN2003采用DIP-16或者SOP-16双列16脚塑料封装,驱动单元可以与步进电动机直接耦合,连接方便,其数字逻辑电路为非门电路,取反控制。

    选取ULN2003作为电机驱动芯片,价格经济,且可以充分发挥功能,实现稳定驱动。可以直接通过电源来调节输出电压,可以直接用单片机的IO口提供信号,而且电路简单。芯片采用单片机作为控制核心,在程序相互调用的方面,更加的方便灵活。

    e00f89a67da6?utm_campaign=maleskine

    图3.5 ULN2003引脚图

    图3.5所示为驱动器引脚图,图左边1~7引脚为输入端,有单片机直接控制,接单片机输出端,引脚8直接接地;右侧10~16引脚为输出端,接步进电机,引脚9接电源+5V,必要时也可以什么都不接悬空而置,该驱动器可提供最高0.5A的电流。

    ULN2003的主要特点是:

    (1)驱动ULN2003电流比较大。ULN2003可以较好的用于单片机控制的电路。

    (2)ULN2003连接上拉电阻,在驱动电机时可以提高其抵抗干扰的能力。ULN2003的每两个达林顿管视为一个单元,都会串联一定阻值的高值电阻可以直接和TTL 或承载电压为5V的CMOS 装置连接 。

    (3)ULN2003的输出采用集电极开路,电流输出值比较大,可以达到500mA。因此可以用来驱动电机。

    另外,ULN2003的极限参数分别如表3.1、3.2所列。

    表3.1 ULN2003的极限参数

    表3.2 ULN2003的极限参数

    接线时需要把步进电机电路图的红色线悬空,其它线接驱动板。如果驱动不起来,有可能接线不对或电压低。如果用单片机来控制此步进电机,则只需分别依次给各线一定时间的脉冲电流,电机便可连续转动起来。

    ULN2003驱动电机的电路图如下图3.6所示。由单片机P3.4—P3.7口经上拉电阻作为驱动芯片ULN2003的输入。COM端供电12V,输出端10至12引脚均接地。四相五线式步进电机的A、B、C、D四相分别与ULN2003的输出端1C—4C连接,接收控制脉冲,实现控制。

    图3.6 ULN2003驱动电机的电路图

    3.3.3 步进电机的选型

    步进电机是一种专门用于位置与速度精确控制的特种电机,虽然同为电机件,步进电机区别于其他控制电机的最大特点是,它主要采用无反馈环节的开环控制,将微观的电脉冲信号转变为宏观电机转动的角位移或线位移。它通过数字来实现电机控制,控制信号以脉冲形式发出,它所接受到的脉冲可以驱使电机转动,即被转化为相应的角位移,所以只要给步进电机一个合适的脉冲信号,它就随之动作固定角度,当采用单片机来控制步进电机相对简单易操作。绕在定子的线圈配置作为步进电机相数分类的主要依据,主要可分为2相、4相、5相等;根据外部引线步进电机又被分为三线式、五线式、六线式等,但各种类型的电机其控制方法并没有发生太大的变化,均采用脉冲信号进行驱动。

    门禁系统的运动不需要加速、减速过程,所需转速较低,所以步进电机选用自启动运行方式。自启动运行方式是指在驱动电机旋转和停止时不经过加速、减速阶段,而直接以驱动脉冲速度启动和停止的运行方式。同时,因为在启动、停止时存在一个突然的速度变化,所以这种方式需要较大的加、减速力矩。由于具体负载重量也会影响其是否产生过大的工作噪音,所以四相五线式步进电机的负载容量可以较好满足要求。另外,出于对电流、步距角、静转矩三大要素的考虑,本设计选择四相五线式步进电机来模拟门禁系统的控制,可以直接插接方便使用。

    3.4 报警模块

    作为人脸识别门禁系统的设备,声光报警电路不可或缺。在系统工作中,每当人脸数据匹配成功时,便会触发蜂鸣器和发光二极管实现声光报警,使监控人员得到开启大门信号,反之则不报警。半导体二极管和普通二极管都是是类似的PN结结构,具有单向导电性,可以将电能转化成光能。 在将电流通到发光二极管之后,电子从N区移动到P区,并且从P区移动到N区的空穴在PN结附近与孔中的电子复合,N区域产生荧光发光提醒。

    声光报警设计部分包括蜂鸣器和LED报警指示灯。声音报警电路如图3.11所示,由于微控制器驱动能力的I / O端口较低,所以需要增加蜂鸣器PNP晶体管驱动,可以让那个蜂鸣器的声音听起来更响,更好地发挥警报功能。为了避免错误的报警添加了三极管基电路,蜂鸣器只有在输出低时才会发出声音。

    e00f89a67da6?utm_campaign=maleskine

    图3.8 声音报警电路原理图

    3.5 显示模块

    设计中为从一定程度上减小操作人员的工作量,特用电脑显示器作为显示模块,电脑显示器就不做过多阐述了。

    3.6电源模块

    本模块的作用是用来控制电源是否进入工作状态。电源模块一般分为以下几部分:滤波电路模块、全波整流电路模块、电源变压器模块等。一般电源提供的是220V交流电,经过门禁系统的电源模块中变压器的变压,变为直接可以供门禁使用的电压,然后进行全波整流,得到有尖峰脉冲的直流电,然后在滤波电路将有交流成分的电压滤除,最后得到可供系统使用的直流电。但我们的设计不需要这么大电流,电源直接是用两节充电锂电池18650共7v进行供电,所以不需要用稳压芯片。工作原理图如图3.1。

    图3.9 电源模块原理图

    第4章人脸识别门禁系统软件设计

    4.1安装系统

    软件部分:win32 DiskImager、SDFormatter、树莓派镜像文件

    硬件部分:SD卡、读卡器

    准备工作

    1.16G的SD卡一张(树莓派3B专用micro SD卡)2.下载树莓派系统镜像文件3.Windows下安装镜像的工具:Win32DiskImager

    安装实战

    1.解压下载的系统镜像压缩文件,得到img镜像文件2.将SD卡使用卡托或者读卡器后,连上电脑3.解压并运行Win32DiskImager工具4.在软件中选择系统镜像的img文件,“Device”下选择SD卡的盘符,然后点击“Write”然后就开始安装系统了,根据你的SD卡的速度,安装过程有快有慢5.安装结束后会弹出完成对话框,说明安装就完成了。

    e00f89a67da6?utm_campaign=maleskine

    图4.1 格式化软件工具

    e00f89a67da6?utm_campaign=maleskine

    图4.2系统烧录软件工具

    首先把SD卡连接到电脑,打开SDFormatter.注意观察盘符不要误将其他SD卡格式化。

    接下来打开win32 diskimager.打开存放镜像的路径,点击“write” /“yes” 等待镜像烧录成功。

    e00f89a67da6?utm_campaign=maleskine

    图4.3 烧录成功提醒界面

    e00f89a67da6?utm_campaign=maleskine

    图4.4 树莓派官方系统Pixel

    4.2 配置中文环境以及扩展文件系统

    树莓派3B默认是采用英文字库的,而且系统里没有预装中文字库,所以在locale中将其改成中文,也不会显示中文,只会显示一堆方块。因此需要手动来安装中文字体。

    ssh中输入以下命令:

    安装过程中如果碰到(Y/n),都选择y中文字库安装完成之后,还需要安装一个中文输入法。输入如下命令

    一样的安装过程,安装完毕后输入

    然后选择change_locale,在Default locale for the system environment:中选择zh_CN.UTF-8,配置完成之后,输入命令

    重启完成好就可以在VNC连接上去后使用中文显示和中文输入法了,切换中文输入法一样也是ctrl+space。

    e00f89a67da6?utm_campaign=maleskine

    图4.5 树莓派安装中文

    终端输入:sudo raspi-config 扩展文件系统

    e00f89a67da6?utm_campaign=maleskine

    图4.6 树莓派扩展文件系统

    “Expand Filesystem” 回车后将SD空间扩展(重启后生效)。配置中文环境如下所示。

    e00f89a67da6?utm_campaign=maleskine

    图4.7 树莓派设置中文(一)

    e00f89a67da6?utm_campaign=maleskine

    图4.8 树莓派设置中文(二)

    e00f89a67da6?utm_campaign=maleskine

    图4.9 树莓派设置中文(三)

    空格选中”zh_CN.UTF-8 “ 回车 “ok” 输入:sudo reboot 重启后生效

    e00f89a67da6?utm_campaign=maleskine

    图4.10 树莓派设置中文(四)

    e00f89a67da6?utm_campaign=maleskine

    图4.11 树莓派设置中文(五)

    4.3 RPI.GPIO搭建及使用介绍

    本系统使用的是树莓派官方系统raspbian。系统预装了python和C编译器等软件。运行本次系统前需要对环境进行搭建。树莓派内核中已经编译自带GPIO的驱动,本次设计采用第三方编写好的库函数来完成具体的操作。python GPIO 是一个小型的 python 库,可以帮助用户完成 raspberry 相关 IO 口操作,但是 python GPIO 库还没有支持 SPI、I2C 或者 1-wire 等总线接口。先安装 python-dev,输入以下指令。

    sudo apt-get install python-dev

    安装 RPi.GPIO,依次输入以下指令。

    · 下载:$ wget

    · 解压缩:$ tar xvzf RPi.GPIO-0.5.3a.tar.gz

    · 进入解压之后的目录 :$ cd RPi.GPIO-0.5.3a

    · 启动安装 :$ sudo python setup.py install

    导入 RPi.GPIO 模块:

    通过该操作,可以将模块名称映射为 GPIO,以便接下来您其它脚本进行使用。

    导入模块并检查它是否导入成功,可以尝试:

    针脚编号

    目前有两种方式可以通过 RPi.GPIO 对 Raspberry Pi 上的 IO 针脚进行编号。

    第一种方式是使用 BOARD 编号系统。该方式参考 Raspberry Pi 主板上 P1 接线柱的针脚编号。使用该方式的优点是无需考虑主板的修订版本,您硬件始终都是可用的状态。您将无需从新连接线路和更改您的代码。

    第二种方式是使用 BCM 编号。这是一种较低层的工作方式 – 该方式参考 Broadcom SOC 的通道编号。使用过程中,您始终要保证主板上的针脚与图表上标注的通道编号相对应。您的脚本可能在 Raspberry Pi 主板进行修订版本更新时无法工作。

    指定您所使用的方式(必须指定):

    或者

    Raspberry Pi 的 GPIO 上可能同时有多个脚本/循环。因此,如果 RPi.GPIO 检测到某个针脚被设置为其它用途而非默认的状态(默认为输入),您会在尝试配置某脚本时得到警告消息。禁用该警告消息:

    为每个用于输入或输出的针脚配置通道。配置为输入的通道:

    通道编号是基于您所使用的编号系统所指定的(BOARD 或 BC)。配置为输出的通道:

    通道编号是基于您所使用的编号系统所指定的(BOARD 或 BCM)。可以指定输出通道的初始值:

    输入读取 GPIO 针脚的值:

    通道编号是基于您所使用的编号系统所指定的(BOARD 或 BCM)。)这将返回 0 / GPIO.LOW / False 或者 1 / GPIO.HIGH / True。

    设置 GPIO 针脚的输出状态:

    通道编号是基于您所使用的编号系统所指定的(BOARD 或 BCM)。)

    状态可以为 0 / GPIO.LOW / False 或者 1 / GPIO.HIGH / True。在任何程序结束后,请养成清理用过的资源的好习惯。使用 RPi.GPIO 也同样需要这样。恢复所有使用过的通道状态为输入,您可以避免由于短路意外损坏您的 Raspberry Pi 针脚。注意,该操作仅会清理您的脚本使用过的 GPIO 通道。

    脚本结束后进行清理:

    4.4 Opencv运行环境的搭建

    首先进入Raspberry Pi系统,将树莓派连上网络,然后Ctrl + Alt +t打开命令终端(直接点击终端图标可能会卡),如果终端窗口没有出现的话,从顶部任务栏可以找到,点开就好。首先是以下这几条更新命令,每次单独执行:

    sudo apt-get update

    sudo apt-get upgrade

    sudo rpi-update

    然后执行安装opencv的构建相关命令:

    sudo apt-get install build-essential git cmake pkg-config

    然后是以下这几条命令安装图片工具包,每次单独执行(网上有很多一起执行的,但是经常出现问题)

    sudo apt-get install libjpeg8-dev

    sudo apt-get install libtiff5-dev

    sudo apt-get install libjasper-dev

    sudo apt-get install libpng12-dev

    然后是视频I/O包:

    sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev

    下面安装GTK:

    sudo apt-get install libgtk2.0-dev

    然后安装优化函数的包:

    sudo apt-get install libatlas-base-dev gfortran

    然后执行以下命令下载opencv3.0:

    cd /home/pi

    git clone https://github.com/opencv/opencv.git

    cd opencv

    git checkout 3.0.0

    然后安装opencv_contrib:

    cd /home/pi

    git clone https://github.com/opencv/opencv_contrib.git

    cd opencv_contrib

    git checkout 3.0.0

    然后安装开发包:

    sudo apt-get install python2.7-dev

    然后安装pip: SHAPE * MERGEFORMAT

    wget https://bootstrap.pypa.io/get-pip.py

    sudo python get-pip.py

    然后安装virtualenv virtualenvwrapper:

    sudo pip install virtualenv virtualenvwrapper

    sudo rm -rf ~/.cache/pip

    下面这个步骤不仅仅是命令了,打开~/.profile文件,我是使用vim打开的:

    sudo nano ~/.profile(”~”符号树莓派键盘打不出来 用笔记本SSH连上去)

    打开profile后,在这个文件最后,添加以下内容后保存退出:

    # virtualenv and virtualenvwrapper

    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python2.7

    export WORKON_HOME=$HOME/.virtualenvs

    source /usr/local/bin/virtualenvwrapper.sh

    然后执行下面这个命令:

    source ~/.profile

    然后创建虚拟工作环境并进入:

    sudo mkvirtualenv LC

    workon LC

    一定要确保进去刚刚创建的虚拟环境了,进入虚拟环境的标志是进去后命令的最前面(绿字前面)都会增加“(LC)”。

    下面在虚拟环境中安装numpy:

    pip install numpy

    sudo rm -rf ~/.cache/pip/

    pip install numpy

    一定确保在刚刚的虚拟环境下进行以下操作,如果新开了一个命令行窗口,那么就依次执行 source ~/.profile 命令和 workon LC 命令进入虚拟环境再执行以下操作。

    执行以下命令来设置编译:

    cd ~/opencv

    mkdir build

    cd build

    cmake -D CMAKE_BUILD_TYPE=RELEASE

    -D CMAKE_INSTALL_PREFIX=/usr/local

    -D INSTALL_C_EXAMPLES=ON

    -D INSTALL_PYTHON_EXAMPLES=ON

    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules

    -D BUILD_EXAMPLES=ON ..

    执行以下命令开始正式编译opencv3.0:

    make -j4

    编译完后进行安装:

    sudo make install

    安装后进行相关配置:

    sudo ldconfig

    配置完成

    本次设计主要利用opencv进行拍照,确实是有点大材小用。但是通过opencv的使用,加深了对图形处理方面的简单认识和理解。在设计之余学会了opencv进行简易人脸识别的原理。

    4.5 系统程序设计

    主程序设计

    流程图

    触摸开关

    流程图

    摄像头

    流程图

    步进电机

    流程图

    第5章系统运行以及源代码分析

    5.1 树莓派系统使用说明

    树莓派系统:可以直接用显示器进入系统桌面也可以远程桌面进入系统,或者putty软件SSH。本设计以远程桌面登陆为例。登陆路由器查询分配给树莓派的ip地址。打电脑的远程桌面软件。输入树莓派的IP地址,本次设计中树莓派的IP是192.168.0.115。用户名为pi,密码:raspberry远程桌面进去系统后还可以再去连接本地wifi信号。

    e00f89a67da6?utm_campaign=maleskine

    e00f89a67da6?utm_campaign=maleskine

    5.2 旷视FACE++ API使用说明

    本次设计对图像的处理是通过云服务来实现的。主要是调用Face++的API来实现的照片中人脸的对比。首先将三张照片上传树莓派或者用树莓派摄像头采集三张照片。调用Detect API进行人脸检测和人脸分析。识别出的人脸会给出face_token,用于后续的人脸比对等操作。当触摸开关出发实时拍照之后,调用Search API在Faceset中找出与目标人脸最相似的一张或多张人脸。支持传入face_token或者直接传入图片进行人脸搜索。使用图片进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。

    Sdk的facepp.py文件中包含如下底层api接口提供我们使用。

    _APIS = [

    '/detect',

    '/detection/landmark'

    '/compare',

    '/search',

    '/faceset/create',

    '/faceset/addface',

    '/faceset/removeface',

    '/faceset/update',

    '/faceset/getdetail',

    '/faceset/delete',

    '/faceset/getfacesets',

    '/face/analyze',

    '/face/getdetail',

    '/face/setuserid'

    ]

    e00f89a67da6?utm_campaign=maleskine

    图5.1 创建FACE++ API key

    Detect API

    调用者提供图片文件或者图片URL,进行人脸检测和人脸分析。识别出的人脸会给出face_token,用于后续的人脸比对等操作。请注意,只对人脸包围盒面积最大的5个人脸进行分析,其他人脸可以使用Face Analyze API进行分析。如果您需要使用检测出的人脸于后续操作,建议将对应face_token添加到FaceSet中。如果一个face_token连续72小时没有存放在任意FaceSet中,则该face_token将会失效。如果对同一张图片进行多次人脸检测,同一个人脸得到的face_token是不同的。

    Search API

    在Faceset中找出与目标人脸最相似的一张或多张人脸。支持传入face_token或者直接传入图片进行人脸搜索。使用图片进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。

    成功请求返回值示例:

    e00f89a67da6?utm_campaign=maleskine

    e00f89a67da6?utm_campaign=maleskine

    5.3 系统调试及运行

    整体流程:将三张待检测人员的照片存储到程序所在目录,执行程序时,调用face++的detectAPI将三张照片中的人脸信息存储在开发者账号,然后执行search的API对程序过程中拍摄的照片进行处理。检测照片中的人脸信息与之前上传的人脸信息对比,如果相似度达到百分之80以上返回相似度最高的人脸信息。

    e00f89a67da6?utm_campaign=maleskine

    图5.2 程序目录

    5.3.1程序初始设置

    首先将自己的照片上传到本文件夹并修改图片文件名,然后在代码中将三张待对比照片赋值给face_one、face_two、face_three三个变量。并设置进行对比的照片名为customer.jpg。

    face_one = 'face_one.jpg'

    face_two = 'face_two.jpg'

    face_three = 'face_three.jpg'

    face_search = 'customer.jpg'

    设置GPIO编码方式为board,GPIO13为输入模式,GPIO11,12,15,16,40为输出模式。

    GPIO.setmode(GPIO.BOARD)

    GPIO.setwarnings(False)

    GPIO.setup(13,GPIO.IN)

    GPIO.setup(11,GPIO.OUT)

    GPIO.setup(12,GPIO.OUT)

    GPIO.setup(15,GPIO.OUT)

    GPIO.setup(16,GPIO.OUT)

    GPIO.setup(40,GPIO.OUT)

    在python程序中设置调用API的key和secret。

    #http_url='https://api-cn.faceplusplus.com/facepp/v3/detect'

    key = "xzFPqqR1q_fasM1D3s4yvUdcBoTovUMX"

    secret = "4GXhLafqDOmnfQRxx-6ZlEVwQpOlZoW-"

    api = facepp.API(key, secret)

    5.3.2 各功能函数

    #蜂鸣器,前面已经初始设置GPIO12为输出模式,此处bee()函数设置gpio12为干电平,延时0.5s后置为低。意味着当调用bee()函数时蜂鸣器鸣叫0.5s.

    def bee():

    GPIO.output(12, False)

    time.sleep(0.5)

    GPIO.output(12, True)

    #步进电机,设置旋转角度为180°,closewise=1时,步进电机顺时针旋转,closewise=0时,步进电机逆时针旋转。步进电机驱动模块由树莓派的GPIO35、 GPIO36、 GPIO38 、GPIO40四个GPIO驱动。

    def motor_open():

    steps = 180;

    clockwise = 1;

    arr = [0,1,2,3];

    if clockwise!=1:

    arr = [3,2,1,0];

    ports = [40,38,36,35] # GPIO 21(Pin 40) GPIO 20(Pin 38) GPIO 16(Pin 36) GPIO 19(Pin 35)

    for p in ports:

    GPIO.setup(p,GPIO.OUT)

    for x in range(0,steps):

    for j in arr:

    time.sleep(0.002)

    for i in range(0,4):

    if i == j:

    GPIO.output(ports[i],True)

    else:

    GPIO.output(ports[i],False)

    #流水灯:初始设置已经将GPIO11、GPIO15、GPIO16为输出模式。分别把三个LED发光二极管的长引脚接到这三个GPIO上,短引脚接至负极。通过把对应的引脚置为高电平延时0.3s后置为低,循环点亮三个小灯。

    def light():

    GPIO.output(11, True)

    time.sleep(0.3)

    GPIO.output(11, False)

    GPIO.output(15, True)

    time.sleep(0.3)

    GPIO.output(15, False)

    GPIO.output(16, True)

    time.sleep(0.3)

    GPIO.output(16, False)

    #提示做好准备 ,一段时间后进行拍照。在终端窗口输出提示信息。并调用light()来实现LED发光二极管的流水灯效果。并调用bee()让蜂鸣器发出提示声音。

    def prep():

    print("欢迎使用人脸识别检测系统 请面对摄像头 5秒钟后进行人脸采集")

    light()

    print("************************5*********************")

    light()

    print("************************4*********************")

    light()

    print("************************3*********************")

    light()

    print("************************2*********************")

    light()

    print("************************1*********************")

    bee()

    #调用拍照函数时流水灯点亮,然后使用opencv利用摄像头采集一张照片,将照片保存为customer.jpg。

    def take_photo():

    light()

    capture = cv2.VideoCapture(0)

    if not capture.isOpened(): print('Capture failed because of camera')

    ret, img = capture.read()

    cv2.imwrite('customer.jpg', img)

    print("***********************照片采集完毕 请稍等*************************")

    print '=' * 60

    #函数调用API将本地存储的照片进行人脸检测和人脸分析。识别出的人脸会给出face_token,用于后续的人脸比对等操作。然后调用searchAPI在Faceset中找出与目标人脸最相似的一张或多张人脸。进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。

    e00f89a67da6?utm_campaign=maleskine

    触发检测的监测函数det(),程序运行时开始检测触摸开关是否被触发。当触摸开关被触发时会发送高电平信号给树莓派。当检测GPIO13为真时,在终端输出确定信息,并调用主函数进行对比操作。主程序运行结束后继续检测是否被触发。一直循环指导程序退出。

    def det():

    while True:

    if GPIO.input(13)==True:

    print "confirm"

    main()

    else:

    print "NO BODY"

    time.sleep(2)

    det()

    提取API.search返回结果,并将返回的信息保存到s,并从中提取相似度的值。转换s[0]["configdence’]为整形变量赋值给m。当m大于70时输出通过检测并调用步进电机转动。

    5.3.3异常处理

    e00f89a67da6?utm_campaign=maleskine

    当检测时由于没有拍摄到正常的人脸照片,程序则可能由于没有正常的人脸库而报错。此时须将下图中ret=api……注释掉,并将上一行的注释符号“#”取消。

    e00f89a67da6?utm_campaign=maleskine

    图5.7 处理报错信息(一)

    保存并上传后再次运行。清除无用的人脸库。

    然后再将代码修改为初始代码,再次进行正确的人脸采集,程序才可以正常运行。

    e00f89a67da6?utm_campaign=maleskine

    图5.7 创建一个faceset

    这种方式解决报错是复杂的一个过程。由于目的只是删除无用的人脸库,所以新建了一个debug.py的python文件。当检测失败之后执行一次debug.py即可。

    import facepp

    #http_url='https://api-cn.faceplusplus.com/facepp/v3/detect'

    key = "xzFPqqR1q_fasM1D3s4yvUdcBoTovUMX"

    secret = "4GXhLafqDOmnfQRxx-6ZlEVwQpOlZoW-"

    api = facepp.API(key, secret)

    # 创建一个Faceset用来存储FaceToken

    # create a Faceset to save FaceToken

    def main():

    api.faceset.delete(outer_id='detect', check_empty=0)

    #ret = api.faceset.create(outer_id='detect')

    #print_result("faceset create", ret)

    main()

    展开全文
  • 基于树莓派的人脸识别门禁系统(python+OpenCV+PyQt)

    千次阅读 多人点赞 2019-08-20 16:29:15
    一、开发环境 硬件:树莓派3B+ 镜像系统:2019-04-08-raspbian-stretch-...注:本来搭建OpenCV环境和PyQt5的时候是按照python3.5来的,开发到一半发现用的是python2.7的版本....不过最终效果还是出来了 二、最...

    一、开发环境

    • 硬件:树莓派3B+
    • 镜像系统:2019-04-08-raspbian-stretch-full.img
    • 软件:python2.7+OpenCV3.4.0+PyQt5
    • HDMI显示屏:10.1寸、分辨率1280*800

    注:本来搭建OpenCV环境和PyQt5的时候是按照python3.5来的,开发到一半发现用的是python2.7的版本....不过最终效果还是出来了

    二、最终效果

    比较模糊,这是因为用电脑远程树莓派录屏并转换为GIF图后的效果,实际上要清晰的多

    • 主界面:主界面主要是“欢迎使用人脸识别门禁系统”字样和普通用户、管理员两个功能按键
    • 登录界面:点击管理员是一个登录界面,输入相应的用户名和密码能进入管理员界面
    • 管理员界面:管理员界面主要是识别和录入人脸的功能,输入ID号,点击“开始录入”,等待进度条到达100%即可
    • 普通用户界面:普通用户界面主要是识别作用,能够识别录入的人脸并有相关提示信息,识别成功后能够控制继电器实现开门效果

    三、技术难点(点击进入)

    1. 登录界面准确的将数据输入到指定的 QLineEdit上
    2. 多线程实现识别人脸、录入人脸和加载进度条
    3. 获取人脸图片和训练人脸
    4. 实现人脸和姓名一一对应

    四、源码

    第一次用 python 写东西,代码比较乱,不过注释比较详细,源码下载地址,欢迎star:https://github.com/oneStarLR/faceReco

    展开全文
  • 基于python人脸识别门禁系统,实现对人脸的录入与识别功能 ,毕业设计 附论文 可移植树莓派
  • 基于树莓派的人脸识别门禁系统 一、功能概述   该软件实现的是人脸识别门禁功能,通过树莓派作为终端处理,使用OpenCV来识别人脸,从而达到特定的人脸开门的目的。主要分为管理员登录、录入人脸、识别人脸三大功能...
  • 人脸识别(python版).txt

    2020-02-08 17:50:16
    本代码用于在树莓派上利用自己配置的摄像头进行人脸识别,适合用来开发智能门禁系统。读者可以训练自己的人脸模型来应用。
  • 人脸识别门禁系统设计原理: 简单利用TigerBoard开发板模拟下人脸检测门禁系统,以继电器开关来代替门禁上电磁锁的开关。 人脸识别门禁系统硬件要求: 1.TigerBoar开发板 2. USB免驱摄像头 3. 继电器 4. 杜邦线若干 5....

空空如也

空空如也

1 2 3 4
收藏数 71
精华内容 28
关键字:

人脸识别门禁python

python 订阅