基于Python+Keras+OpenCV实现实时人脸活体检测
磐创AI你在互联网上找到的大多数人脸识别算法和研究论文都会遭受照片攻击。这些方法在检测和识别来自网络摄像头的图像、视频和视频流中的人脸方面是非常有效,但是他们无法区分现实生活中的面孔和照片上的面孔。这种无法区别现实人脸的现象是由于这些算法是在二维帧上工作的。现在让我们去试想一下,我们实现一个人脸识别系统,该系统可以很好地区分已知面孔和未知面孔,以便只有授权人员才能访问,尽管如此,一个心怀不轨的人只要出示授权人的照片也能访问。至此一个3D人脸的识别系统,类似于苹果的FaceID,应运而生了,但如果我们没有3D探测器该怎么办呢?
本文的目标是实现一种基于眨眼检测的人脸活体检测算法,以抵抗照片攻击。该算法通过网络摄像头实时工作,通过检测眨眼来区分现实生活中的面孔和照片上的面孔。通俗地说,程序运行如下:在网络摄像头生成的每个帧中检测人脸。对于每个检测到的脸,检测眼睛。对于每个检测到的眼睛,检测眼睛是否睁开或关闭。如果在某个时候检测到眼睛是睁开的,然后是闭着的,然后是睁开的,我们就断定此人已经眨了眼睛,并且程序显示他的名字(如果是人脸识别开门器,我们将授权此人进入)。对于人脸的检测和识别,你需要安装face_recognition库,它提供了非常有用的深度学习方法来查找和识别图像中的人脸,特别是,face_locations、face_encodings和compare_faces函数是最有用的3个函数。人脸定位方法可以用两种方法来检测人脸:方向梯度直方图(HoG)和卷积神经网络(CNN),由于时间限制,选择了HoG方法。face_encodings函数是一个预先训练的卷积神经网络,能够将图像编码成128哥元素的一维特征向量,这个嵌入向量包含足够的特征信息来区分两个不同的人,最后,compare_faces计算两个嵌入向量之间的距离。它将允许算法识别从摄像头帧中提取的人脸,并将其嵌入向量与我们数据集中所有编码的人脸进行比较,距离最近的向量对应于同一个人。1. 已知人脸数据集编码在我的例子中,算法能够识别我和奥巴马,我为每个人挑选了大约10张照片。下面是处理和编码已知人脸数据库的代码。def process_and_encode(images):
known_encodings = [] known_names = [] print("[LOG] Encoding dataset ...")
for image_path in tqdm(images): # 加载图片 image = cv2.imread(image_path) # 将其从BGR转换为RGB image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 检测图像中的脸并获取其位置(方框坐标) boxes = face_recognition.face_locations(image, model='hog')
# 将人脸编码为128维嵌入向量 encoding = face_recognition.face_encodings(image, boxes)
# 人物名称是图像来源文件夹的名称 name = image_path.split(os.path.sep)[-2]
if len(encoding) > 0 : known_encodings.append(encoding[0]) known_names.append(name)
return {"encodings": known_encodings, "names": known_names}现在我们知道了每个想识别的人的编码,我们可以尝试通过网络摄像头识别人脸,然而,在转到这一部分之前,我们需要区分一张人脸照片和一张活人的脸。2.人脸活体检测我们的目标是在某个点上检测出一个睁闭的睁眼模式。我训练了一个卷积神经网络来分类眼睛是闭着的还是睁着的,所选择的模型是LeNet-5,它已经在Closed Eyes In The Wild (CEW)数据集上进行了训练,它由大约4800张24x24大小的眼睛图像组成。Closed Eyes In The Wild (CEW)数据集地址:http://parnec.nuaa.edu.cn/xtan/data/ClosedEyeDatabases.htmlfrom keras.models
import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import AveragePooling2Dfrom keras.layers import Flattenfrom keras.layers import Densefrom keras.preprocessing.image
import ImageDataGenerator
IMG_SIZE = 24def train(train_generator, val_generator): STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size STEP_SIZE_VALID=val_generator.n//val_generator.batch_size
model = Sequential()
model.add(Conv2D(filters=6, kernel_size=(3, 3), activation='relu', input_shape=(IMG_SIZE,IMG_SIZE,1))) model.add(AveragePooling2D())
model.add(Conv2D(filters=16, kernel_size=(3, 3), activation='relu')) model.add(AveragePooling2D())
model.add(Flatten())
model.add(Dense(units=120, activation='relu'))
model.add(Dense(units=84, activation='relu'))
model.add(Dense(units=1, activation = 'sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print('[LOG] Training CNN')
model.fit_generator(generator=train_generator,steps_per_epoch=STEP_SIZE_TRAIN,validation_data=val_generator,validation_steps=STEP_SIZE_VALID, epochs=20 ) return model在评估模型时,我达到了94%的准确率。每次我们检测到一只眼睛,我们就用我们的模型来预测它的状态,并跟踪每个人的眼睛状态,因此,检测眨眼变得非常容易,它试图在眼睛状态历史中找到一个闭眼-睁眼-闭眼的过程。
1 2 下一页>