【深度有趣 14】 Dlib快速上手-续

人脸比对

其实就是将两张人脸的特征之间的相对位置进行计算,然后根据欧几里得距离来判断是不是同一个人。

# -*- 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

 

你可能感兴趣的:(深度有趣)