Dlib库教程(2)联合python的人脸检测标记识别
1 说明
=====
1.1 准备篇《Dlib库教程(1):介绍、linux下的安装与避坑》。
1.2 本次讲解Dlib库的强大的联合python的人脸检测、标记和识别功能。
1.3 熟悉Dlib库的python的API功能函数。
1.4 熟悉python编程相关知识,讲解思路清晰,注释仔细,干货满满,由浅入深,一秒入门。
1.5 图片来自今日头条正版免费图库,表示对女神的喜爱,致敬,仅供学习。
1.6 环境:python3.8+dlib19.21.99+opencv4.4.0+deepin-linux操作系统。
1.jpeg
2.jpeg
2 dlib+opencv+python的人脸检测、识别和标示
====================================
2.1 代码:#人脸检测,画框和画68点特征显示 #第1步:导入模块 import dlib import cv2 #第2步:模型加载 #这是人脸68点特征检测器模型,提前官网下载好 shape_predictor_path = "/home/xgj/Desktop/dlib/shape_predictor_68_face_landmarks.dat" #获取人脸分类器 detector = dlib.get_frontal_face_detector() #获取人脸 68 点特征检测器,进行人脸面部轮廓特征提取: predictor = dlib.shape_predictor(shape_predictor_path) #第3步:被检测图片 #载入被检测图片路径 imgpath ="/home/xgj/Desktop/dlib/pic/2.jpeg" #读图片,cv.imread()共两个参数,第二个为如何读取图片, #包括cv2.IMREAD_COLOR: 读入一个彩色图片 #img = cv2.imread(imgpath, cv2.IMREAD_COLOR) img = cv2.imread(imgpath) #默认,等同于上面读取彩色图片 #这个是cv2特有的图片读取,需要转换,否则不是原图 b, g, r = cv2.split(img) img2 = cv2.merge([r, g, b]) #侦测人脸 dets = detector(img2, 1) #第4步: for index, face in enumerate(dets): left = face.left() top = face.top() right = face.right() bottom = face.bottom() #在人脸上标示绿色方框 cv2.rectangle(img,(left, top),(right, bottom),(0, 255, 0), 1) shape = predictor(img, face) for index, pt in enumerate(shape.parts()): pt_pos = (pt.x, pt.y) #标示人脸68个特征圆点 cv2.circle(img, pt_pos, 1, (255, 0, 0), 1) #第5步: #展示已经人脸识别后的带有标示图片 cv2.imshow("pic",img) cv2.namedWindow("pic",cv2.WINDOW_AUTOSIZE) #窗口关闭设置 k = cv2.waitKey(0) cv2.destroyAllWindows()
2.2 图
3 dlib+cv2+numpy法人脸检测和识别
===========================
3.1 代码# encoding:utf-8 #代码来源 #https://blog.csdn.net/liuxiao214/article/details/83411820?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param #人脸检测,画框 import dlib import numpy as np import cv2 # 获得人脸矩形的坐标信息函数 def rect_to_bb(rect): x = rect.left() y = rect.top() w = rect.right() - x h = rect.bottom() - y return (x, y, w, h) # 图片大小调整函数 def resize(image, width=1200): # 将待检测的image进行resize r = width * 1.0 / image.shape[1] dim = (width, int(image.shape[0] * r)) resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) return resized # 人脸检测函数 def detect(): #加载待检测的图片 image_file = "/home/xgj/Desktop/dlib/pic/1.jpeg" image = cv2.imread(image_file) #调整大小 image = resize(image, width=1200) #灰度转换 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #dlib人脸检测器和人脸检测画框 detector = dlib.get_frontal_face_detector() #dlib人脸检测矩形框4点坐标和对图像画人脸框 rects = detector(gray, 1) #画框和输出文字 for (i, rect) in enumerate(rects): (x, y, w, h) = rect_to_bb(rect) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(image, "Face:{}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) #图片展示 cv2.imshow("Output", image) cv2.waitKey(0) if __name__ == "__main__": detect()
3.2 图
3.3 增加功能,标注68人脸特征点
=========================
3.3.1 代码# encoding:utf-8 import dlib import numpy as np import cv2 # 获得人脸矩形的坐标信息 def rect_to_bb(rect): x = rect.left() y = rect.top() w = rect.right() - x h = rect.bottom() - y return (x, y, w, h) # 将包含68个特征的的shape转换为numpy array格式 def shape_to_np(shape, dtype="int"): coords = np.zeros((68, 2), dtype=dtype) for i in range(0, 68): coords[i] = (shape.part(i).x, shape.part(i).y) return coords # 将待检测的image进行resize def resize(image, width=1200): r = width * 1.0 / image.shape[1] dim = (width, int(image.shape[0] * r)) resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) return resized #人脸检测、识别、标注68特征点 def feature(): #加载被检测图片 image_file = "/home/xgj/Desktop/dlib/pic/2.jpeg" image = cv2.imread(image_file) image = resize(image, width=1200) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #加载dlib功能函数 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("/home/xgj/Desktop/dlib/shape_predictor_68_face_landmarks.dat") rects = detector(gray, 1) shapes = [] #人脸检测、识别和画框 for (i, rect) in enumerate(rects): shape = predictor(gray, rect) #获取特征点 shape = shape_to_np(shape) #存入列表中 shapes.append(shape) (x, y, w, h) = rect_to_bb(rect) cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) #获取68关键点并画圈标注 for shape in shapes: for (x, y) in shape: cv2.circle(image, (x, y), 2, (0, 0, 255), -1) cv2.imshow("Output", image) cv2.waitKey(0) if __name__ == "__main__": feature()
3.3.2 图
4 高级一点:视频实时检测人脸和标注
=============================
4.1 代码:# coding=utf-8 #参考文章 #https://blog.csdn.net/m0_37477175/article/details/78151320?locationNum=2&fps=1&utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242 #摄像头实时,人脸检测和画框和画弧,默认红色框和蓝色人脸特征线 import cv2 import dlib # dlib模型加载 predictor_path = "/home/xgj/Desktop/dlib/shape_predictor_68_face_landmarks.dat" # 初始化landmark predictor = dlib.shape_predictor(predictor_path) # 初始化dlib人脸检测器 detector = dlib.get_frontal_face_detector() # 初始化dlib自带显示窗口 win = dlib.image_window() # opencv加载视频文件 #cap = cv2.VideoCapture("/home/xxx.mp4") #摄像头读取 cap = cv2.VideoCapture(0) if cap.isOpened(): print("Unable to connect to camera !") #循环 while cap.isOpened(): ret, cv_img = cap.read() if cv_img is None: break # RGB TO BGR img = cv2.cvtColor(cv_img, cv2.COLOR_RGB2BGR) #侦测和检测人脸 dets = detector(img, 0) shapes = [] for i, d in enumerate(dets): shape = predictor(img, d) shapes.append(shape) win.clear_overlay() win.set_image(img) if len(shapes)!= 0 : for i in range(len(shapes)): win.add_overlay(shapes[i]) win.add_overlay(dets) cap.release()
4.2 再高级一点的代码# 调用摄像头,进行人脸捕获,和 68 个特征点的追踪 # 参考原作者,感谢原作者 # Author: coneypo # Blog: http://www.cnblogs.com/AdaminXie # GitHub: https://github.com/coneypo/Dlib_face_detection_from_camera #第1步:导入模块 import dlib import numpy as np import cv2 #时间模块用于截图保存后生成的文件名 import time import timeit #第2步:初始化 # 储存截图的目录 path_screenshots = "/home/xgj/Desktop/dlib/data/screenshots/" # dlib模块加载 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor("/home/xgj/Desktop/dlib/shape_predictor_68_face_landmarks.dat") # 创建 cv2 摄像头对象 cap = cv2.VideoCapture(0) # cap.set(propId, value) # 设置视频参数,propId 设置的视频参数,value 设置的参数值 cap.set(3, 480) # 截图 screenshots 的计数器 cnt = 0 #时间列表 time_cost_list = [] #第3步: # cap.isOpened() 返回 true/false 检查初始化是否成功 while cap.isOpened(): # cap.read() # 返回两个值: # 一个布尔值 true/false,用来判断读取视频是否成功/是否到视频末尾 # 图像对象,图像的三维矩阵 flag, im_rd = cap.read() # 每帧数据延时 1ms,延时为 0 读取的是静态帧 k = cv2.waitKey(1) # 取灰度 img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY) # start point start = timeit.default_timer() # 人脸数 faces = detector(img_gray, 0) # 待会要写的字体 font = cv2.FONT_HERSHEY_SIMPLEX # 标 68 个点 if len(faces) != 0: # 检测到人脸 for i in range(len(faces)): landmarks = np.matrix([[p.x, p.y] for p in predictor(im_rd, faces[i]).parts()]) for idx, point in enumerate(landmarks): # 68 点的坐标 pos = (point[0, 0], point[0, 1]) # 利用 cv2.circle 给每个特征点画一个圈,共 68 个 cv2.circle(im_rd, pos, 2, color=(139, 0, 0)) # 利用 cv2.putText 输出 1-68 cv2.putText(im_rd, str(idx + 1), pos, font, 0.2, (187, 255, 255), 1, cv2.LINE_AA) cv2.putText(im_rd, "faces: " + str(len(faces)), (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA) # end point stop = timeit.default_timer() time_cost_list.append(stop - start) else: # 没有检测到人脸 cv2.putText(im_rd, "no face", (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA) # 添加说明 im_rd = cv2.putText(im_rd, "press "S": screenshot", (20, 400), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) im_rd = cv2.putText(im_rd, "press "Q": quit", (20, 450), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA) # 按下 "s" 键保存 if k == ord("s"): cnt += 1 cv2.imwrite(path_screenshots + "screenshot" + "_" + str(cnt) + "_" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".jpg", im_rd) # 按下 "q" 键退出 if k == ord("q"): break # 窗口显示 # 参数取 0 可以拖动缩放窗口,为 1 不可以 cv2.namedWindow("camera", 0) #cv2.namedWindow("camera", 1) cv2.imshow("camera", im_rd) # 释放摄像头 cap.release() # 删除建立的窗口 cv2.destroyAllWindows()
5 备注:附注学习和复习opencv的色彩转换问题
====================================
5.1 代码# -*- coding: utf-8 -*- #熟悉opencv色彩转换问题 #代码所在终端打开输入 #python3.8 11.py /home/xgj/Desktop/dlib/pic/1.jpeg import sys import cv2 import dlib #采用skimage读取图片代码简单些,img全部为img #from skimage import io #add1 detector = dlib.get_frontal_face_detector() win = dlib.image_window() for f in sys.argv[1:]: #img = io.imread(f) #add2 img = cv2.imread(f) #opencv的增加色彩转换,增加2行 b, g, r = cv2.split(img) img1 = cv2.merge([r, g, b]) dets = detector(img1,1) #使用detector进行人脸检测 for i, d in enumerate(dets): x = d.left() y = d.top() w = d.right() h = d.bottom() cv2.rectangle(img1, (x, y), (w, h), (0, 255, 0)) print("({},{},{},{})".format( x, y, (w-x), (h-y))) win.set_image(img1) #io.imsave("/home/xgj/Desktop/dlib/P_Dlib_test.jpg",img) #增加2行色彩转换 r, g, b = cv2.split(img1) img2 = cv2.merge([b, g, r]) cv2.imwrite("/home/xgj/Desktop/dlib/P_Dlib_test.jpg",img2) #等待点击 dlib.hit_enter_to_continue()
5.2 操作效果图
下一次讲,dlib的目标检测和实时视频的行人计数。