Dlib由C++編寫,提供了和機器學習、數值計算、圖模型算法、圖像處理等領域相關的一系列功能git
安裝Dlib以前須要先安裝cmake
,這裏以源碼方式安裝,去官網根據系統下載相應的源碼,cmake.org/download/github
解壓以後,在終端裏進入源碼目錄,依次運行如下命令算法
./bootstrap
make
sudo make install
複製代碼
sudo
是以root權限運行命令,適用於Linux和Mac OSbootstrap
若是是Windows,則以管理員身份打開cmd,而且最後一行命令改成xcode
make install
複製代碼
接下來,在終端中運行如下命令,檢查cmake是否成功安裝bash
cmake --version
複製代碼
若是出現了相應的版本信息,則說明cmake安裝成功app
以後即可以使用pip安裝Dlib機器學習
pip install dlib
複製代碼
安裝以後進入Python,若是能正常import,則說明Dlib安裝成功ide
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.dat
和dlib_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始終可以比較準確地進行追蹤