![cover](https://img-blog.csdnimg.cn/img_convert/6caf7fbef0004759a791b91e9214ce6e.png)
树莓派4B-Python-四种人脸检测/人脸识别
关于人脸检测本人目前用树莓派4B仅了解到了人脸检测的四种方法:使用OpenCV使用OpenMV利用百度智能云的人脸识别使用face recognition库树莓派4B-Python-人脸检测文章目录关于人脸检测前言一、OpenCV二、OpenMV1.引入库2.读入数据三、百度智能云的人脸识别四、face recognition库总结前言人脸识别对于大家来说应该都是挺耳熟的,它就是从人脸检测升级而来
关于人脸检测/人脸识别
本人目前用树莓派4B仅了解到了人脸检测/人脸识别的四种方法:
- 使用OpenCV
- 使用OpenMV
- 使用face_recognition库
- 使用百度智能云的人脸识别
树莓派4B-Python-人脸检测/人脸识别文章目录
前言
人脸识别对于大家来说应该都是挺耳熟的,它就是从人脸检测升级而来的。可能就会有人问:这人脸识别和人脸检测有啥不一样咧?
人脸检测是人脸识别的基础,人脸检测是检测到这一图片或这一画面中有人脸,但不知道这是谁的脸;人脸识别便是先给人脸打上了“标签”,告诉电脑某某某1的人脸长这样,每次检测到人脸就拿来与打了“标签”的人脸作对比,相似率达到多少多少(自己设定的值,如80%)时,就认为这张人脸叫某某某1,若达不到,就“不认识”。
一、OpenCV
1.OpenCV的简介
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。
2.树莓派上安装OpenCV——Python3环境
有许多大佬已经写过如何安装OpenCV了,本人也就不再“重复造轮子”了。
大概提一下安装步骤吧:
- 首先设置好 / 激活摄像头功能,把根目录扩大到整个SD卡等
- 安装numpy和其他依赖(若依赖安装出现问题,多半都是因为换源不对,版本分为stretch和buster,看清楚自己用的系统是什么版本,不然换了源一样安装不了部分依赖)
- 下载OpenCV3.4.0(有三个压缩包,OpenCV下载链接,两个是OpenCV的文件,另一个是编译到75%左右出错时需要添加的文件)
(再另提一下,全程大概出现三个或四个错误,还请做好心理准备,毕竟本人当时也编译了两三天、掉进了好几个坑才编译好的,当然了是因为需要重新编译所以才花那么久的)
- 最后解压、设置编译参数、编译(编译过程最为漫长,请耐心等待4~5小时,编译时间跟树莓派运行内存大小有关)
安装:
OpenCV的参考安装文章1
OpenCV的参考安装文章2(子豪兄的文章)
安装OpenCV3.4.0版本在编译过程中出现问题的解决方法:
参考解决方法一
参考解决方法二
当初本人便是结合这两种解决办法才能成功编译的,安装OpenCV的确是挺麻烦,所以需要不断尝试解决那些出现的错误,一般的出错时都会有所提示是在哪个文件夹、哪行代码、哪个文件出了问题,是缺失某个文件还是文件地址错误,都会有所提示,再不懂就仔细揣摩那两个参考解决方法或多百度百度吧。
3.OpenCV的级联分类器
安装OpenCV成功后,在opencv-3.4.0/data中会有好几个文件,其中以下文件存放了OpenCV自带的级联分类器文件,都是已经训练好的文件,可以检测人脸、眼睛、嘴等部位,但效果也并非就是完美的,会存在一些准确率问题,毕竟是开源的嘛,想要准确率很高的还是得自己训练。
这四个文件夹分别是四种检测方法,检测方法的不同自然准确率什么的也会存在差异(这是本人的猜测)。如下图所示为检测各种部位的分类器:
4.OpenCV的人脸检测代码
以下为使用OpenCV对图片里的人进行人脸检测的代码:
import cv2
#选择此代码目录下的某个图片文件
img = cv2.imread('image2.jpg',1)
# 导入人脸级联分类器,'.xml'文件里包含训练出来的人脸特征
face_engine = cv2.CascadeClassifier('/home/pi/Downloads/opencv-3.4.0/data/haarcascades/haarcascade_frontalface_default.xml')
# 检测设置,将图片放大1.1倍(一般设1.1倍,看效果而定)
# 重复检测的次数为5次(检测次数越多,速度越慢,检测也越严格,准确率可能有所提升)
faces = face_engine.detectMultiScale(img,scaleFactor=1.1,minNeighbors=5)
# 对图片进行人脸检测,之后得到人脸的坐标(一个矩形框),再用蓝色框框出,线宽为2
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # (255,0,0)=(B,G,R)
# 显示图片
cv2.imshow('img',img)
# 检测是否有按键按下
cv2.waitKey(0)
# 关闭窗口,释放占用的资源
cv2.destroyAllWindows()
以下为OpenCV使用摄像头对人脸和眼睛进行动态检测的代码:
import cv2
# 导入人脸级联分类器,'.xml'文件里包含训练出来的人脸特征
face_engine = cv2.CascadeClassifier('/home/pi/Downloads/opencv-3.4.0/data/haarcascades/haarcascade_frontalface_default.xml')
# 导入人眼级联分类器,'.xml'文件里包含训练出来的人眼特征
eye_cascade = cv2.CascadeClassifier('/home/pi/Downloads/opencv-3.4.0/data/haarcascades/haarcascade_eye.xml')
# 调用摄像头摄像头
cap = cv2.VideoCapture(0)
while(True):
# 获取摄像头拍摄到的画面
# 会得到两个参数,一个为存放是否捕捉到图像(True/False),另一个为存放每帧的图像
ret, frame = cap.read()
# 每帧图像放大1.1倍,重复检测10次
faces = face_engine.detectMultiScale(frame,1.1, 10)
img = frame
for (x,y,w,h) in faces:
# 画出人脸框,蓝色,画笔宽度为2
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
# 框选出人脸区域,在人脸区域而不是全图中进行人眼检测,节省计算资源
face_area = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(face_area,1.1,5)
# 用人眼级联分类器在人脸区域进行人眼识别,返回的eyes为眼睛坐标列表
for (ex,ey,ew,eh) in eyes:
#画出人眼框,绿色,画笔宽度为1
cv2.rectangle(face_area,(ex,ey),(ex+ew,ey+eh),(0,255,0),1)
# 实时展示效果画面
cv2.imshow('frame2',img)
# 每5毫秒监听一次键盘动作
if cv2.waitKey(5) & 0xFF == ord('a'): #当按下“a”键时退出人脸检测
break
# 最后,关闭所有窗口
cap.release()
cv2.destroyAllWindows()
二、OpenMV
openmv功能也挺强大的,自身就可以实现各种检测,如颜色检测、物体检测、人脸检测、人脸识别等等,与树莓派也可以通讯,通讯方式可有WiFi、蓝牙、I2C等(具体如何实现本人还未开始研究)。
1.OpenMV的简介
OpenMV是一个开源,低成本,功能强大的机器视觉模块。以STM32F427CPU为核心,集成了OV7725摄像头芯片,在小巧的硬件模块上,用C语言高效地实现了核心机器视觉算法,提供Python编程接口。使用者们(包括发明家、爱好者以及智能设备开发商)可以用Python语言使用OpenMV提供的机器视觉功能,为自己的产品和发明增加有特色的竞争力。
OpenMV上的机器视觉算法包括寻找色块、人脸检测、眼球跟踪、边缘检测、标志跟踪等。可以用来实现非法入侵检测、产品的残次品筛选、跟踪固定的标记物等。使用者仅需要写一些简单的Python代码,即可轻松的完成各种机器视觉相关的任务。小巧的设计,使得OpenMV可以用到很多创意的产品上。比如,可以给自己的机器人提供周边环境感知能力;给智能车增加视觉巡线功能;给智能玩具增加识别人脸功能,提高产品趣味性等;甚至,可以给工厂产品线增加残次品筛选功能等。
openmv的具体介绍1
openmv的具体介绍2(星瞳科技)
2.OpenMV实现人脸检测的原理
openmv内置了人脸检测的算法,是利用Haar算子来进行人脸的检测,可以快速的在视野中找到人脸,但获取图像后必须将图像转变成灰度图才可以进行计算(将图像转为灰度图可以提高其人脸检测的速度),然后做框出人脸位置等步骤。
3.OpenMV的人脸检测代码
代码如下:
(需要人脸与该模块摄像头在30cm左右的距离内才可以检测到人脸)
import sensor, time, image
# 重置感光元件
sensor.reset()
# 感光元件设置
sensor.set_contrast(3)
sensor.set_gainceiling(16)
# HQVGA和灰度对于人脸识别效果最好
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
#注意人脸识别只能用灰度图哦
sensor.set_vflip(True) # 设置画面垂直翻转
sensor.set_hmirror(True) # 设置画面左右翻转
# 加载Haar算子
# 默认情况下,这将使用所有阶段,更低的satges更快,但不太准确。
face_cascade = image.HaarCascade("frontalface", stages=25)
#image.HaarCascade(path, stages=Auto)加载一个haar模型。haar模型是二进制文件,
#这个模型如果是自定义的,则引号内为模型文件的路径;也可以使用内置的haar模型,
#比如“frontalface” 人脸模型或者“eye”人眼模型。
#stages值未传入时使用默认的stages。stages值设置的小一些可以加速匹配,但会降低准确率。
print(face_cascade)
# FPS clock
clock = time.clock()
while (True):
clock.tick()
# 拍摄一张照片
img = sensor.snapshot()
# 找到对象
# 注意:低比例因子缩小图像更多,检测更小的对象
# 阈值越高,检出率越高,假阳性越多。
objects = img.find_features(face_cascade, threshold=1, scale=1.5)
#image.find_features(cascade, threshold=0.5, scale=1.5),thresholds越大,
#匹配速度越快,错误率也会上升。scale可以缩放被匹配特征的大小。
#在找到的目标上画框,标记出来
for r in objects:
img.draw_rectangle(r)
# 打印FPS。
# 注:实际FPS更高,流FB使它更慢。
print(clock.fps())
三、face_recognition库
1.face_recognition的简介
face_recognition库是最为简洁的人脸识别库,可以直接通过捕捉图片中128维的人脸向量进行存储,打上“标签”,假设为某某某2,再与其他图片/画面中捕获128维的人脸向量做对比,相似度达到一定值后便判定刚刚识别的是某某某2的人脸。
(128维的人脸向量:也就是会在人脸上获取128个点的向量之类的,好比如眉毛的轮廓、鼻子的轮廓、嘴的轮廓等许多个点组成的线)
face_recognition的视频教程(在播放到37分后为安装教程,50分后为使用教程 很抱歉哈,那位UP主的视频已下架(2023.05.23本人亲自前往确认的))
2.树莓派上安装face_recognition
有两种方法(本人试的是第一种):
方法一
- 若之前安装过cmake的,就先将cmake升级一下
sudo apt --upgrade install cmake
再安装face_recognition
pip3 install face_recognition
- 若没安装过cmake,就先安装一下下
sudo apt install cmake
再安装face_recognition
pip3 install face_recognition
方法二
3.face_recognition实现人脸识别的思路
- 加载已知图片和待识别图片
- 对图片中的人脸进行编码
- 建立人脸库
- 识别待识别图片中的人脸
- 标记姓名并展示
- 释放资源
详细一些的说明 / 步骤:
- 传入人脸1图片
- 传入人脸2图片
- 传入需要检测的人脸图片
- 获取需要检测的人脸图片的人脸位置
- 对人脸1进行编码(识别这样类似的脸就是人脸1)
- 对人脸2进行编码(识别这样类似的脸就是人脸2)
- 知道的人脸编码列表
- 知道的人脸名字列表
- 获取需要检测的图片中人脸编码
- 在需要检测的图片上遍历出(top,right,bottom,left),face_encoding
- 使用方框将人脸框起来
- 将已知人脸和需要检测中未知人脸进行比较
- 若检测不出则在未知人脸上显示unknown
- 若检测得出,就将对应名字列表中的名字在人脸上显示
- 在方框上显示文字
- 显示图片
- 检测键盘是否按下,若按下则停止
- 销毁显示的窗口
4.人脸识别代码
该代码是将检测速度提升了,其实其他提速的方法也挺(可能也许大概八成)简单的,可以用于参考:
1.替换人脸检测方法成OpenCV的Haar人脸检测方法;(好像是在输出位置的向量上需要转换,有些麻烦,原理上是可以的)
2.换成在灰度图上检测;(按道理可以,但本人还未成功,猜测是颜色格式没转换好的问题)
3.将画面大小按比例缩小再检测;
4.将按比例缩小后的画面作为显示的画面;
5.采用多个CPU一起检测(目前还没尝试成功,但据说可以);
6.使用神经棒加速;(猜测可以)
7. …(目前知识有限,待续)
以下代码仅采用了将画面大小按比例缩小的方法,速度提升了10s左右:
(这是指从程序开始到显示画面的时间减少了10s左右,实际上还是会花15s左右做预处理。检测到人脸后的延迟为3s左右,这也跟网络延迟有关)
import face_recognition
import cv2
import numpy as np
# 用opencv获取摄像头画面
video_capture = cv2.VideoCapture(0)
# 获取obama图片,提取128维的人脸向量
obama_image = face_recognition.load_image_file("obama.jpg")
obama_face_encoding = face_recognition.face_encodings(obama_image)[0]
# 获取biden图片,提取128维的人脸向量
biden_image = face_recognition.load_image_file("biden.jpg")
biden_face_encoding = face_recognition.face_encodings(biden_image)[0]
# 存储128维的人脸向量
known_face_encodings = [
obama_face_encoding,
biden_face_encoding
]
# 存储人脸名字
known_face_names = [
"Barack Obama",
"Joe Biden"
]
# 初始化
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True
while True:
ret, frame = video_capture.read()
# 将画面缩小4倍
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
# 将BGR颜色格式转换为RGB
rgb_small_frame = small_frame[:, :, ::-1]
if process_this_frame:
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
name = "Unknown"
face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
best_match_index = np.argmin(face_distances)
if matches[best_match_index]:
name = known_face_names[best_match_index]
face_names.append(name)
process_this_frame = not process_this_frame
for (top, right, bottom, left), name in zip(face_locations, face_names):
# 此处将前面缩小的比例还原(放大4倍),这样才可以在原图像上框对人脸
top *= 4
right *= 4
bottom *= 4
left *= 4
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
# 此处是显示原图像,若将显示的图像换成缩小4倍后的图像,速度也能提升
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
四、百度智能云的人脸识别
1.百度智能云
利用百度智能云的人脸识别系统实现人脸识别也是很简单的,但是树莓派需要在联网的情况下才可以使用该人脸识别,除非部署了离线版的人脸识别系统。
2.创建人脸识别项目
1.首先需要在百度智能云上创建一个账号,或者使用百度账号登录;
2.进入后创建一个人脸识别应用;
3.下图框出的三个内容后面会用到,因此需要记下;
4.创建用户组和用户(用户组和用户的名称都只能是数字或英文,不能有中文)
5.给用户上传用户的正面照(上传不同的照片越多越好)
6.下载SDK
将SDK压缩包解压得到以下文件:
3.部署SDK
在树莓派4B上部署SDK:
1.先通过U盘或VNC的文件传输将SDK文件夹传输给树莓派
2. 安装pip(若已经安装了则跳过安装pip)和setuptools
2.1 安装setuptools
2.1.1 下载安装包(此安装包为2020.8.14更新的49.6.0版本)
wget https://files.pythonhosted.org/packages/38/cc/db23dbe4efc464c3c0111fedf7d46de8888f05b09488d610f6f8ab6e2544/setuptools-49.6.0.zip
2.1.2 解压
unzip setuptools-49.6.0.zip
2.1.3 安装
cd setuptools-49.6.0
sudo python setup.py build
sudo python setup.py install
2.2 安装pip(若已经安装了的就跳过)
方法一:
sudo apt-get install -y python-pip
方法二:
2.2.1 下载(此安装包为2020.8.11更新的20.2.2版本)
wget https://files.pythonhosted.org/packages/73/8e/7774190ac616c69194688ffce7c1b2a097749792fea42e390e7ddfdef8bc/pip-20.2.2.tar.gz
2.2.2 解压(注意版本是否一致)
tar zxvf pip-20.2.2.tar.gz
2.2.3 安装(安装前请看清楚下载好的文件夹名是否一致,随着更新,版本会不一样)
cd ../pip-20.2.2/
sudo python3 setup.py install
3. 安装SDK
假设传输过来的SDK文件放在了Download文件夹内,则先进入该文件夹内:
cd Downloads/aip-python-sdk-2.2.15
然后再安装:
sudo pip install baidu-aip
得到类似如下图所示画面就说明SDK已经安装成功:
接下来还需安装API:
sudo python3 setup.py install
这样就可以调用百度智能云的人脸识别了
4.调用百度智能云的人脸识别代码
当使用以下代码后,会生成一个名为“ming_dan”的文本在当前文件夹内,用于记录检测人的姓名和时间。
from aip import AipFace
from picamera import PiCamera
import urllib.request
import RPi.GPIO as GPIO
import base64
import time
import datetime
#百度人脸识别API账号信息
APP_ID = '19127770'
API_KEY = 'bgaoZtrDyFm097RZy4zc1b1p'
SECRET_KEY = '8dPNLaUyG7HKBDHU848y6gS7lZHvfQU3'
client = AipFace(APP_ID, API_KEY, SECRET_KEY)#创建一个客户端用以访问百度云
#图像编码方式
IMAGE_TYPE='BASE64'
camera = PiCamera()#定义一个摄像头对象
#用户组
GROUP = 'one'
#照相函数
def getimage():
camera.resolution = (1024,768)#摄像界面为1024*768
camera.start_preview()#开始摄像
time.sleep(1)
camera.capture('faceimage.jpg')#拍照并保存
time.sleep(1)
#对图片的格式进行转换
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 == 'qin_guan_lin': # 此为自己设置的用户组中的用户名(只能是由字母和数字组成)
name1 = '小霖'
name = name1
print('相似度为:%.2f' % score)
print("欢迎%s!" % name)
time.sleep(0.5)
if name == 'lin_xiu_li':
name2 = '小莉'
name = name2
print('相似度为:%.2f' % score)
print("欢迎%s!" % name)
time.sleep(0.5)
if name == "qin_wen_hua":
name3 = '小华'
name = name3
print('相似度为:%.2f' % score)
print("欢迎%s!" % name)
time.sleep(0.5)
else:
print('相似度为:%.2f' % score)
print("抱歉,识别失败!请重试!")
name = 'Unknow'
return 0
#curren_time = time.asctime(time.localtime(time.time()))#获取当前时间
curren_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#将人员出入的记录保存到Log.txt中
f = open('ming_dan.txt','a')
f.write("姓名:" + name + " " + "时间:" + str(curren_time)+'\n')
f.close()
return 1
if result['error_msg'] == 'pic not has face':
print('检测不到人脸')
time.sleep(1)
return 0
else:
print(result['error_code']+' ' + result['error_code'])
return 0
#主函数
if __name__ == '__main__':
a = 0
#while True:
while a < 2:
print('准备')
if True:
getimage()#拍照
img = transimage()#转换照片格式
res = go_api(img)#将转换了格式的图片上传到百度云
if(res == 1):#是人脸库中的人
print("开门")
else:
print("关门")
print('稍等三秒进入下一个')
time.sleep(1)
a += 1
总结
- 本人是在了毕业设计上用到了opencv,简单的用了下人脸检测和口罩检测,唯独麻烦的是训练口罩检测的级联分类器,由于想要精度高所以训练花费的时间也是非常久的,当时是正样本与负样本的比例为500:1500,训练20层,准确率设在了90%以上,单单前面十几层就花费了两三天时间,后面几层花费的时间更久,大概算来得花费二十天左右吧(大概是哪里出了问题导致了这个结果,比如图片大小、灰度图、设置的准确率等等吧),最终因为时间太久的缘故停止了训练。
- openmv3这个模块是舍友的毕业设计用到的,后面是因为不想要了才给(丢给)本人玩(研究)的,当时就乐开了花(毕竟一直听说这个小玩意的功能挺厉害的)。openmv3这个小玩意儿呢是手动调节焦距的,然后还发现它的像素并不是很好(大概是因为镜头的问题吧),不过有多种镜头可以更换,就是那些镜头和配件什么的有点点贵…学习嘛,肯定是要有所代价的。
- face_recognition是偶然间发现的,居然还有这么一个库可以直接实现人脸识别,可是在本人使用之后发现有点问题,这个问题不知道是不是本人问题(有点尴尬),先是识别本人照片后,使用摄像头去捕捉、识别其他人脸时,发现,别人脸上本该显示的应该是“unknown”,然而却许多次都是显示本人的名字!!??(这是说明本人的脸是大众脸么…)
- 百度智能云的人脸识别就厉害多了,只要系统上上传的图片合格,并且样式多一些,识别的准确率就会更高,甚至有时候只是露个侧脸都能识别出。但也存在一些小问题,比如说:对手机上显示的人脸图片也能识别,所以若用于做门禁之类的话,需谨慎哦。当然,前面三种方法也存在这个小问题的。
这四种方法都是本人所尝试过的,但由于自身能力还是有所不足,有些地方写得或描述得不是很好,还望见谅。
可能有个bug,就是手机上的CSDN APP在显示代码时不显示完整,许多都会下面一半代码就空了,但是在电脑网页上代码却是显示完整的。
##2020.8.30
(该文章用于给自己今年所经历的,做一个总结和回忆)
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)