opencv人像采集:
使用opencv进行人像采集,其中使用ssd人脸检测器(快且准),详细代码如下get_face.py
:
import os
import cv2
import numpy as np
from cv2_face_detector import FaceDetector
# OpenCv 调用摄像头 use camera
cap = cv2.VideoCapture(0)
cnt_ss = 0
# 存储人脸的文件夹
current_face_dir = ""
# 保存 faces images 的路径
path_photos_from_camera = "./faces_from_camera/"
# 新建保存人脸图像文件
def pre_work_mkdir():
if os.path.isdir(path_photos_from_camera):
pass
else:
os.mkdir(path_photos_from_camera)
pre_work_mkdir()
# 如果有之前录入的人脸
# 在之前 person_x 的序号按照 person_x+1 开始录入
if os.listdir("./faces_from_camera/"):
# 获取已录入的最后一个人脸序号 / get the num of latest person
person_list = os.listdir("./faces_from_camera/")
person_num_list = []
for person in person_list:
person_num_list.append(int(person.split('_')[-1]))
person_cnt = max(person_num_list)
# 如果第一次存储或者没有之前录入的人脸, 按照 person_1 开始录入
else:
person_cnt = 0
# 之后用来控制是否保存图像的 flag
save_flag = 1
# 之后用来检查是否先按 'n' 再按 's'
press_n_flag = 0
# 使用ssd 人脸检测器
faceDetector = FaceDetector('ssd', 0.5)
# 字体类型
font = cv2.FONT_HERSHEY_COMPLEX
while cap.isOpened():
flag, img_rd = cap.read()
kk = cv2.waitKey(1)
frame = img_rd.copy()
faces = faceDetector.detect(frame)
# 固定截取窗口
(x,y,w,h) = (150,100,250,250)
cv2.rectangle(frame, (x, y),(x+w, y+h),
(0, 0, 255) , 2)
# press 'n' to create the folders for saving faces
if kk == ord('n'):
person_cnt += 1
current_face_dir = path_photos_from_camera + "person_" + str(person_cnt)
os.makedirs(current_face_dir)
print('\n')
print("新建的人脸文件夹 / Create folders: ", current_face_dir)
cnt_ss = 0 # clear the cnt of faces
press_n_flag = 1 # have pressed 'n'
# 检测到人脸
if len(faces) != 0:
print(len(faces))
for rect in faces:
(x, y, w, h) = rect
cv2.rectangle(frame, (x, y),(x+w, y+h),
(0, 255, 0) , 2)
if save_flag:
# press 's' to save faces into local images
if kk == ord('s'):
# check if you have pressed 'n'
if press_n_flag:
cnt_ss += 1
# 保存固定窗口截图
im_blank = img_rd[100:350,150:400,:]
cv2.imwrite(current_face_dir + '/' +str("%03d" % cnt_ss) + ".jpg", im_blank)
print("写入本地 / Save into:", str(current_face_dir)+ '/' + str("%03d" % cnt_ss) + ".jpg")
else:
print("Please press 'N' before 'S'")
# # 添加说明 / add some statements
cv2.putText(frame, "Face Register", (20, 40), font, 1, (0, 0, 0), 1, cv2.LINE_AA)
cv2.putText(frame, "N: New face folder", (20, 350), font, 0.8, (0, 0, 0), 1, cv2.LINE_AA)
cv2.putText(frame, "S: Save current face", (20, 400), font, 0.8, (0, 0, 0), 1, cv2.LINE_AA)
cv2.putText(frame, "Q: Quit", (20, 450), font, 0.8, (0, 0, 0), 1, cv2.LINE_AA)
# show the numbers of faces detected
cv2.putText(img_rd, "Faces: " + str(len(faces)), (20, 100), font, 0.8, (0, 255, 0), 1, cv2.LINE_AA)
# press 'q' to exit
if kk == ord('q'):
break
# 如果需要摄像头窗口大小可调
cv2.namedWindow("camera", 0)
cv2.imshow("camera", frame)
# 释放摄像头 / release camera
cap.release()
cv2.destroyAllWindows()
facenet提取人脸特征:
mtcnn检测人脸,剪裁有效人脸区域
facene提取人脸特征
详细代码如下face_feature.py
import cv2
import csv
from os.path import join as pjoin
import skimage
import tensorflow as tf
import numpy as np
import os
import facenet
import align.detect_face
minsize = 20 # minimum size of face
threshold = [ 0.6, 0.7, 0.7 ] # three steps's threshold
factor = 0.709 # scale factor
# 创建mtcnn网络,并加载参数
print('Creating networks and loading parameters')
with tf.Graph().as_default():
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.5)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
with sess.as_default():
pnet, rnet, onet = align.detect_face.create_mtcnn(sess, None)
def load_and_align_data(image, image_size, margin, gpu_memory_fraction):
# 读取图片
img = image
# 获取图片的shape
img_size = np.asarray(img.shape)[0:2]
# 返回边界框数组 (参数分别是输入图片 脸部最小尺寸 三个网络 阈值 factor不清楚)
bounding_boxes, _ = align.detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
# 如果检测出图片中不存在人脸 则直接返回,return 0(表示不存在人脸,跳过此图)
if len(bounding_boxes) < 1:
return 0,0,0
else:
crop=[]
det=bounding_boxes
det[:,0]=np.maximum(det[:,0], 0)
det[:,1]=np.maximum(det[:,1], 0)
det[:,2]=np.minimum(det[:,2], img_size[1])
det[:,3]=np.minimum(det[:,3], img_size[0])
det=det.astype(int)
for i in range(len(bounding_boxes)):
temp_crop=img[det[i,1]:det[i,3],det[i,0]:det[i,2],:]
aligned=skimage.transform.resize(temp_crop, (image_size, image_size))
prewhitened = facenet.prewhiten(aligned)
crop.append(prewhitened)
crop_image=np.stack(crop)
return det,crop_image,1
def to_rgb(img):
w, h = img.shape
ret = np.empty((w, h, 3), dtype=np.uint8)
ret[:, :, 0] = ret[:, :, 1] = ret[:, :, 2] = img
return ret
def load_data(data_dir):
# data为字典类型 key对应人物分类 value为读取的一个人的所有图片 类型为ndarray
data = {}
pics_ctr = 0
for guy in os.listdir(data_dir):
person_dir = pjoin(data_dir, guy)
curr_pics = [read_img(person_dir, f) for f in os.listdir(person_dir)]
# 存储每一类人的文件夹内所有图片
data[guy] = curr_pics
return data
def read_img(person_dir,f):
img=cv2.imread(pjoin(person_dir, f))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 判断数组维度
if gray.ndim == 2:
img = to_rgb(gray)
return img
# 模型位置
model_dir='./models/facenet/'
with tf.Graph().as_default():
with tf.Session() as sess:
# 加载facenet模型
facenet.load_model(model_dir)
# 返回给定名称的tensor
images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
# 从训练数据文件夹中加载图片并剪裁,最后embding,data为dict
data=load_data('./train_data/')
# keys列表存储图片文件夹类别(几个人)
keys=[]
for key in data:
keys.append(key)
print('folder:{},image numbers:{}'.format(key,len(data[key])))
# 使用mtcnn模型获取每张图中face的数量以及位置,并将得到的embedding数据存储
for n in range(len(keys)):
for x in data[keys[n]]:
_,images_me,i = load_and_align_data(x, 160, 44, 1.0)
if i:
feed_dict = { images_placeholder: images_me, phase_train_placeholder:False }
emb = sess.run(embeddings, feed_dict=feed_dict)
for xx in range(len(emb)):
emb=list(emb[xx,:])
emb.append(keys[n])
with open('face_feature.csv', "a+", newline="") as csvfile:
writer = csv.writer(csvfile)
writer.writerow(emb)
人脸特征库建立
上述步骤生成文件face_feature.csv
即为已经采集的人脸特征库;
效果验证
在数据集处理过程中,已经将数据集分为训练集和测试集,比例约为8:2,经过验证比对,平均准确率达到百分之95以上,具体每个类别识别准确率如下:
name== yin123
acc: 1.0
name== liu123
acc: 0.9855072463768116
name== yu123
acc: 1.0
name== ma123
acc: 0.9821428571428571
name== zhou123
acc: 0.9912280701754386
name== wang123
acc: 1.0
name== xu123
acc: 1.0
name== taojinglong
acc: 0.8529411764705882
实时检测
设备描述:8g内存+i7+gtx960m+自带摄像头
详细代码如face_recognition.py
检测效果如图:
备注