us-wjz

dlib

介绍与安装

官网:http://dlib.net/

官网对于dlib的介绍是:Dlib包含广泛的机器学习算法。所有的设计都是高度模块化的,快速执行,并且通过一个干净而现代的C ++ API,使用起来非常简单。它用于各种应用,包括机器人技术,嵌入式设备,手机和大型高性能计算环境。

看一下它官网的 Python examples 可以知道它大概可以干什么,下面是它官网的一些 Demo:

安装 dlib 库的时候需要用到 CMake 进行本地编译,而Cmake又是基于Visual Studio运行的,我在装这个库的时候,各种找不到教程,就想着分享一下自己的经验。

安装Dlib的必要条件是: 配置好boost和cmake

先安装Cmake和boost

输入pip  install  cmake ,回车,安装

输入pip  install  boost ,回车,安装

安装dlib

https://github.com/coneypo/Dlib_install/blob/master/dlib-19.7.0-cp36-cp36m-win_amd64.whl

pip  install  dlib

人脸检测

官网给的源代码:http://dlib.net/face_detector.py.html

This example program shows how to find frontal human faces in an image.  / 这个例子程序告诉我们如何找出图像中的正向人脸;

Iparticular, it shows how you can take a list of images from the command line / 从命令行读取一系列图像文件,

and display each on the screen with red boxes overlaid on each human face.  / 然后在每张人脸上面用红色框标识出来。

import sys
import dlib
from skimage import io

#使用dlib自带的frontal_face_detector()函数作为特征提取器
detector = dlib.get_frontal_face_detector() #加载dlib自带的人脸检测器

#使用dlib的图片窗口
win = dlib.image_window()

#sys.argv用来获取命令行参数,[0]表示代码本身文件路径,参数1开始向后依次是获取图片路径
for f in sys.argv[1:]:

    #输出目前处理的图片地址
    print("Processing file: {}".format(f))

    #使用skimage的io读取图片
    img = io.imread(f)
    print(type(img))
     #使用detector进行人脸检测,dets为人脸个数
    dets = detector(img, 1) #将检测器应用在输入图片上,结果返回给dets(参数1表示对图片进行上采样一次,有利于检测到更多的人脸);
    print("Number of faces detected: {}".format(len(dets)))
    print(dets)
    #dets的个数即为检测到的人脸的个数;遍历dets可以获取到检测到的每个人脸四个坐标极值。
    for i, d in enumerate(dets):
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
        i, d.left(), d.top(), d.right(), d.bottom()))

    #绘制图片
    win.clear_overlay()
    win.set_image(img) #先将图片显示到窗口上
    win.add_overlay(dets)  #利用window.add_overlay(dets)来绘制检测到的人脸框;
    dlib.hit_enter_to_continue() #用于等待点击(类似于opencv的cv2.waitKey(0),不加这个会出现闪退)。

# if (len(sys.argv[1:]) > 0):
#     img = io.imread(sys.argv[1])
#     dets, scores, idx = detector.run(img, 1, -1)
#     for i, d in enumerate(dets):
#         print("Detection {}, score: {}, face_type:{}".format(d, scores[i], idx[i]))

face_detector代码处理流程

 

 

 

视频人脸检测

import sys
import dlib
import cv2

