****树莓派基于opencv的人脸识别和口罩检测****
树莓派基于opencv的人脸识别和口罩检测
文章目录
学习目标:
目标:人脸识别和口罩的检测
实现的功能:
1:检测到人脸,画框,并识别已训练的人的模型,并打印出名字
2:识别是否带了口罩
学习内容:
内容:基于python的opencv和face_recognition来实现
1、 掌握opencv,face_recognition的安装
2、 掌握 训练模型
3、 掌握调用模型
4、 掌握树莓派安装opencv和contrib以及face_recognition
文章目录
前言
打电赛输了,在比赛的几天后一个人做出来,也了解到了硬件的重要性
一、opencv是什么?
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1] 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。
二、步骤
1.树莓派安装模块
值得一提,我就是安装不上才失败的,因为有的模块需要很大的内存,而树莓派分不出来,所以经常就是安装到99%的时候卡住,然后就是程序已杀死,我心态崩了都!!!!
安装教程链接:
1:安装opencv:
https://zhuanlan.zhihu.com/p/92184435
2:安装dlib:
https://blog.csdn.net/weixin_44086593/article/details/87467537
3:安装face_recognition:
https://blog.csdn.net/weixin_43106043/article/details/104962026
4:xml模型的下载:
链接:https://pan.baidu.com/s/1ULupRUJGRtRRPfLw-Iooyw
提取码:6zf8
祝大家成功哈哈哈哈哈
2.设计思路
有点长,希望大家不要嫌啰嗦
1;首先,在多种优秀的人脸识别的方法中,我们还是毅然决然的选择了最为有效,最为方便的python+opencv,因为其有相对应的函数库供我们使用,效果明显,代码简洁。
2;收集:一开始,因为只需要测试三个队员和其他未知者,所以先通过face_collect.py开始通过电脑内置摄像头对三个队员进行人脸采集,并输入自己的id号和顺序,便于后期的数组遍历寻找匹配对象,加载人脸分类识别器,导入人脸识别的模型找出人脸进行截取,经过测试,由***于彩色的照片会占据大量内存并且受外界干扰明显,所以使用OpenCV调用摄像头获取图像并进行基础的处理(灰度等)转为灰度图片,减少程序符合,提高识别度,特定功能库Dlib进行特征获取,然后以jpg格式保存,并每个人都存储101张在totalfaces的文件中。***
3;训练:对得到的303张jpg图片,通过python中的os文件处理,PIL以及numpy数据库的结合,再次导入人脸识别模型和输入输出格式的绝对路径的设置,通过遍历照片文件进行对其整体的一个封装,并且保存为以yml为后缀的训练型文件。我们在前一部分的同目录下创建一个Python文件,文件名为trainner.py,用于编写数据集生成脚本。同目录下,创建一个文件夹,名为trainner,用于存放我们训练后的识别器。
4;测试:由于项目需要实现口罩的检测功能,但是经过查找opencv的API文档,并没有找到针对口罩的识别模型,所以,通过思考和小组讨论,因为口罩主要是掩盖了口鼻,所以以是否检测到下半部分的嘴巴替代,如果检测到嘴巴,并框选出来,则说明并没有佩戴口罩,若没有检测到嘴,则说明有按照防控标准佩戴口罩。LBP是一种特征提取方式,能提取出图像的局部的纹理特征,最开始的LBP算子是在3X3窗口中,取中心像素的像素值为阀值,与其周围八个像素点的像素值比较,若像素点的像素值大于阀值,则此像素点被标记为1,否则标记为0。这样就能得到一个八位二进制的码,转换为十进制即LBP码,于是得到了这个窗口的LBP值,用这个值来反映这个窗口内的纹理信息。LBPH是在原始LBP上的一个改进,在opencv支持下我们可以直接调用函数直接创建一个LBPH人脸识别的模型。就此开始通过face.LBPHFaceRecognizer_create读取前一步的训练模型,定义数组,填入队员姓名,同样的,通过内置摄像头扫出人脸,并转换为灰度,并记录下人脸是识别范围,作为下一步检测嘴的区域范围,进一步缩小工作量,以达到更为准确的识别读取。为了实现检测是否有嘴巴,我们通过len()方法对画出的矩形框进行与0的比较,大于0则打印没带口罩,小于0则打印有带口罩,并通过之前识别的数据,进行格式化输出并打印在对话框中,并在程序最后设置了窗口等待以及键盘控制退出等按钮的设置,以及在左上角设置了相关的fps参数,来显示面部识别的帧数,更加直观的呈现了数据,最后关闭摄像头,并释放窗口。
代码如下:
face_collect.py
这个是收集101张人脸
**
然后注意一下,下面的yml文件,和xml文件,必须都用绝对路径来写!!!!!!
**
import cv2
#计数
count = 0
#输入id
face_id = input('\n enter user id:')
#输入姓名
username = input('\n enter user name:')
print('\n 正在初始化脸部识别,请保持在摄像头前面 .......')
# 读取内置摄像头中的图像,获取图像grabbed为true
cap = cv2.VideoCapture(0)
# 加载人脸分类识别器
face_detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')#改成这个文件的绝对路径!!!
while True:
grabbed, img = cap.read()
# 图片转灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(img_gray,1.3, 5)
for x, y, w, h in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=1)
count += 1
# 保存图像
''
#待处理
''
filename = r"mask_faces/" + username + "." + str(face_id) + '.' + str(count) + '.jpg'
print(filename)
#通过绝对路径保存jpg图片
cv2.imwrite(filename, img_gray[y: y + h, x: x + w])
#展示
cv2.imshow("detecting", img)
#按q退出并保持窗口10s
if ord('q') == cv2.waitKey(10):
break
#若保存了100次,则退出保存程序
elif count > 100:
break
#关闭摄像头
cv2.destroyAllWindows()
cap.release()
face_trainer.py
将上文收集的jpg图片训练成自己的yml文件
YAML(Yet Another Markup Language)(发音 /ˈjæməl/ ) 一种基于Unicode容易阅读,容易和脚本语言交互的,用来表达资料序列的编程语言。就很神奇,收集的人脸会变成一系列数据来使用,并存放在yml文件中
import numpy as np
from PIL import Image
import os
import cv2
print("开始")
# 人脸数据路径
path = r'total_faces/'
recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')#这边建议全部使用绝对路径,确保能够调用的到!
def getImagesAndLabels(path):
imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
faceSamples = []
ids = []
for imagePath in imagePaths:
PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
img_numpy = np.array(PIL_img, 'uint8')
id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(img_numpy)
for (x, y, w, h) in faces:
faceSamples.append(img_numpy[y:y + h, x: x + w])
ids.append(id)
return faceSamples, ids
print('Training faces. It will take a few seconds. Wait ...')
faces, ids = getImagesAndLabels(path)
recognizer.train(faces, np.array(ids))
#定义训练路径
recognizer.write(r'face_trainer\trainer.yml')
print("{0} faces trained. Exiting Program".format(len(np.unique(ids))))
print('over')
face_main.py
# 从视频中识别人脸
import cv2 as cv
import time
def face_recognition():
t_start = time.time()
fps = 0
recognizer = cv.face.LBPHFaceRecognizer_create()
# 读取训练数据
recognizer.read('G:/python_program/Basement/face_trainer/trainer.yml') #之前训练的模型
face_detector = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml') #那个包里面下载的模型
mouth_detector = cv.CascadeClassifier("G:/haarshare/haarcascade_mcs_mouth.xml") #嘴巴模型
#字体
font = cv.FONT_HERSHEY_SIMPLEX
feature_id=None
# 以训练的时候,按人脸id进行排序
names = [' ','dai jun','li zhi ming','wang fei'] #下角标是从0开始,所以起始插入一个空字符来占位
cap = cv.VideoCapture(0)
# minW = 0.1*cap.get(3)
# minH = 0.1*cap.get(4)
while True:
grabbed, img = cap.read()
if grabbed:
print("frame:", img.shape)
else:
break
# 图片转灰度
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(img_gray)
for x, y, w, h in faces:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=1)
# 预测
feature_id, confidence = recognizer.predict(img_gray[y:y + h, x:x + w])
print(feature_id-1, " ", confidence)
# 检查嘴
# mouth_zone = mouth_detector.detectMultiScale(head_down, 1.3, 3, minSize=(10, 10))
# 记录下脸部位置,作为识别嘴巴的区域范围
face_area = img[y:y + h, x:x + w]
# # 在记录下的脸部区域识别嘴巴
mouth = mouth_detector.detectMultiScale(face_area,scaleFactor=1.1,minNeighbors=5,minSize=(50, 50))
print(mouth)
# 框出嘴巴
for (mx, my, mw, mh) in mouth:
cv.rectangle(face_area, (mx, my), (mx + mw, my + mh), (0, 255, 0), 1)
#判断是否有嘴巴
#问题:如何检测矩形框的有无返回值的方法,如果返回有,则没带口罩,无,则有带
if len(mouth) > 0:
print(len(mouth))
print("没有戴口罩")
cv.putText(img, 'no mask', (x-50, y + 200), 3, 1.3, (0, 255, 0), 2)
else:
pass
#cv.putText(img, 'has mask', (x - 50, y + 200), 3, 1.3, (0, 255, 0), 2)
else:
if len(mouth) <= 0:
cv.putText(img, 'has mask', (x - 50, y + 200), 3, 1.3, (0, 255, 0), 2)
if confidence < 100:
features = names[feature_id]
print(features)
confidence = "{0}%".format(round(100 - confidence))
else:
features = "unknown"
confidence = "{0}%".format(round(100 - confidence))
cv.putText(img, str(features), (x + 5, y - 5), font, 1, (0, 255, 0), 4)
cv.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (0, 255, 0), 4)
# Calculate and show the FPS
fps = fps + 1
sfps = fps / (time.time() - t_start)
cv.putText(img, "FPS : " + str(int(sfps)), (10, 10), cv.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,0), 2)
cv.imshow("recognizing", img)
if ord('q') == cv.waitKey(10):
break
cv.destroyAllWindows()
cap.release()
if __name__ == '__main__':
face_recognition()
成果展示
本人上镜哈哈哈哈哈
总结
其实这些也都是抄来抄去,改来改去的,懂大概就行了,这个识别度说真的,不咋地,只能拿来骗人哈哈哈,要真拿去用就糗大了哈哈哈哈,主要就是三步走:
第一次写,就这样啦,比赛是输了,也敲醒了警钟,电子信息专业不会硬件????重新做人
上一篇: 微信小程序实现添加手机联系人功能示例
下一篇: JS实现小球的弹性碰撞效果
推荐阅读
-
基于jupyter notebook的python编程(Win10通过OpenCv-3.4.1进行人脸口罩数据集的模型训练并进行戴口罩识别检测)
-
基于Python+OpenCV的人脸口罩识别检测
-
基于树莓派opencv-Python的人脸识别
-
基于树莓派和OpenCV的人脸识别
-
基于树莓派opencv—Python的人脸面部特征框选(眼睛和微笑)
-
juypter 基于keras训练的笑脸检测+口罩人脸识别
-
戴口罩场景下的口罩检测+人脸识别(百度的PaddleHub+OpenCV)
-
用树莓派3B+和Python+OpenCV实现实时的人脸检测
-
三种人脸检测方法(opencv,dlib,openpose)的戴口罩识别效果测试
-
摄像头人脸检测的树莓派指纹识别系统