0%

基于树莓派的简易人脸识别

需要硬件

  1. 树莓派一个
  2. 树莓派CSI摄像头 5MP Camera Board Module

## 固件安装 1. 树莓派,内存卡,电源安装好。 2. 将CSI摄像头按照步骤安装于树莓派上 步骤一 图片来源

软件安装

树莓派系统安装

树莓派安装官网最新操作系统,推荐使用NOOBS,这是一个Raspbian的傻瓜安装版。

  1. 从官网下载NOOBS,解压zip文件

  2. 准备格式化后的SD卡,最好8G以上,从SD Formatter 官网下载SD Formatter,按照提示正常安装,将SD卡连接到PC上 通过(读卡器,电脑卡槽都行),格式化

  3. 把解压后的文件全部放入SD卡内,之后将SD卡安全拔出,把SD卡插入到Raspberry

  4. 连上键盘,鼠标,显示器,启动Rasberry,点击install 等待自动安装的完成。完成后 登录图形界面 (默认登录用户名为pi 密码为raspberry)

并通过以下命令完成系统更新 ' sudo apt-get update sudo apt-get -upgrade ' ### 在树莓派上启动摄像头模块 #### 开启摄像头 1. 确认系统更新完成后,用树莓派配置工具来激活摄像头模块 ' sudo raspi-config' raspi-config界面 选择interfacing options 选择Camera 将Camera功能设置为Enable,之后操作系统自动重启

摄像头测试

重启之后,我们需要对摄像头是否工作做一个测试 'raspistill -t 2000 -o test.jpg' raspistill 是树莓派控制摄像头拍摄的命令, -t 为捕获图片等待时间 单位ms, -0为输出为文件 。

查看图片命令 'gpicview test.jpg' 若输出正常,则可以使用opencv来实现人脸识别

人脸识别框架

人脸识别框架,来源:参考文章1 可以看出分为三个部分 - 数据收集 - 训练分类器 - 人脸识别 ### 主要参考文章

参考文章1;参考文章2

安装OpenCV

树莓派系统内自带Python,我们的人脸识别是基于OpenCV实现的,OpenCV具备很强的计算效率,而且可以应用于实时应用,非常适合于使用摄像头的实时人脸识别。 1. 通过以下代码安装OpenCV。

1
2
3
sudo apt-get  update
sudo apt-get upgrade
sudo apt-get install python-opencv
2. 安装PiCamera。
1
2
3
4

sudo apt-get install python-pip
sudo apt-get install python-dev
sudo pip install picamera
这样基于人脸识别的准备工作就完成。

人脸识别

从框架图中可知,实现人脸识别的基础任务是人脸检测,必须先捕捉到人脸才可以识别他。

最常见的人脸检测方法为使用Haar级联分类器 ,很幸运的是 OpenCV具备训练器和检测器。并且OpenCV也包含很多预训练的分类器,相关的xml可以从OpenCV上下载,或者从我的百度云盘里下载。

使用OpenCV创建人脸检测器

import

在python里使用摄像头

1
2
from picamera import PiCamera
from picamera.array import PiRGBArray
1
2
3
4
camera = PiCamera()
camera.resolution = (320,240) #分辨率
camera.framerate = 60 #帧数
rawCapture =PiRGBArray(camera, size=(320,240))

载入cascade file文件来检测人脸

1
2
3
face_cascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
t_start = time.time()
fps = 0

haarcascade_frontalface_default.xml 为OpenCV预训练的分类器,路径按照自己放置的路径填写。

定义一些主要函数

  1. get_faces 函数
