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

知识点:

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

 

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

 

 

 

主要用到了dlib

1
2
3
4
5
6
7
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维特征值

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)         #文本标注

  

1
face_utils.FACIAL_LANDMARKS_IDXS,这个是对68个点的描述,有很多(有兴趣大家自己试试):
1
2
3
4
5
6
7
8
9
10
11
#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))
])

  

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

1
2
3
4
5
6
7
8
9
10
11
12
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里

       实际匹配代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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的有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

  

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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()))

  

 

posted @   McKay  阅读(2134)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示