[Day11] Face Detection - 使用OpenCV & Dlib:Dlib HOG + Linear SVM

不要被标题一堆名词吓到;当你用过它後,你会惊讶它的易用以及,最重要的,无缝接轨辨识人脸关键点

本文开始

Dlib套件,一个你可能觉得陌生,但在听到Facial Landmark或是Face Alignment时,却几乎一定会用到的强大套件。

以我自己在进行Computer Vision相关功能或专案时,下面几个套件一定是先装好装满:

  • OpenCV
  • Dlib
  • imutils (图片处理常用工具)

再来才会看要做哪一种影像分析,或是训练模型... (训练模型的图片预处理有其他方便的工具,如kerasscikit-learn等)

当你了解如何使用基本工具 (OpenCV & Dlib)来进行人脸分析後,FaceNet、VGGFace、DeepFace等等这些人脸识别模型的使用才会更得心应手。


前面提到过,使用OpenCV & Dlib来做人脸侦测,大概可以分为四种方式:

  1. OpenCV Haar cascades
  2. OpenCV deep neural networks (DNNs)
  3. Dlib HOG + Linear SVM <-- 今天说这个
  4. Dlib max-margin object detector (MMOD)

今天要介绍第三种方式。

Dlib HOG + Linear SVM

习惯上我喜欢称呼这个方法叫Dlib特徵检测,其实从名称其实可以看出一二,

Dlib HOG + Linear SVM与OpenCV Haar cascades其实都是透过检测(滑动视窗)的特徵来辨识物体与位置

今天介绍的方法其背後原理大概可以分成两步骤:

  1. 提取特徵:透过方向梯度直方图(HOG)来取得正面脸部的特徵
  2. 训练模型:透过支援向量机(SVM)来做线性的类别区分

最终训练出来的模型就是我们今天要使用的方法。

在辨识准确度上相比,Dlib特徵检测要比哈尔特徵检测高,也不太需要调整参数来提高辨识度。

话不多说,Let's code!

  1. Day9的专案下,同样在face_detection目录下新增一个Python档案dlib_hog_svm.py
    dlib_hog_1
  2. 在新增的Python档案内输入以下内容 (相关程序码说明在注解内):
    # 汇入必要套件
    import time
    
    import cv2
    import dlib
    import imutils
    import numpy as np
    from imutils.face_utils import rect_to_bb
    from imutils.video import WebcamVideoStream
    
    # 初始化模型
    detector = dlib.get_frontal_face_detector()
    
    
    # 定义人脸侦测函数方便重复使用
    def detect(img):
        rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 侦测人脸,将辨识结果转为(x, y, w, h)的bounding box
        results = detector(rgb, 0)
        rects = [rect_to_bb(rect) for rect in results]
        return rects
    
    
    def main():
        # 启动WebCam
        vs = WebcamVideoStream().start()
        time.sleep(2.0)
        start = time.time()
        fps = vs.stream.get(cv2.CAP_PROP_FPS)
        print("Frames per second using cv2.CAP_PROP_FPS : {0}".format(fps))
    
        while True:
            # 取得当前的frame,变更比例为宽300,并且转成RGB图片
            frame = vs.read()
            img = frame.copy()
            img = imutils.resize(img, width=300)
    
            # 取得frame的大小(高,宽)
            ratio = frame.shape[1] / img.shape[1]
    
            # 呼叫侦测函数,取得结果
            rects = detect(img)
    
            # loop所有预测结果
            for rect in rects:
                # 计算bounding box(边界框)与准确率 - 取得(左上X,左上Y,右下X,右下Y)的值 (记得转换回原始frame的大小)
                box = np.array(rect) * ratio
                (x, y, w, h) = box.astype("int")
    
                # 画出边界框
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
    
            # 标示FPS
            end = time.time()
            cv2.putText(frame, f"FPS: {str(int(1 / (end - start)))}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
                        (0, 0, 255), 2)
            start = end
    
            # 显示影像
            cv2.imshow("Frame", frame)
    
            # 判断是否案下"q";跳离回圈
            key = cv2.waitKey(1) & 0xff
            if key == ord('q'):
                break
    
    
    if __name__ == '__main__':
        main()
    
    
  3. 在terminal输入python face_detection/dlib_hog_svm.py,跑出来的范例结果会是这样:
    dlib_hog_2

结论

  1. 我知道有些人看到这边会觉得不想实作,只想看结论;相信我,即使你是复制贴上程序码,实际跑看看,学到的东西跟直接看结论是完全不同的
  2. Dlib特徵检测会对脸部面向镜头的角度很敏感 (你可以看出我在范例结果中"刻意"把脸转一个角度与把口罩稍微往下移 -- 为了能够辨识到"戴口罩的人脸");其实你从程序码第12行get_frontal_face_detector函数名称就可以看出来了,这个功能对正面脸的准确度比较好
  3. Dlib特徵检测基本上不需要调整参数。唯一可能会调整的是程序码第19行detector(rgb, 0)中的第二个参数:
    • upsample_num_times:表示在进行侦测之前,要将图片"放大"几次;次数越多越能侦测到比较小的人脸,但花费的时间也更长
  4. 很重要所以再说一次,你要用Dlib做人脸关键点检测,今天这个方法是你其中一个不会多走远路的选择
  5. 辨识速度基本上对300px的影像可以有30 fps以上,实际在使用上大概跟哈尔特徵检测的速度差不多

参考程序码在这

好了,今天就到这边,

对程序码有疑问的欢迎留言罗。


<<:  Day24 - 铁人付外挂实作付款类别(三)- 接收回传资料

>>:  【Day24】来到了测试的总整理啦 ヽ(‘ ∇‘ )ノ

[Day 29] JS 实作练习 - YouTube API

前言 在练习 Ajax 串接实作时,馒头计画中就推荐就找了几个实作作业,找有开放资源的网站(如:Yo...

Day 11:批次修改!!

昨天体验了一些快捷键和命令,今天要讲的是在 vim 中也很常用的搜寻与取代 搜寻与取代 vim 的搜...

我选择的学习语言跟框架

我选了python当作主要开发语言 因为我以前有用过python而且很潮 框架部分我选比较主流的Dj...

乙级电脑软件设计技术士-Java 考照历程

在网路上很少关於这个科目的介绍,虽然第一次盲考就通过,但是整个过程还是如履薄冰。因此留下这次考试的过...

【day29】修改ProfileFragment X (第三方套件)ImagePicker

好的,我们会发现,有时候我们传送的照片档案太大,以及有可能我们拍完美美的照片时,却发现我们竟然不在...