12 | Dlib快速入门

简介

Dlib由C++编写,提供了和机器学习、数值计算、图模型算法、图像处理等领域相关的一系列功能

安装

安装Dlib之前需要先安装cmake,这里以源码方式安装,去官网根据系统下载相应的源码,cmake.org/download/

解压之后,在终端里进入源码目录,依次运行以下命令

./bootstrap
make
sudo make install

sudo是以root权限运行命令,适用于Linux和Mac OS

如果是Windows,则以管理员身份打开cmd,并且最后一行命令改为

make install

接下来,在终端中运行以下命令,检查cmake是否成功安装

cmake --version

如果出现了相应的版本信息,则说明cmake安装成功

之后便可以使用pip安装Dlib

pip install dlib

安装之后进入Python,如果能正常import,则说明Dlib安装成功

import dlib

如果是Mac OS,还需要安装XQuartz用于显示图像

安装XQuartz之后如果碰到类似以下问题

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

那么在命令行运行以下命令即可解决

xcode-select --install

完成以上安装工作之后,我们来体验下Dlib提供的一些和图片处理相关的例子

人脸检测

加载库

# -*- coding: utf-8 -*-

import dlib
from imageio import imread
import glob

准备好人脸检测器和显示窗口,获取图片路径

detector = dlib.get_frontal_face_detector()
win = dlib.image_window()
paths = glob.glob('faces/*.jpg')

对每一张图片进行检测,并显示检测结果对应的矩形框

for path in paths:
    img = imread(path)
    # 1 表示将图片放大一倍,便于检测到更多人脸
    dets = detector(img, 1)
    print('检测到了 %d 个人脸' % len(dets))
    for i, d in enumerate(dets):
        print('- %d:Left %d Top %d Right %d Bottom %d' % (i, d.left(), d.top(), d.right(), d.bottom()))

    win.clear_overlay()
    win.set_image(img)
    win.add_overlay(dets)
    dlib.hit_enter_to_continue()

检测时也可以指定一个阈值

path = 'faces/2007_007763.jpg'
img = imread(path)
# -1 表示人脸检测的判定阈值
# scores 为每个检测结果的得分,idx 为人脸检测器的类型
dets, scores, idx = detector.run(img, 1, -1)
for i, d in enumerate(dets):
    print('%d:score %f, face_type %f' % (i, scores[i], idx[i]))
win.clear_overlay()
win.set_image(img)
win.add_overlay(dets)
dlib.hit_enter_to_continue()

人脸关键点检测

使用训练好的模型shape_predictor_68_face_landmarks.dat,在检测出人脸的同时,检测出人脸上的68个关键点

加载库

# -*- coding: utf-8 -*-

import dlib
from imageio import imread
import glob

准备好人脸检测器、关键点检测模型、显示窗口、图片路径

detector = dlib.get_frontal_face_detector()
predictor_path = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(predictor_path)
win = dlib.image_window()
paths = glob.glob('faces/*.jpg')

检测每一张图片

for path in paths:
    img = imread(path)
    win.clear_overlay()
    win.set_image(img)

    # 1 表示将图片放大一倍,便于检测到更多人脸
    dets = detector(img, 1)
    print('检测到了 %d 个人脸' % len(dets))
    for i, d in enumerate(dets):
        print('- %d: Left %d Top %d Right %d Bottom %d' % (i, d.left(), d.top(), d.right(), d.bottom()))
        shape = predictor(img, d)
        # 第 0 个点和第 1 个点的坐标
        print('Part 0: {}, Part 1: {}'.format(shape.part(0), shape.part(1)))
        win.add_overlay(shape)

    win.add_overlay(dets)
    dlib.hit_enter_to_continue()

人脸识别

不光是检测人脸,还要知道每张脸是谁

Dlib将每张人脸映射为一个128维的向量,当两个向量之间的Euclidean距离小于0.6时,可以认为属于同一个人

以上判定标准在LFW(Labeled Faces in the Wild,08课提到过)数据集上可以获得99.38%的识别准确率

这里需要用到两个模型,shape_predictor_68_face_landmarks.datdlib_face_recognition_resnet_model_v1.dat,根据人脸检测结果得到关键点检测结果,根据关键点检测结果进一步得到128维向量表示

加载库

# -*- 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):
    # d = 0
    # for i in range(len(a)):
    #     d += (a[i] - b[i]) * (a[i] - b[i])
    # return np.sqrt(d)
    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

将未标注图片的向量表示,和标注图片逐一匹配

# 读取未标注图片,并和标注图片进行对比
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)
    print('{}:{}'.format(name, ';'.join(matches)))

结果显示,全部标注图片都通过了匹配,说明白百合和王珞丹是真的像……

人脸聚类

对于大量图片中的大量人脸,基于以上人脸识别标准进行聚类,把距离较近的人脸聚为一类,即有可能为同一个人

加载库

# -*- coding: utf-8 -*-

import dlib
from imageio import imread
import glob
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('faces/*.jpg')

获取所有图片的关键点检测结果和向量表示

vectors = []
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)
        vectors.append(face_vector)
        images.append((img, shape))

以0.5为阈值进行聚类,并找出人脸数量最多的类

labels = dlib.chinese_whispers_clustering(vectors, 0.5)
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

物体追踪

物体追踪是指,对于视频文件,在第一帧指定一个矩形区域,对于后续帧自动追踪和更新区域的位置

加载库

# -*- coding: utf-8 -*-

import dlib
from imageio import imread
import glob

准备好追踪器和图片

tracker = dlib.correlation_tracker()
win = dlib.image_window()
paths = sorted(glob.glob('video_frames/*.jpg'))

追踪图片中的物体

for i, path in enumerate(paths):
    img = imread(path)
    # 第一帧,指定一个区域
    if i == 0:
        tracker.start_track(img, dlib.rectangle(74, 67, 112, 153))
    # 后续帧,自动追踪
    else:
        tracker.update(img)

    win.clear_overlay()
    win.set_image(img)
    win.add_overlay(tracker.get_position())
    dlib.hit_enter_to_continue()

尽管物体的位置在不断变化,Dlib始终能够比较准确地进行追踪

参考

Dlib官网:dlib.net/

Dlib Github:github.com/davisking/d…

results matching ""

    No results matching ""