人脸跟踪、识别、脸部标识
知识点:
- 人脸跟踪
- 人脸特征
- 要识别的人脸特征距离
看效果图,鼻子部分已经被标识出来了:
主要用到了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())) |
自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 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】