人脸跟踪、识别、脸部标识

知识点:

  1. 人脸跟踪
  2. 人脸特征
  3. 要识别的人脸特征距离

看效果图,鼻子部分已经被标识出来了:

主要用到了dlib

import dlib

predictor_path = 'models\shape_predictor_68_face_landmarks.dat'
face_rec_model_path = 'models\dlib_face_recognition_resnet_model_v1.dat'
detector = dlib.get_frontal_face_detector()                       #人脸跟踪
predictor = dlib.shape_predictor(predictor_path)                  #人脸68个特征点检测器
facerec = dlib.face_recognition_model_v1(face_rec_model_path)     #映射人脸为128维特征值

由于目标里还希望把鼻子区域标识出来(方便后续自己贴图上去),因此:

from imutils import face_utils

(noseStart, noseEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"] 

#省略一部分代码,主要是省略了opencv调用摄像头逻辑代码

        success, img = cap.read()                                  #读取摄像头视频信息
        frame = imutils.resize(img, width=300)                     #resize,尺寸越小处理越快
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)             #变灰度图
        rects = detector(gray, 0)                                  #人脸区域跟踪
        rect = rects[0]                                            #假设只有1个区域存在人脸
        shape = predictor(gray, rect)                              #识别68个特征点
        shape = face_utils.shape_to_np(shape)                      #转换为numpy格式
        nose = shape[noseStart:noseEnd]                            #只拿鼻子区域的点
        noseHull = cv2.convexHull(nose)                            #把这些点转换为凸包
        cv2.drawContours(frame, [noseHull], -1, (0, 255, 0), 1)    #画出这些凸包外形
        cv2.putText(frame, "nose", (nose[0][0], nose[0][1]), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)         #文本标注

  

face_utils.FACIAL_LANDMARKS_IDXS,这个是对68个点的描述,有很多(有兴趣大家自己试试):
#For dlib’s 68-point facial landmark detector:
FACIAL_LANDMARKS_68_IDXS = OrderedDict([
	("mouth", (48, 68)),
	("inner_mouth", (60, 68)),
	("right_eyebrow", (17, 22)),
	("left_eyebrow", (22, 27)),
	("right_eye", (36, 42)),
	("left_eye", (42, 48)),
	("nose", (27, 36)),
	("jaw", (0, 17))
])

  

接下来就是识别人脸到底是谁了

def get_feature(path):
    img = imread(path)
    frame = img
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    dets = detector(gray, 0)
    shape = predictor(gray, dets[0])
    face_vector = facerec.compute_face_descriptor(img, shape)
    return face_vector

faces = [
           (get_feature('faces\dbh.jpg'), 'McKay')
        ]

  目前就1张,所以只load了1个到faces array里

       实际匹配代码如下:

def distance(a, b):
    a, b = np.array(a), np.array(b)
    sub = np.sum((a - b) ** 2)
    add = (np.sum(a ** 2) + np.sum(b ** 2)) / 2.
    r = sub / add
    return r

def process_face_id(faces, frame, rect, shape): found_face_id = 'Unknown' if len(faces) > 0: face_descriptor = facerec.compute_face_descriptor(frame, shape) min_face_id = found_face_id min_face_distance = 1 for face_feature, face_id in faces: cur_distance = distance(face_feature, face_descriptor) if cur_distance < min_face_distance: min_face_distance = cur_distance min_face_id = face_id if min_face_distance < threshold: found_face_id = min_face_id cv2.rectangle(frame, (rect.left(), rect.top() + 10), (rect.right(), rect.bottom()), (0, 255, 0), 2) cv2.putText(frame, found_face_id, (rect.left(), rect.top()), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2, cv2.LINE_AA) if found_face_id != 'Unknown': events.append(('user_found', found_face_id, time.time()))

  

需要pip install的有:

import dlib
import cv2
import numpy as np
import imutils
from imutils import face_utils
from imageio import imread


pip install cmake
pip install dlib
pip install opencv-python
pip install numpy
pip install imutils
pip install imageio 

  

完整代码

import dlib
import cv2
import numpy as np
import imutils
from imutils import face_utils
from imageio import imread
import time

predictor_path = 'models\shape_predictor_68_face_landmarks.dat'
face_rec_model_path = 'models\dlib_face_recognition_resnet_model_v1.dat'

predictor = dlib.shape_predictor(predictor_path)
detector = dlib.get_frontal_face_detector()
facerec = dlib.face_recognition_model_v1(face_rec_model_path)

(noseStart, noseEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"]

threshold = 0.12


def get_feature(path):
    img = imread(path)
    frame = img
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    dets = detector(gray, 0)
    # print('检测到了 %d 个人脸' % len(dets))
    # 这里假设每张图只有一个人脸
    shape = predictor(gray, dets[0])
    face_vector = facerec.compute_face_descriptor(img, shape)
    return face_vector


def distance(a, b):
    a, b = np.array(a), np.array(b)
    sub = np.sum((a - b) ** 2)
    add = (np.sum(a ** 2) + np.sum(b ** 2)) / 2.
    r = sub / add
    return r


faces = None
cap = None
success = None
events = []


def init():
    global faces
    global cap
    global success
    faces = [
                (get_feature('faces\dbh.jpg'), 'McKay')
            ]

    cap = cv2.VideoCapture(0)
    success, img = cap.read()

def start():
    global faces
    global cap
    global success
    while success:
        success, img = cap.read()
        frame = imutils.resize(img, width=300)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        rects = detector(gray, 0)
        for rect in rects:
            shape = predictor(gray, rect)

            process_face_id(faces, frame, rect, shape)

            shape = face_utils.shape_to_np(shape)
            nose = shape[noseStart:noseEnd]
            noseHull = cv2.convexHull(nose)
            cv2.drawContours(frame, [noseHull], -1, (0, 255, 0), 1)
            cv2.putText(frame, "nose", (nose[0][0], nose[0][1]), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

        cv2.imshow("Frame", frame)
        key = cv2.waitKey(1) & 0xFF

    cv2.destroyAllWindows()


def process_face_id(faces, frame, rect, shape):
    found_face_id = 'Unknown'
    if len(faces) > 0:
        face_descriptor = facerec.compute_face_descriptor(frame, shape)
        min_face_id = found_face_id
        min_face_distance = 1
        for face_feature, face_id in faces:
            cur_distance = distance(face_feature, face_descriptor)
            if cur_distance < min_face_distance:
                min_face_distance = cur_distance
                min_face_id = face_id

        if min_face_distance < threshold:
            found_face_id = min_face_id
    cv2.rectangle(frame, (rect.left(), rect.top() + 10), (rect.right(), rect.bottom()), (0, 255, 0), 2)
    cv2.putText(frame, found_face_id, (rect.left(), rect.top()), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2, cv2.LINE_AA)
    if found_face_id != 'Unknown':
        events.append(('user_found', found_face_id, time.time()))

  

原文地址:https://www.cnblogs.com/aarond/p/dlib.html