目录
前言
课题背景和意义
实现技术思路
实现效果图样例
前言
📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投入到更重要的就业和考试中去,学长分享优质的选题经验和毕设项目与技术思路。
🚀对毕设有任何疑问都可以问学长哦!
大家好,这里是海浪学长毕设专题,本次分享的课题是
🎯机器学习人眼检测活体检测
课题背景和意义
小朋友用妈妈的一寸照片通过了人脸识别,打击了小度音箱的家长监督机制。
活体检测没做好。
公交车身广告上的董明珠头像,被宁波交警系统拍了照,判定成“违法闯红灯”。
活体检测没做好。
实现技术思路
活体检测,可以检测些什么?
一是纹理分析 (Texture Analysis) 。皮肤的纹理特征是重要的依据,给2D照片拍照,比起给3D真人拍照,会损失一些纹理。
二是频率分析 (Frequency Analysis) 。照片脸部的频率组成,也不像真人那样丰富。
三是可变聚焦分析 (Variable focusing Analysis) 。连拍两张照片,聚焦在不同位置,查看像素值 (Pixel Value) 的变化。
四是启发式算法 (Heuristic-Based Algorithms) 。眼动、唇动、眨眼这些动作,照片是不会有的。
五是光流算法 (Optical Flow Algorithms) 。在相邻两帧之间,检测物体运动的方向和幅度,查出2D和3D物体之间的差别。
-
在网络摄像头生成的每个帧中检测人脸。
-
对于每个检测到的脸,检测眼睛。
-
对于每个检测到的眼睛,检测眼睛是否睁开或关闭。
-
如果在某个时候检测到眼睛是睁开的,然后是闭着的,然后是睁开的,我们就断定此人已经眨了眼睛,并且程序显示他的名字(如果是人脸识别开门器,我们将授权此人进入)。
处理和编码已知人脸数据库
现在我们知道了每个想识别的人的编码,我们可以尝试通过网络摄像头识别人脸,然而,在转到这一部分之前,我们需要区分一张人脸照片和一张活人的脸。
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}
人脸活体检测
我们的目标是在某个点上检测出一个睁闭的睁眼模式。训练一个卷积神经网络来分类眼睛是闭着的还是睁着的,所选择的模型是LeNet-5,它已经在Closed Eyes In The Wild (CEW)数据集上进行了训练,它由大约4800张24x24大小的眼睛图像组成。
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import AveragePooling2D
from keras.layers import Flatten
from keras.layers import Dense
from keras.preprocessing.image import ImageDataGenerator
IMG_SIZE = 24
def 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
每次我们检测到一只眼睛,我们就用我们的模型来预测它的状态,并跟踪每个人的眼睛状态,因此,检测眨眼变得非常容易,它试图在眼睛状态历史中找到一个闭眼-睁眼-闭眼的过程。
def isBlinking(history, maxFrames):
""" @history: A string containing the history of eyes status
where a '1' means that the eyes were closed and '0' open.
@maxFrames: The maximal number of successive frames where an eye is closed """
for i in range(maxFrames):
pattern = '1' + '0'*(i+1) + '1'
if pattern in history:
return True
return False
实现效果图样例
我是海浪学长,创作不易,欢迎点赞、关注、收藏、留言。
毕设帮助,疑难解答,欢迎打扰!