1
2
3
4
5
6
7
8
9
'''
input: img 视频拍摄中的图像
output: faces; image 将原图像和识别出的脸一起返回。
'''
def get_faces(img):
image = img
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces =face_cascade.detectMultiScale(gray)
return faces,image
  1. draw_frame 函数 在识别的脸部画上识别框
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    '''
    Args:
    img: 视频拍摄中的图像
    faces:识别出的脸
    Return:
    None
    '''
    def draw_frame(img,faces):
    global fps
    global time_t
    for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y), (x+w,y+h),(100,255,100),2)
    cv2.putText(img, "face ", (x,y),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
    ####show fps
    fps = fps +1
    sfps = fps/(time.time()-t_start)
    cv2.putText(img, "FPS"+str(int(sfps)), (10,10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0,0,255),2)
    #######show image
    cv2.imshow("frame", img)
    cv2.waitKey(1)
  2. 为了提高拍摄视频的帧数使用functools函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    def main():
    pool = mp.Pool(processes=4)
    fcount = 0
    camera.capture(rawCapture, format="bgr")
    r1 = pool.apply_async(get_faces, [rawCapture.array])
    r2 = pool.apply_async(get_faces, [rawCapture.array])
    r3 = pool.apply_async(get_faces, [rawCapture.array])
    r4 = pool.apply_async(get_faces, [rawCapture.array])

    face1, img1 = r1.get()
    face2, img2 = r2.get()
    face3, img3 = r3.get()
    face4, img4 = r4.get()

    rawCapture.truncate(0)

    for frame in camera.capture_continuous(rawCapture, format="bgr",use_video_port=True):
    image = frame.array

    if fcount == 1:
    r1 = pool.apply_async(get_faces, [image])
    face2, img2 = r2.get()
    draw_frame(img2, face2)
    if fcount == 2:
    r2 = pool.apply_async(get_faces, [image])
    face3, img3 = r3.get()
    draw_frame(img3, face3)
    if fcount == 3:
    r3 = pool.apply_async(get_faces, [image])
    face4, img4 = r4.get()
    draw_frame(img4, face4)
    if fcount == 4:
    r4 = pool.apply_async(get_faces, [image])
    face1, img1 = r1.get()
    draw_frame(img1, face1)

    fcount = 0 # restart the count loop
    fcount += 1
    rawCapture.truncate(0)

    ## 源代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94

    '''
    A camera script
    '''
    ###############import##########
    from picamera.array import PiRGBArray
    import numpy as np
    import cv2
    import time
    import os
    from picamera import PiCamera
    from functools import partial
    import multiprocessing as mp

    #################import###########

    resx = 320
    resy = 240
    #########setup camera
    camera = PiCamera()
    camera.resolution = (320,240)
    camera.framerate = 60
    rawCapture =PiRGBArray(camera, size=(320,240))

    face_cascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')

    t_start = time.time()
    fps = 0
    #####main function##########
    def get_faces(img):
    image = img
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces =face_cascade.detectMultiScale(gray)

    return faces,image

    def draw_frame(img,faces):
    global fps
    global time_t
    for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y), (x+w,y+h),(100,255,100),2)
    cv2.putText(img, "face ", (x,y),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
    ####show fps
    fps = fps +1
    sfps = fps/(time.time()-t_start)
    cv2.putText(img, "FPS"+str(int(sfps)), (10,10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0,0,255),2)
    #######show image
    cv2.imshow("frame", img)
    cv2.waitKey(1)



    def main():
    pool = mp.Pool(processes=4)
    fcount = 0
    camera.capture(rawCapture, format="bgr")
    r1 = pool.apply_async(get_faces, [rawCapture.array])
    r2 = pool.apply_async(get_faces, [rawCapture.array])
    r3 = pool.apply_async(get_faces, [rawCapture.array])
    r4 = pool.apply_async(get_faces, [rawCapture.array])

    face1, img1 = r1.get()
    face2, img2 = r2.get()
    face3, img3 = r3.get()
    face4, img4 = r4.get()

    rawCapture.truncate(0)

    for frame in camera.capture_continuous(rawCapture, format="bgr",use_video_port=True):
    image = frame.array

    if fcount == 1:
    r1 = pool.apply_async(get_faces, [image])
    face2, img2 = r2.get()
    draw_frame(img2, face2)
    if fcount == 2:
    r2 = pool.apply_async(get_faces, [image])
    face3, img3 = r3.get()
    draw_frame(img3, face3)
    if fcount == 3:
    r3 = pool.apply_async(get_faces, [image])
    face4, img4 = r4.get()
    draw_frame(img4, face4)
    if fcount == 4:
    r4 = pool.apply_async(get_faces, [image])
    face1, img1 = r1.get()
    draw_frame(img1, face1)

    fcount = 0 # restart the count loop
    fcount += 1
    rawCapture.truncate(0)

    if __name__ == '__main__':
    main()