0%

opencv-flask-web人脸识别

本文介绍了基于OpenCV 和 Python 、Flask的web人脸检测项目。

  • 1):人脸图片收集
  • 2):人脸数据训练
  • 3):人脸识别
  • 4):集成到Flask 提供web接口

人脸识别的最基础任务是「人脸检测」。你必须首先「捕捉」人脸(第 1 阶段)才能在未来与捕捉到的新人脸对比时(第 3 阶段)识别它。

最常见的人脸检测方式是使用「Haar 级联分类器」。使用基于 Haar 特征的级联分类器的目标检测是 Paul Viola 和 Michael Jones 2001 年在论文《Rapid Object Detection using a Boosted Cascade of Simple Features》中提出的一种高效目标检测方法。这种机器学习方法基于大量正面、负面图像训练级联函数,然后用于检测其他图像中的对象。这里,我们将用它进行人脸识别。最初,该算法需要大量正类图像(人脸图像)和负类图像(不带人脸的图像)来训练分类器。然后我们需要从中提取特征。好消息是 OpenCV 具备训练器和检测器。

web提供3个接口

地址 接口名称
/ 首页
/dataset?share_id 人脸数据收集(参数-人姓名)
/recognition 人脸验证

main.py

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
from flask import Flask, render_template, Response, request
from camera import VideoCamera
import cv2
app = Flask(__name__)

@app.route('/')
def index():
return render_template('index.html')

def gen(camera):
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')
def video_feed():
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/dataset', methods = ["GET"])
def dataset():
face_id = request.args.get("face_id")
camera = VideoCamera()
camera.data_set(face_id)
msg = "%s%s" %(face_id, "采集完成")
content = {"msg": msg}
return render_template('index.html')

@app.route('/recognition', methods = ["GET"])
def recognition():
camera = VideoCamera()
face_name = camera.recognition()
msg = "认证结果为:%s" %(face_name)
content = {"msg": msg}
return render_template('index.html', **content)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)

camera.py
haarcascade_frontalface_default.xml 文件需使用自己本地的,如果使用网上的 需要本地新建文件 然后把内容复制到本地,不然会报错

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
95
96
97
98
99
100
101
102
103
104
105
106
107
import cv2,os
import numpy as np
from PIL import Image
import pymongo,random

class VideoCamera(object):
def __init__(self):
# Using OpenCV to capture from device 0. If you have trouble capturing
# from a webcam, comment the line below out and use a video file
# instead.
self.video = cv2.VideoCapture(0)
self.video.set(3, 640)
self.video.set(4, 480)
self.face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#width = int(self.video .get(cv2.CAP_PROP_FRAME_WIDTH) + 0.5)
#height = int(self.video .get(cv2.CAP_PROP_FRAME_HEIGHT) + 0.5)
#fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 第三个参数则是镜头快慢的,10为正常,小于10为慢镜头
#self.out = cv2.VideoWriter('./output2.avi', fourcc,10,(width,height))
# If you decide to use video.mp4, you must have this file in the folder
# as the main.py.
# self.video = cv2.VideoCapture('video.mp4')
mongodbs = pymongo.MongoClient('127.0.0.1', 27017)
self.face = mongodbs.face
self.path = "dataset"
def __del__(self):
self.video.release()

def get_frame(self):
success, image = self.video.read()
#frame = cv2.flip(image, 1)
#a = self.out.write(frame)
ret, jpeg = cv2.imencode('.jpg', image)
return jpeg.tobytes()

#图片采集
def data_set(self, face_name):
count = 0
face_id = random.randint(0, 100000)
while(True):
ret, img = self.video.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = self.face_detector.detectMultiScale(gray, 1.3, 5)

for (x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
count += 1
# Save the captured image into the datasets folder
cv2.imwrite(self.path+"/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])

k = cv2.waitKey(100) & 0xff # Press 'ESC' for exiting video
if k == 27:
break
elif count >= 30: # Take 30 face sample and stop video
break
self.face.face.save({"face_name":face_name,"face_id":face_id})
self.training()
#图片训练
def training(self):
recognizer = cv2.face.LBPHFaceRecognizer_create()
imagePaths = [os.path.join(self.path,f) for f in os.listdir(self.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 = self.face_detector.detectMultiScale(img_numpy)
for (x,y,w,h) in faces:
faceSamples.append(img_numpy[y:y+h,x:x+w])
ids.append(id)
recognizer.train(faceSamples, np.array(ids))
recognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi
#认证函数
def recognition(self):
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
font = cv2.FONT_HERSHEY_SIMPLEX
minW = 0.1*self.video.get(3)
minH = 0.1*self.video.get(4)
while True:
id = 'unknown'
ret, img = self.video.read()
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

faces = self.face_detector.detectMultiScale(
gray,
scaleFactor = 1.2,
minNeighbors = 5,
minSize = (int(minW), int(minH)),
)

for(x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
id, confidence = recognizer.predict(gray[y:y+h,x:x+w])

# Check if confidence is less them 100 ==> "0" is perfect match
if (confidence < 100):
face = self.face.face.find_one({"face_id":id})
id = id
confidence = " {0}%".format(round(100 - confidence))
else:
id = "unknown"
confidence = " {0}%".format(round(100 - confidence))
if id != "unknown":
break
return face['face_name']

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<html>
<head>
<title>人脸识别</title>
</head>
<body>
<h1>人脸识别</h1>
<input id="face_id" type="text"><br>
<span onclick="face_dataset()" style="cursor:pointer">人脸信息采集</span><br>
<a href="/recognition">人脸信息识别</a><br>
<span></span>
</body>
<script>
function face_dataset(){
var face_id = document.getElementById("face_id").value;
if(!face_id){
confirm("请输入姓名");
return;
}
location.href = "/dataset?face_id=" + face_id;
}
</script>
</html>

参考:
@https://shumeipai.nxez.com/2018/03/09/real-time-face-recognition-an-end-to-end-project-with-raspberry-pi.html
使用 OpenCV 和 Python 从头实现人脸识别 @www.superdatascience.com
理解人脸识别 @www.thecodacus.com