change the method of face detection to increase ac
This commit is contained in:
@@ -9,7 +9,11 @@ import time
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
# 1. Dlib 正向人脸检测器
|
||||
detector = dlib.get_frontal_face_detector()
|
||||
# detector = dlib.get_frontal_face_detector()
|
||||
|
||||
# OpenCV DNN face detector
|
||||
detector = cv2.dnn.readNetFromCaffe("data/data_opencv/deploy.prototxt.txt",
|
||||
"data/data_opencv/res10_300x300_ssd_iter_140000.caffemodel")
|
||||
|
||||
# 2. Dlib 人脸 landmark 特征点检测器
|
||||
predictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')
|
||||
@@ -53,7 +57,7 @@ class Face_Recognizer:
|
||||
else:
|
||||
features_someone_arr.append(csv_rd.iloc[i][j])
|
||||
self.features_known_list.append(features_someone_arr)
|
||||
self.name_known_list.append("Person_"+str(i+1))
|
||||
self.name_known_list.append("Person_" + str(i + 1))
|
||||
self.name_known_cnt = len(self.name_known_list)
|
||||
print("Faces in Database:", len(self.features_known_list))
|
||||
return 1
|
||||
@@ -74,6 +78,8 @@ class Face_Recognizer:
|
||||
dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
|
||||
return dist
|
||||
|
||||
# TODO th
|
||||
|
||||
# 更新 FPS
|
||||
def update_fps(self):
|
||||
now = time.time()
|
||||
@@ -91,7 +97,7 @@ class Face_Recognizer:
|
||||
|
||||
def draw_name(self, img_rd):
|
||||
# 在人脸框下面写人脸名字
|
||||
font = ImageFont.truetype("simsun.ttc", 30)
|
||||
font = ImageFont.truetype("simsun.ttc", 30, index=1)
|
||||
img = Image.fromarray(cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB))
|
||||
draw = ImageDraw.Draw(img)
|
||||
for i in range(self.faces_cnt):
|
||||
@@ -104,7 +110,7 @@ class Face_Recognizer:
|
||||
def modify_name_camera_list(self):
|
||||
# TODO 数据库 ID
|
||||
# Default known name: person_1, person_2, person_3
|
||||
self.name_known_list[0] ='唐麒'.encode('utf-8').decode()
|
||||
self.name_known_list[0] = '唐麒'.encode('utf-8').decode()
|
||||
# self.name_known_list[1] ='李四'.encode('utf-8').decode()
|
||||
# self.name_known_list[2] ='xx'.encode('utf-8').decode()
|
||||
# self.name_known_list[3] ='xx'.encode('utf-8').decode()
|
||||
@@ -116,7 +122,6 @@ class Face_Recognizer:
|
||||
if self.get_face_database():
|
||||
while stream.isOpened():
|
||||
flag, img_rd = stream.read()
|
||||
faces = detector(img_rd, 0)
|
||||
kk = cv2.waitKey(1)
|
||||
# 按下 q 键退出
|
||||
if kk == ord('q'):
|
||||
@@ -128,25 +133,49 @@ class Face_Recognizer:
|
||||
self.pos_camera_list = []
|
||||
self.name_camera_list = []
|
||||
|
||||
(h, w) = img_rd.shape[:2]
|
||||
blob = cv2.dnn.blobFromImage(cv2.resize(img_rd, (300, 300)), 1.0,
|
||||
(300, 300), (104.0, 177.0, 123.0))
|
||||
detector.setInput(blob)
|
||||
faces = detector.forward()
|
||||
|
||||
# 2. 检测到人脸
|
||||
if len(faces) != 0:
|
||||
if faces.shape[2] != 0:
|
||||
# 3. 获取当前捕获到的图像的所有人脸的特征,存储到 self.features_camera_list
|
||||
for i in range(len(faces)):
|
||||
shape = predictor(img_rd, faces[i])
|
||||
for i in range(0, faces.shape[2]):
|
||||
confidence = faces[0, 0, i, 2]
|
||||
|
||||
# filter out weak detections by ensuring the `confidence` is
|
||||
# greater than the minimum confidence
|
||||
if confidence < 0.5:
|
||||
continue
|
||||
box = faces[0, 0, i, 3:7] * np.array([w, h, w, h])
|
||||
(startX, startY, endX, endY) = box.astype("int")
|
||||
rect = dlib.rectangle(startX, startY, endX, endY)
|
||||
shape = predictor(img_rd, rect)
|
||||
self.features_camera_list.append(face_reco_model.compute_face_descriptor(img_rd, shape))
|
||||
|
||||
# 4. 遍历捕获到的图像中所有的人脸
|
||||
for k in range(len(faces)):
|
||||
for k in range(0, faces.shape[2]):
|
||||
# 计算矩形框大小
|
||||
confidence = faces[0, 0, k, 2]
|
||||
|
||||
# filter out weak detections by ensuring the `confidence` is
|
||||
# greater than the minimum confidence
|
||||
if confidence < 0.5:
|
||||
continue
|
||||
print("##### camera person", k + 1, "#####")
|
||||
# 让人名跟随在矩形框的下方
|
||||
# 让人名跟随在矩形框的上方
|
||||
# 确定人名的位置坐标
|
||||
# 先默认所有人不认识,是 unknown
|
||||
# Set the default names of faces with "unknown"
|
||||
self.name_camera_list.append("unknown")
|
||||
|
||||
# 每个捕获人脸的名字坐标
|
||||
box = faces[0, 0, k, 3:7] * np.array([w, h, w, h])
|
||||
(startX, startY, endX, endY) = box.astype("int")
|
||||
self.pos_camera_list.append(tuple(
|
||||
[faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]))
|
||||
[int(startX+5), int(startY - 30)]))
|
||||
|
||||
# 5. 对于某张人脸,遍历所有存储的人脸特征
|
||||
e_distance_list = []
|
||||
@@ -174,8 +203,10 @@ class Face_Recognizer:
|
||||
# 矩形框
|
||||
for kk, d in enumerate(faces):
|
||||
# 绘制矩形框
|
||||
cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]),
|
||||
(0, 255, 255), 2)
|
||||
cv2.rectangle(img_rd, tuple([startX, startY]), tuple([endX, endY]),
|
||||
(0, 255, 0), 2)
|
||||
cv2.rectangle(img_rd, tuple([startX, startY - 35]), tuple([endX, startY]),
|
||||
(0, 255, 0), cv2.FILLED)
|
||||
print('\n')
|
||||
|
||||
self.faces_cnt = len(faces)
|
||||
@@ -210,4 +241,4 @@ def main():
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -4,13 +4,17 @@ import os
|
||||
import dlib
|
||||
from skimage import io
|
||||
import csv
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
# 要读取人脸图像文件的路径
|
||||
path_images_from_camera = "data/data_faces_from_camera/"
|
||||
|
||||
# 1. Dlib 正向人脸检测器
|
||||
detector = dlib.get_frontal_face_detector()
|
||||
# detector = dlib.get_frontal_face_detector()
|
||||
# OpenCV DNN face detector
|
||||
detector = cv2.dnn.readNetFromCaffe("data/data_opencv/deploy.prototxt.txt",
|
||||
"data/data_opencv/res10_300x300_ssd_iter_140000.caffemodel")
|
||||
|
||||
# 2. Dlib 人脸 landmark 特征点检测器
|
||||
predictor = dlib.shape_predictor('data/data_dlib/shape_predictor_68_face_landmarks.dat')
|
||||
@@ -22,14 +26,21 @@ face_reco_model = dlib.face_recognition_model_v1("data/data_dlib/dlib_face_recog
|
||||
# 返回单张图像的 128D 特征
|
||||
def return_128d_features(path_img):
|
||||
img_rd = io.imread(path_img)
|
||||
faces = detector(img_rd, 1)
|
||||
(h, w) = img_rd.shape[:2]
|
||||
blob = cv2.dnn.blobFromImage(cv2.resize(img_rd, (300, 300)), 1.0,
|
||||
(300, 300), (104.0, 177.0, 123.0))
|
||||
detector.setInput(blob)
|
||||
faces = detector.forward()
|
||||
|
||||
print("%-40s %-20s" % ("检测到人脸的图像 / Image with faces detected:", path_img), '\n')
|
||||
|
||||
# 因为有可能截下来的人脸再去检测,检测不出来人脸了
|
||||
# 所以要确保是 检测到人脸的人脸图像 拿去算特征
|
||||
if len(faces) != 0:
|
||||
shape = predictor(img_rd, faces[0])
|
||||
if faces.shape[2] != 0:
|
||||
box = faces[0, 0, 0, 3:7] * np.array([w, h, w, h])
|
||||
(startX, startY, endX, endY) = box.astype("int")
|
||||
rect = dlib.rectangle(startX, startY, endX, endY)
|
||||
shape = predictor(img_rd, rect)
|
||||
face_descriptor = face_reco_model.compute_face_descriptor(img_rd, shape)
|
||||
else:
|
||||
face_descriptor = 0
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
# 进行人脸录入 / face register
|
||||
# 录入多张人脸 / support multi-faces
|
||||
|
||||
import dlib # 人脸处理的库 Dlib
|
||||
import numpy as np # 数据处理的库 Numpy
|
||||
import cv2 # 图像处理的库 OpenCV
|
||||
import os # 读写文件
|
||||
import shutil # 读写文件
|
||||
import dlib
|
||||
import numpy as np
|
||||
import cv2
|
||||
import os
|
||||
import shutil # 读写文件
|
||||
import time
|
||||
import face_recognition
|
||||
|
||||
# Dlib 正向人脸检测器
|
||||
detector = dlib.get_frontal_face_detector()
|
||||
# detector = dlib.get_frontal_face_detector()
|
||||
|
||||
# OpenCV DNN face detector
|
||||
detector = cv2.dnn.readNetFromCaffe("data/data_opencv/deploy.prototxt.txt",
|
||||
"data/data_opencv/res10_300x300_ssd_iter_140000.caffemodel")
|
||||
|
||||
|
||||
class Face_Register:
|
||||
@@ -17,9 +22,9 @@ class Face_Register:
|
||||
self.path_photos_from_camera = "data/data_faces_from_camera/"
|
||||
self.font = cv2.FONT_ITALIC
|
||||
|
||||
self.existing_faces_cnt = 0 # 已录入的人脸计数器
|
||||
self.ss_cnt = 0 # 录入 personX 人脸时图片计数器
|
||||
self.faces_cnt = 0 # 录入人脸计数器
|
||||
self.existing_faces_cnt = 0 # 已录入的人脸计数器
|
||||
self.ss_cnt = 0 # 录入 personX 人脸时图片计数器
|
||||
self.faces_cnt = 0 # 录入人脸计数器
|
||||
|
||||
# 之后用来控制是否保存图像的 flag
|
||||
self.save_flag = 1
|
||||
@@ -42,7 +47,7 @@ class Face_Register:
|
||||
# 删除之前存的人脸数据文件夹
|
||||
folders_rd = os.listdir(self.path_photos_from_camera)
|
||||
for i in range(len(folders_rd)):
|
||||
shutil.rmtree(self.path_photos_from_camera+folders_rd[i])
|
||||
shutil.rmtree(self.path_photos_from_camera + folders_rd[i])
|
||||
if os.path.isfile("data/features_all.csv"):
|
||||
os.remove("data/features_all.csv")
|
||||
|
||||
@@ -85,15 +90,21 @@ class Face_Register:
|
||||
# self.pre_work_mkdir()
|
||||
|
||||
# 2. 删除 "/data/data_faces_from_camera" 中已有人脸图像文件
|
||||
self.pre_work_del_old_face_folders()
|
||||
# self.pre_work_del_old_face_folders()
|
||||
|
||||
# 3. 检查 "/data/data_faces_from_camera" 中已有人脸文件
|
||||
self.check_existing_faces_cnt()
|
||||
|
||||
while stream.isOpened():
|
||||
flag, img_rd = stream.read() # Get camera video stream
|
||||
flag, img_rd = stream.read() # Get camera video stream
|
||||
|
||||
kk = cv2.waitKey(1)
|
||||
faces = detector(img_rd, 0) # Use dlib face detector
|
||||
|
||||
(h, w) = img_rd.shape[:2]
|
||||
blob = cv2.dnn.blobFromImage(cv2.resize(img_rd, (300, 300)), 1.0,
|
||||
(300, 300), (104.0, 177.0, 123.0))
|
||||
detector.setInput(blob)
|
||||
faces = detector.forward()
|
||||
|
||||
# 4. 按下 'n' 新建存储人脸的文件夹
|
||||
if kk == ord('n'):
|
||||
@@ -103,37 +114,50 @@ class Face_Register:
|
||||
print('\n')
|
||||
print("新建的人脸文件夹 / Create folders: ", current_face_dir)
|
||||
|
||||
self.ss_cnt = 0 # 将人脸计数器清零
|
||||
self.press_n_flag = 1 # 已经按下 'n'
|
||||
self.ss_cnt = 0 # 将人脸计数器清零
|
||||
self.press_n_flag = 1 # 已经按下 'n'
|
||||
|
||||
# 5. 检测到人脸
|
||||
if len(faces) != 0:
|
||||
if faces.shape[2] != 0:
|
||||
# 矩形框
|
||||
for k, d in enumerate(faces):
|
||||
for i in range(0, faces.shape[2]):
|
||||
# 计算矩形框大小
|
||||
height = (d.bottom() - d.top())
|
||||
width = (d.right() - d.left())
|
||||
hh = int(height/2)
|
||||
ww = int(width/2)
|
||||
confidence = faces[0, 0, i, 2]
|
||||
|
||||
# filter out weak detections by ensuring the `confidence` is
|
||||
# greater than the minimum confidence
|
||||
if confidence < 0.5:
|
||||
continue
|
||||
|
||||
# compute the (x, y)-coordinates of the bounding box for the
|
||||
# object
|
||||
box = faces[0, 0, i, 3:7] * np.array([w, h, w, h])
|
||||
(startX, startY, endX, endY) = box.astype("int")
|
||||
|
||||
height = (endY - startY)
|
||||
width = (endX - startX)
|
||||
hh = int(height / 2)
|
||||
ww = int(width / 2)
|
||||
|
||||
# 6. 判断人脸矩形框是否超出 480x640
|
||||
if (d.right()+ww) > 640 or (d.bottom()+hh > 480) or (d.left()-ww < 0) or (d.top()-hh < 0):
|
||||
if (endX + ww) > 640 or (endY + hh > 480) or (startX - ww < 0) or (
|
||||
startY - hh < 0):
|
||||
cv2.putText(img_rd, "OUT OF RANGE", (20, 300), self.font, 0.8, (0, 0, 255), 1, cv2.LINE_AA)
|
||||
color_rectangle = (0, 0, 255)
|
||||
save_flag = 0
|
||||
if kk == ord('s'):
|
||||
print("请调整位置 / Please adjust your position")
|
||||
else:
|
||||
color_rectangle = (255, 255, 255)
|
||||
color_rectangle = (0, 255, 0)
|
||||
save_flag = 1
|
||||
|
||||
cv2.rectangle(img_rd,
|
||||
tuple([d.left() - ww, d.top() - hh]),
|
||||
tuple([d.right() + ww, d.bottom() + hh]),
|
||||
tuple([startX - ww, startY - hh]),
|
||||
tuple([endX + ww, endY + hh]),
|
||||
color_rectangle, 2)
|
||||
|
||||
# 7. 根据人脸大小生成空的图像
|
||||
img_blank = np.zeros((int(height*2), width*2, 3), np.uint8)
|
||||
img_blank = np.zeros((int(height * 2), width * 2, 3), np.uint8)
|
||||
|
||||
if save_flag:
|
||||
# 8. 按下 's' 保存摄像头中的人脸到本地
|
||||
@@ -141,11 +165,12 @@ class Face_Register:
|
||||
# 检查有没有先按'n'新建文件夹
|
||||
if self.press_n_flag:
|
||||
self.ss_cnt += 1
|
||||
for ii in range(height*2):
|
||||
for jj in range(width*2):
|
||||
img_blank[ii][jj] = img_rd[d.top()-hh + ii][d.left()-ww + jj]
|
||||
for ii in range(height * 2):
|
||||
for jj in range(width * 2):
|
||||
img_blank[ii][jj] = img_rd[startY - hh + ii][startX - ww + jj]
|
||||
cv2.imwrite(current_face_dir + "/img_face_" + str(self.ss_cnt) + ".jpg", img_blank)
|
||||
print("写入本地 / Save into:", str(current_face_dir) + "/img_face_" + str(self.ss_cnt) + ".jpg")
|
||||
print("写入本地 / Save into:",
|
||||
str(current_face_dir) + "/img_face_" + str(self.ss_cnt) + ".jpg")
|
||||
else:
|
||||
print("请先按 'N' 来建文件夹, 按 'S' / Please press 'N' and press 'S'")
|
||||
self.faces_cnt = len(faces)
|
||||
|
||||
BIN
Class/collect_data/simsun.ttc
Normal file
BIN
Class/collect_data/simsun.ttc
Normal file
Binary file not shown.
1789
Data/data_opencv/deploy.prototxt.txt
Normal file
1789
Data/data_opencv/deploy.prototxt.txt
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Data/data_opencv/res10_300x300_ssd_iter_140000.caffemodel
Normal file
BIN
Data/data_opencv/res10_300x300_ssd_iter_140000.caffemodel
Normal file
Binary file not shown.
Reference in New Issue
Block a user