活物识别在生活中有广泛应用,设想如果一个人拿着你的照片去刷脸支付,是不是你钱包就要空了。在生活中,有多种方法进行活物(活体)识别,比如动作指令活体检测(让你眨眼睛等)。这里我们是用CNN(卷积神经网络)来对图片进行分析来识别是否为真人。
最终效果:
首先,我们将我们的项目大致分成三步:
1. 产生训练集
2. 训练模型
3. 验证数据
1. 产生训练集
我们知道,视频是由每一帧组成的,换句话说就是由很多张图片组成的。因此我们如果想要产生训练集,首先要将人脸逐帧截图,分别产生真实(Real)和非真实(Fake)的数据集,具体方法如下:
我们先看一下两段视频
一段是手机自拍(Real),另一段是拿另一个手机录屏(Fake),然后我们导入这两个视频然后逐帧截取人脸。此时,我们需要 face_recognition的功能来识别人脸的具体位置。由于本文章是专注于活物识别的,面部识别就直接使用别人的封包了,具体代码如下:
import cv2
import os
import numpy as np
import face_recognition
from PIL import Image
inputpath_real='video/real.mp4'
inputpath_fake='video/fake.mp4'
outputpath_real='train/real/'
outputpath_fake='train/fake/'
'''
inputpathtest_real='video/real_test.mp4'
inputpathtest_fake='video/fake_test.mp4'
outputpathtest_real='train/real_test/'
outputpathtest_fake='train/fake_test/'
'''
def cut_img (inputpath,outputpath,type,width,height):
vs = cv2.VideoCapture(inputpath)
read = 0
while True:
(grabbed, frame) = vs.read()
if not grabbed:
print('This frame is not grabbed')
break
read +=1
rgb_frame = frame[:, :, ::-1]
face_locations = face_recognition.face_locations(rgb_frame)
for face_location in face_locations:
top, right, bottom, left = face_location
cropped= frame [top:bottom, left:right]
img_name=outputpath+'%s_%d.png' %(type,read)
cv2.imwrite(img_name, cropped,[int(cv2.IMWRITE_PNG_COMPRESSION), 9] )
img = Image.open(img_name)
new_image = img.resize((width, height), Image.BILINEAR) #Resize to 50*50
new_image.save(os.path.join(outputpath, os.path.basename(img_name)))
if __name__ == '__main__':
cut_img(inputpath_real,outputpath_real,'real',50,50)
cut_img(inputpath_fake,outputpath_fake,'fake',50,50)
'''
cut_img(inputpathtest_real, outputpathtest_real, 'real_test', 50, 50)
cut_img(inputpathtest_fake, outputpathtest_fake, 'fake_test', 50, 50)
'''
被注释起来的部分是用来产生测试数据的,有兴趣的可以再录两段测试视频(共四段)。代码很简单,我就不解释了,最后会产生如下效果:
这里,所有的图片(约400张)都被resize到50*50,方便导入CNN。这样我们的训练集就产生了。
2. 训练模型
下面就是我们的重头戏,训练模型了。 我们使用TensorFlow的CNN来构件我们的神经网络:
我们先看一下我们的文件路径等设置:
import os
from PIL import Image
import numpy as np
import tensorflow as tf
import face_recognition
import cv2
#文件路径设置(address)
data_dir_real='train/real/'
data_dir_fake='train/fake/'
test='video/test.mp4'
output_test='train/test_output/'
model_path='train/' # CNN model save address
train= Ture # Ture: Training mode ,False: Validation mode
当train=True是为训练模式,False为验证模式。 data_dir_real和data_dir_fake为之前产生图片的地址,test是用来验证模型的视频路径,output_test则是验证视频产生的人脸图片的路径。
首先第一步读取数据:
def read_data(data_dir_real,data_dir_fake):
datas = []
labels = []
fpaths = []
# Read data of real
for fname in os.listdir(data_dir_real):
fpath = os.path.join(data_dir_real, fname) # Record image name and address
fpaths.append(fpath)
image = Image.open(fpath) # Open image
data = np.array(image) / 255.0 # 归一化(Normalization)
datas.append(data)
labels.append(0) # Take real as 0
# Read data of fake
for fname in os.listdir(data_dir_fake):
fpath = os.path.join(data_dir_fake, fname)
fpaths.append(fpath)
image = Image.open(fpath)
data = np.array(image) / 255.0 # 归一化(Normalization)
datas.append(data)
labels.append(1) # Take fake as 1
datas = np.array(datas)
labels = np.array(labels)
return fpaths, datas,labels
fpaths, datas,labels =