cap = cv2.VideoCapture(\'WH-500x350.mp4\') #分辨率越小模型计算量就越小,模型预测就越快。

#(0)是调用笔记本内置摄像头,(1)是调用usb摄像头,如果是文件路径则读取文件。
# fourcc = cv2.VideoWriter_fourcc(*\'XVID\')
# out = cv2.VideoWriter(\'testwrite.avi\',fourcc, 20.0, (500,350),True)
detector = dlib.get_frontal_face_detector() #加载dlib自带的人脸检测器
cv2.namedWindow(\'frame\',0)
cv2.resizeWindow(\'frame\',800,600)

#设个步长来跳帧。
step = 2
#当前帧的位置
current_frame = -1

while cap.isOpened(): #判断cap是否开启
    ret,frame = cap.read()
    current_frame+=1
    if ret:
        if current_frame%step == 0:
            dets = detector(frame, 1)
            for d in dets:
                cv2.rectangle(frame,(d.left(), d.top()), (d.right(), d.bottom()),(0,0,255),thickness=3)
            cv2.imshow(\'frame\',frame) #显示图片

            # out.write(frame) #写入文件
            if cv2.waitKey(1) & 0xFF == ord(\'q\'):
                break
    else:
        break

# out.release()
cv2.destroyAllWindows() #关闭所有窗口

关键点(特征)的提取

实现关键点描述需要用到用于特征提取的官方模型,下载地址如下:

http://sourceforge.net/projects/dclib/files/dlib/v18.10/shape_predictor_68_face_landmarks.dat.bz2

https://blog.csdn.net/qq_29894613/article/details/89531013

官网给的源代码:http://dlib.net/face_landmark_detection.py.html

This example program shows how to find frontal human faces in an image and estimate their pose.  / 这个例子程序向我们展示如何图像中的正向人脸并且估计出他们的相貌;

The pose takes the form of 68 landmarks.  These are points on the face such as the corners of the mouth, along the eyebrows, on the eyes, and so forth. / 这些面部特征由 68 点特征构成,这些特征点向我们展示了人脸部的嘴部,眼部等等;

首先通过dlib.shape_predictor(predictor_path)从路径中加载模型,返回的predictor就是特征提取器。

对dets遍历,用predictor(img, d)计算检测到的每张人脸的关键点;

通过shape.parts()获取每个关键点坐标的x,y值,存入landmark矩阵(模型默认提取68个关键点,所以landmark为68×2矩阵)。

import sys
import os
import dlib
import glob
from skimage import io

detector = dlib.get_frontal_face_detector()

#使用预测器,此处为预测器的路径,预测器在下载的example文件夹里面,  *****修改此处****
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

#使用dlib的图片窗口
win = dlib.image_window()

#1.读取图片test2.jpg的路径,    ******修改此处*****
img = io.imread(r"D:\project\MyMusicPlay\images\T002R300x300M000000anHZA2CuwxK.jpg")

#2.或者还是利用cmd参数输入读取路径:
#img=io.imread(sys.argv[1])

win.clear_overlay()
win.set_image(img)

dets = detector(img, 1)
print("Number of faces detected: {}".format(len(dets)))

for k, d in enumerate(dets):
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
            k, d.left(), d.top(), d.right(), d.bottom()))
        # Get the landmarks/parts for the face in box d.
        shape = predictor(img, d)
        print(\'shape_size{}\'.format(shape))
        print("Part 0: {}, Part 1: {} ...".format(shape.part(0),
                                                  shape.part(1)),shape.part(3))
        # Draw the face landmarks on the screen.
        win.add_overlay(shape)
win.add_overlay(dets)
dlib.hit_enter_to_continue()

 

 

import sys
import dlib
from skimage import io
import cv2

# 加载并初始化检测器
# 模型下载地址http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(\'shape_predictor_68_face_landmarks.dat\')

camera = cv2.VideoCapture(0) #打开相机
if not camera.isOpened():
    print("cannot open camear")
    exit(0)

cv2.namedWindow(\'Camera\',0)
cv2.resizeWindow(\'Camera\',800,600)

while True:
    ret, frame = camera.read()

    if not ret:
        continue
    frame_new = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # 检测脸部
    dets = detector(frame_new, 1)
    # print("Number of faces detected: {}".format(len(dets)))
    # 查找脸部位置
    for i, face in enumerate(dets):
        # print("Detection {}: Left: {} Top: {} Right: {} Bottom: {} ".format(
        #     i, face.left(), face.top(), face.right(), face.bottom()))
        # 绘制脸部位置
        cv2.rectangle(frame, (face.left(), face.top()), (face.right(), face.bottom()), (0, 255, 0), 1) #画矩形
        shape = predictor(frame_new, face)
        # print(shape.part(0),shape.part(1))

        # 绘制特征点
        for i in range(68):
            cv2.circle(frame, (shape.part(i).x, shape.part(i).y), 3, (0, 0, 255), 2) #画园
            cv2.putText(frame, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 0, 0),
                        1) #写入文本
    cv2.imshow("Camera", frame)
    key = cv2.waitKey(1)
    if key == 27:
        break

cv2.destroyAllWindows()

参考文献:

https://www.cnblogs.com/AdaminXie/

https://blog.csdn.net/qiumokucao/article/details/81610628

案例

实现流程
从摄像头获取视频流,并转换为一帧一帧的图像,然后将图像信息传递给opencv这个工具库处理,返回灰度图像(就像你使用本地静态图片一样)

程序启动后,根据监听器信息,使用一个while循环,不断的加载视频图像,然后返回给opencv工具呈现图像信息。

创建一个键盘事件监听,按下"d"键,则开始执行面部匹配,并进行面具加载(这个过程是动态的,你可以随时移动)。

面部匹配使用Dlib中的人脸检测算法来查看是否有人脸存在。如果有,它将为每个人脸创建一个结束位置,眼镜和烟卷会移动到那里结束。

然后我们需要缩放和旋转我们的眼镜以适合每个人的脸。我们将使用从Dlib的68点模型返回的点集来找到眼睛和嘴巴的中心,并为它们之间的空间旋转。

在我们实时获取眼镜和烟卷的最终位置后,眼镜和烟卷从屏幕顶部进入,开始匹配你的眼镜和嘴巴。

假如没有人脸,程序会直接返回你的视频信息,不会有面具移动的效果。

默认一个周期是4秒钟。然后你可以通过"d"键再次检测。

程序退出使用"q"键。

from time import sleep

import cv2
import numpy as np
from PIL import Image
from imutils import face_utils, resize

try:
    from dlib import get_frontal_face_detector, shape_predictor
except ImportError:
    raise

\'\'\'创建面具加载服务类DynamicStreamMaskService及其对应的初始化属性:\'\'\'


class DynamicStreamMaskService(object):
    """
    动态黏贴面具服务
    """

    def __init__(self, saved=False):
        self.saved = saved  # 是否保存图片
        self.listener = True  # 启动参数
        self.video_capture = cv2.VideoCapture(0)  # 调用本地摄像头
        self.doing = False  # 是否进行面部面具
        self.speed = 0.1  # 面具移动速度
        self.detector = get_frontal_face_detector()  # 面部识别器
        self.predictor = shape_predictor("shape_predictor_68_face_landmarks.dat")  # 面部分析器
        self.fps = 4  # 面具存在时间基础时间
        self.animation_time = 0  # 动画周期初始值
        self.duration = self.fps * 4  # 动画周期最大值
        self.fixed_time = 4  # 画图之后,停留时间
        self.max_width = 500  # 图像大小
        self.deal, self.text, self.cigarette = None, None, None  # 面具对象


    \'\'\'按照上面介绍,我们先实现读取视频流转换图片的函数:\'\'\'

    def read_data(self):
        """
        从摄像头获取视频流,并转换为一帧一帧的图像
        :return: 返回一帧一帧的图像信息
        """
        _, data = self.video_capture.read()
        return data


    \'\'\'接下来我们实现人脸定位函数,及眼镜和烟卷的定位:\'\'\'


    def get_glasses_info(self, face_shape, face_width):
        """
        获取当前面部的眼镜信息
        :param face_shape:
        :param face_width:
        :return:
        """
        left_eye = face_shape[36:42]
        right_eye = face_shape[42:48]

        left_eye_center = left_eye.mean(axis=0).astype("int")
        right_eye_center = right_eye.mean(axis=0).astype("int")

        y = left_eye_center[1] - right_eye_center[1]
        x = left_eye_center[0] - right_eye_center[0]
        eye_angle = np.rad2deg(np.arctan2(y, x))

        deal = self.deal.resize(
            (face_width, int(face_width * self.deal.size[1] / self.deal.size[0])),
            resample=Image.LANCZOS)

        deal = deal.rotate(eye_angle, expand=True)
        deal = deal.transpose(Image.FLIP_TOP_BOTTOM)

        left_eye_x = left_eye[0, 0] - face_width // 4
        left_eye_y = left_eye[0, 1] - face_width // 6

        return {"image": deal, "pos": (left_eye_x, left_eye_y)}


    def get_cigarette_info(self, face_shape, face_width):
        """
        获取当前面部的烟卷信息
        :param face_shape:
        :param face_width:
        :return:
        """
        mouth = face_shape[49:68]
        mouth_center = mouth.mean(axis=0).astype("int")
        cigarette = self.cigarette.resize(
            (face_width, int(face_width * self.cigarette.size[1] / self.cigarette.size[0])),
            resample=Image.LANCZOS)
        x = mouth[0, 0] - face_width + int(16 * face_width / self.cigarette.size[0])
        y = mouth_center[1]
        return {"image": cigarette, "pos": (x, y)}


    def orientation(self, rects, img_gray):
        """
        人脸定位
        :return:
        """
        faces = []
        for rect in rects:
            face = {}
            face_shades_width = rect.right() - rect.left()
            predictor_shape = self.predictor(img_gray, rect)
            face_shape = face_utils.shape_to_np(predictor_shape)
            face[\'cigarette\'] = self.get_cigarette_info(face_shape, face_shades_width)
            face[\'glasses\'] = self.get_glasses_info(face_shape, face_shades_width)

            faces.append(face)

        return faces


    \'\'\'刚才我们提到了键盘监听事件,这里我们实现一下这个函数:\'\'\'

    def listener_keys(self):
        """
        设置键盘监听事件
        :return:
        """
        key = cv2.waitKey(1) & 0xFF
        if key == ord("q"):
            self.listener = False
            self.console("程序退出")
            sleep(1)
            self.exit()

        if key == ord("d"):
            self.doing = not self.doing


    \'\'\'接下来我们来实现加载面具信息的函数:\'\'\'

    def init_mask(self):
        """
        加载面具
        :return:
        """
        self.console("加载面具...")
        self.deal, self.text, self.cigarette = (
            Image.open(x) for x in ["images/deals.png", "images/text.png", "images/cigarette.png"]
        )


    \'\'\'
    上面基本的功能都实现了,我们该实现画图函数了,这个函数原理和之前我写的那篇用AI人脸识别技术实现抖音特效实现是一样的,
    这里我就不赘述了,可以去github或Python中文社区微信公众号查看。
    \'\'\'

    def drawing(self, draw_img, faces):
        """
        画图
        :param draw_img:
        :param faces:
        :return:
        """
        for face in faces:
            if self.animation_time < self.duration - self.fixed_time:
                current_x = int(face["glasses"]["pos"][0])
                current_y = int(face["glasses"]["pos"][1] * self.animation_time / (self.duration - self.fixed_time))
                draw_img.paste(face["glasses"]["image"], (current_x, current_y), face["glasses"]["image"])

                cigarette_x = int(face["cigarette"]["pos"][0])
                cigarette_y = int(face["cigarette"]["pos"][1] * self.animation_time / (self.duration - self.fixed_time))
                draw_img.paste(face["cigarette"]["image"], (cigarette_x, cigarette_y),
                               face["cigarette"]["image"])
            else:
                draw_img.paste(face["glasses"]["image"], face["glasses"]["pos"], face["glasses"]["image"])
                draw_img.paste(face["cigarette"]["image"], face["cigarette"]["pos"], face["cigarette"]["image"])
                draw_img.paste(self.text, (75, draw_img.height // 2 + 128), self.text)

    \'\'\'
    既然是一个服务类,那该有启动与退出函数吧,最后我们来写一下吧。
    
    简单介绍一下这个start()
    函数, 启动后根据初始化监听信息,不断监听视频流,并将流信息通过opencv转换成图像展示出来。
    并且调用按键监听函数,不断的监听你是否按下
    "d"
    键进行面具加载,如果监听成功,则进行图像人脸检测,并移动面具,
    并持续一个周期的时间结束,面具此时会根据你的面部移动而移动。最终呈现文章顶部图片的效果.
    \'\'\'
    def start(self):
        """
        启动程序
        :return:
        """
        self.console("程序启动成功.")
        self.init_mask()
        while self.listener:
            frame = self.read_data()
            frame = resize(frame, width=self.max_width)
            img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            rects = self.detector(img_gray, 0)
            faces = self.orientation(rects, img_gray)
            draw_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            if self.doing:
                self.drawing(draw_img, faces)
                self.animation_time += self.speed
                self.save_data(draw_img)
                if self.animation_time > self.duration:
                    self.doing = False
                    self.animation_time = 0
                else:
                    frame = cv2.cvtColor(np.asarray(draw_img), cv2.COLOR_RGB2BGR)
            cv2.imshow("hello mask", frame)
            self.listener_keys()


    def exit(self):
        """
        程序退出
        :return:
        """
        self.video_capture.release()
        cv2.destroyAllWindows()


if __name__ == \'__main__\':
    ms = DynamicStreamMaskService()
    ms.start()
View Code

face_recognition

项目源:https://github.com/ageitgey/face_recognition

安装

pip install face_recognition

参考文献:

https://www.jianshu.com/p/0b37452be63e

https://www.jianshu.com/p/107803778086

https://www.jb51.net/article/160623.htm

安装问题总结

首先,如果你是第一次使用Face_recogintion,前提是必须要知道以下依赖关系:

Win下python3.6版本:

  1. 安装Dlib的必要条件是: 配置好boost和cmake
  2. 安装face_recongnition的必要条件是:配置好Dlib和openCV

注意:请务必从最底层的依赖项目开始进行安装

  • 在没有安装好第1步之前,不要安装dlib
  • 在没有安装好dlib之前,不要进行安装face_recongnition。

个人开发环境

python-3.6.5

cmake-3.14.4

dlib-19.7

其他方式安装参考:

https://www.cnblogs.com/wdzn/p/9675821.html

https://blog.csdn.net/zhang475546259/article/details/84104368

https://blog.csdn.net/qq_36387683/article/details/83656100

 

分类:

技术点:

相关文章: