其实就是将两张人脸的特征之间的相对位置进行计算,然后根据欧几里得距离来判断是不是同一个人。
# -*- coding: utf-8 -*-
import dlib
from imageio import imread
import glob
import numpy as np
detector = dlib.get_frontal_face_detector()
predictor_path = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(predictor_path)
face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat' # 人脸比对的模型
facerec = dlib.face_recognition_model_v1(face_rec_model_path)
labeled = glob.glob('labeled/*.jpg')
labeled_data = {}
unlabeled = glob.glob('unlabeled/*.jpg')
# 定义一个计算Euclidean距离的函数
def distance(a, b):
return np.linalg.norm(np.array(a) - np.array(b), ord=2)
# 读取标注图片并保存对应的128向量
for path in labeled:
img = imread(path)
name = path.split('\\')[1].rstrip('.jpg')
dets = detector(img, 1)
# 这里假设每张图只有一个人脸
shape = predictor(img, dets[0])
face_vector = facerec.compute_face_descriptor(img, shape)
labeled_data[name] = face_vector
# 读取未标注图片,并和标注图片进行对比
print('未标注的图片的匹配结果:')
for path in unlabeled:
img = imread(path)
name = path.split('\\')[1].rstrip('.jpg')
dets = detector(img, 1)
# 这里假设每张图只有一个人脸
shape = predictor(img, dets[0])
face_vector = facerec.compute_face_descriptor(img, shape)
matches = []
for key, value in labeled_data.items():
d = distance(face_vector, value)
#if d < 0.6:
# matches.append(key + ':%.2f' % d)
matches.append(key + ':%.2f' % d)
print('{}:\n{}'.format(name, '; '.join(matches)))
labeled目录下存放的是白百何和王珞丹的各4张图片作为标记图片
unlabeled目录下存放的是几张验证的图片
运行效果
未标注的图片的匹配结果:
1(白百合):
王珞丹1:0.46; 王珞丹2:0.41; 王珞丹3:0.43; 王珞丹4:0.48; 白百合1:0.40; 白百合2:0.39; 白百合3:0.38; 白百合4:0.43
1高圆圆:
王珞丹1:0.49; 王珞丹2:0.48; 王珞丹3:0.54; 王珞丹4:0.61; 白百合1:0.45; 白百合2:0.53; 白百合3:0.53; 白百合4:0.55
2(白百合):
王珞丹1:0.36; 王珞丹2:0.41; 王珞丹3:0.39; 王珞丹4:0.47; 白百合1:0.35; 白百合2:0.41; 白百合3:0.41; 白百合4:0.46
2高圆圆:
王珞丹1:0.52; 王珞丹2:0.54; 王珞丹3:0.52; 王珞丹4:0.60; 白百合1:0.53; 白百合2:0.55; 白百合3:0.55; 白百合4:0.51
3(王珞丹):
王珞丹1:0.41; 王珞丹2:0.43; 王珞丹3:0.41; 王珞丹4:0.45; 白百合1:0.53; 白百合2:0.51; 白百合3:0.50; 白百合4:0.51
4(王珞丹):
王珞丹1:0.41; 王珞丹2:0.44; 王珞丹3:0.37; 王珞丹4:0.44; 白百合1:0.52; 白百合2:0.47; 白百合3:0.43; 白百合4:0.44
7高圆圆:
王珞丹1:0.53; 王珞丹2:0.53; 王珞丹3:0.48; 王珞丹4:0.56; 白百合1:0.54; 白百合2:0.49; 白百合3:0.57; 白百合4:0.51
mei:
王珞丹1:0.75; 王珞丹2:0.75; 王珞丹3:0.68; 王珞丹4:0.74; 白百合1:0.67; 白百合2:0.65; 白百合3:0.66; 白百合4:0.64
分数越低,说明两者越相似。可以看出,白百合,王珞丹确实很相似。
还需要注意一点:如果原作者的程序报错
name = path.split('/')[1].rstrip('.jpg')
IndexError: list index out of range
试试将‘ name = path.split('/')[1].rstrip('.jpg')’改成‘ name = path.split('\\')[1].rstrip('.jpg')’
对于大量的图片中人脸,基于以上人脸识别就行聚类,将距离较近的人脸聚为一类,即有可能是同一个人。
下面是代码实现,具体的看注释
#-*-coding UTF-GBK -*-
import glob
from imageio import imread
import dlib
import os
from collections import Counter
# 模型
detector = dlib.get_frontal_face_detector()
predictor_path = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(predictor_path)
face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat'
facerec = dlib.face_recognition_model_v1(face_rec_model_path)
paths = glob.glob('yuanyuan/*.jpg')
# 获取所有的人脸 及 向量表示
vector=[]
images=[]
for path in paths:
img = imread(path)
dets = detector(img,1)
for i, d in enumerate(dets):
shape = predictor(img,d)
face_vector = facerec.compute_face_descriptor(img,shape)
vector.append(face_vector)
images.append((img,shape))
# 以0.5为阈值,进行聚类
labels = dlib.chinese_whispers_clustering(vector,0.4)
num_classes = len(set(labels))
print('共聚为 %d 类'%num_classes)
biggest_class = Counter(labels).most_common(1)
print(biggest_class)
#
output_dir = 'most_common'
if not os.path.exists(output_dir):
os.mkdir(output_dir)
face_id = 1
for i in range(len(images)):
if labels[i] == biggest_class[0][0]:
img,shape = images[i]
dlib.save_face_chip(img,shape,output_dir + '/face_%d' % face_id,size=150,padding=0.25)
face_id+=1
在yuanyuan文件夹内,我搜集了一些高圆圆的照片,下面的检测结果
有几个误检,降低阈值,可以有所改善。
物体追踪是指,对于视频文件,在第一帧指定一个矩形区域,对于后续帧自动追踪和更新区域的位置。
看下面的代码
#-*- coding: utf-8 -*-
import dlib
import glob
from imageio import imread
import time
# 图片
tractor = dlib.correlation_tracker()
win = dlib.image_window()
paths = sorted(glob.glob('frames/*.png'))
#追踪
for i ,path in enumerate(paths):
img = imread(path)
# 对第一帧进行标注
if i ==0:
tractor.start_track(img,dlib.rectangle(195,110,465,200))
else:
tractor.update(img)
win.clear_overlay()
win.set_image(img)
win.add_overlay(tractor.get_position())
time.sleep(0.2)
用刚刚裁剪的一段视频做了一下实验,效果还不错。
事关导师项目,就不贴出来了。
Dlib很强,感谢大牛:https://zhuanlan.zhihu.com/p/44169338