树莓派人脸识别门禁系统的总体设计
硬件包括:树莓派3B、电源模块、转5V降压模块、触摸感应传感器模块、声光报警模块和驱动模块。
由此设计出的人脸识别门禁系统总体结构框图如下:
总体结构框图
程序运行时树莓派会将本地照片中的面部图像发送至云端服务进行分析,识别出的人脸会给出face_token,用于后续的人脸比对等操作。触摸传感器触发主函数实时拍照并发送至云服务调用Search API在Faceset中找出与目标人脸最相似的一张或多张人脸。将比对结果发送到树莓派本地终端,提取返回结果并将其显示在树莓派终端。
主流程图
系统主要功能实现
当触摸开关被按下LED闪烁,接着进行一张人脸的采集。并将此照片与已经上传的三张照片做对比。判断出相似的人脸。当相似度大于70%,则开门(电机正转开门 、停止并发出警报声、电机反转关门)。
主要模块各自的功能如下:
主控模块。在本设计中主要起到集中分配的作用,不仅需要即时采集人脸图像,调用API处理图像,同时还要提供摄像头检测、驱动芯片、显示屏等数字器件的工作信号。
触发模块。系统的输入部分,实现人机交互。通过接收触控按键的电平信息,使得树莓派得到需要的数据。
检测模块。对人脸进行采集摄像的模块,提供最原始的图片信息。
驱动模块。大门开闭的过程控制的控制元件
显示模块。以连接一台电脑液晶显示器即可
系统电源模块。系统电源模块主要负责给系统提供符合要求的电流与电压
报警模块。系统的声光报警模块,利用LED灯和蜂鸣器来提示人脸即将检测的信息。
主控板的选型
树莓派3B
触发模块
触摸开关模块
检测模块
树莓派摄像头
树莓派专用500W摄像头提供了三个应用程序,分别为:raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv 非常相似,并且都是用于捕捉图像,而 raspivid 用于捕捉视频。
树莓派上电即开机进入系统。启动人脸识别检测程序。程序启动后触摸传感器循环检测是否被触发。检测周期时2S,当触摸感应开关被触发则启动摄像头实时拍照。照片存储到本地之后上传云服务处理。之后判断返回的处理结果是否通过。
搭建opencv环境将在下一个文章详细介绍,此处跳过。除此之外安装pycurl.使用apt-get的方式安装$ sudo apt-get install python-pycurl。
流程图
到Face++网站https://www.faceplusplus.com.cn/注册自己的APIkey.
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'
]|
输入自己在Face++网站注册的APIkey。
FACE++的API
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或者直接传入图片进行人脸搜索。使用图片进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。
调用正确的返回值
系统调试及运行
等待对比的照片先存储在本地 等待代码中上传
程序初始设置
首先拍摄的照片上传到本文件夹并修改图片文件名,然后在代码中将三张待对比照片赋值给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 = "XXXXXXXXXXXXXXXXXXXX"
secret = "XXXXXXXXXXXXXXXXXXXXXXXX"
api = facepp.API(key, secret)|
各功能函数
蜂鸣器,前面已经初始设置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)|
(3)流水灯:初始设置已经将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中找出与目标人脸最相似的一张或多张人脸。进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。
触发检测的监测函数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时输出通过检测并调用步进电机转动。
异常处理
目的是删除无用的人脸库,所以新建了一个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()|
至此所有代码讲解完毕 有任何不懂得地方随时给我看留言
PS:
本文中为了节省篇幅 省略了opencv搭建的步骤。其实拍照功能可以换成调用os使用命令行的方式拍照:
|def take_photo():
os.system('raspistill -w 480 -h 360 -o customer.jpg -t 2000')
print("***********************首次照片采集完毕 请稍等*************************")
print '=' * 60|
如果你也想知道树莓派安装opencv和使用opencv做人脸检测、移动物体检测 请继续关注吧
跟我一起玩转树莓派