Python 3 利用 Dlib 實現攝像頭人臉檢測特徵點標定

0. 引言html

  利用 Python 開發,藉助 Dlib 庫捕獲攝像頭中的人臉,進行實時人臉 68 個特徵點標定;python

  支持多張人臉;git

  有截圖功能;github

 

圖 1 工程效果示例( gif )app

圖 2 工程效果示例( 靜態圖片 )機器學習

 

1. 開發環境ide

  Python:  3.6.3函數

  Dlib:    19.7post

  OpenCv, NumPy學習

import dlib                  # 人臉檢測的庫 Dlib
import numpy as np   # 數據處理的庫 NumPy
import cv2                   # 圖像處理的庫 OpenCv

 

2. 源碼介紹

  其實實現很簡單,主要分爲兩個部分:攝像頭調用 + 人臉特徵點標定

2.1 攝像頭調用

  介紹下 OpenCv 中攝像頭的調用方法,用到如下幾個 OpenCv 函數:

    cv2.VideoCapture(0)               建立一個對象;

    cv2.VideoCapture.set(propId, value)  設置視頻參數;

    cv2.VideoCapture.isOpened()     檢測讀取視頻是否成功;

    cv2.VideoCapture.read()        返回是否讀取成功和讀取到的幀圖像;

  (具體能夠參考官方文檔:https://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html

  關於 cv2 中 VideoCapture 類的一些函數參數的說明以下:

# Sort by coneypo # Updated at 10, Oct # Blog: http://www.cnblogs.com/AdaminXie


###### 1. cv2.VideoCapture(), 建立cv2攝像頭對象 / Open the default camera ######
""" Python: cv2.VideoCapture() → <VideoCapture object> Python: cv2.VideoCapture(filename) → <VideoCapture object> filename – name of the opened video file (eg. video.avi) or image sequence (eg. img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) Python: cv2.VideoCapture(device) → <VideoCapture object> device – id of the opened video capturing device (i.e. a camera index). If there is a single camera connected, just pass 0. """ cap = cv2.VideoCapture(0) ##### 2. cv2.VideoCapture.set(propId, value),設置視頻參數; #####
""" propId: CV_CAP_PROP_POS_MSEC Current position of the video file in milliseconds. CV_CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next. CV_CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0 - start of the film, 1 - end of the film. CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream. CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream. CV_CAP_PROP_FPS Frame rate. ... value: 設置的參數值/ Value of the property """ cap.set(3, 480) ##### 3. cv2.VideoCapture.isOpened(), 檢查攝像頭初始化是否成功, 返回true或false / check if open camera successfully #####
cap.isOpened() ##### 4. cv2.VideoCapture.read([imgage]) -> retval,image, 讀取視頻 / Grabs, decodes and returns the next video frame #####
""" 返回兩個值: 一個是布爾值true/false,用來判斷讀取視頻是否成功/是否到視頻末尾 圖像對象,圖像的三維矩陣 """ flag, im_rd = cap.read()

 

2.2 人臉特徵點標定

  調用預測器 「shape_predictor_68_face_landmarks.dat」 進行 68 點標定,這是 Dlib 訓練好的模型,能夠直接調用,進行人臉 68 我的臉特徵點的標定;

  須要進行的後續工做是,利用座標值進行特徵點繪製;

  具體能夠參考個人另外一篇博客(Python 3 利用 Dlib 19.7 實現人臉68個特徵點的標定);

 

圖 3 Dlib 中人臉 68 個特徵點位置說明

   

2.3 源碼

  既然已經可以利用訓練好的模型進行特徵點檢測,須要進行的工做是將攝像頭捕獲到的視頻流,轉換爲 OpenCv 的圖像對象,這樣才能進行人臉特徵點檢測;

  而後利用返回的特徵點座標值,繪製特徵點,實時的再繪製到攝像頭界面上,達到實時人臉檢測追蹤的目的;

 

  利用 cv2.VideoCapture() 建立攝像頭對象,而後利用 flag, im_rd = cv2.VideoCapture.read() 讀取攝像頭視頻,im_rd 就是視頻中的一幀幀圖像;

  而後就相似於單張圖像進行人臉檢測,對這一幀幀的圖像 im_rd 利用 Dlib 進行特徵點標定,而後繪製特徵點;

  

  能夠按下 's' 鍵來獲取當前截圖,會存下帶有時間戳的本地圖像文件如 「screenshoot_1_2018-05-14-11-04-23.jpg」;

  或者按下 'q' 鍵來退出攝像頭窗口;

  

  有四個 python 文件:

  how_to_use_camera.py    OpenCv 調用攝像頭;

  get_features_from_image.py  繪製 "data/face_to_detect/face_x.jpg" 本地圖像人臉文件的特徵點;

  get_features_from_camera.py  從攝像頭實時人臉檢測繪製特徵點;

  remove_ss.py:        刪除 "data/screenshots/" 路徑下的全部截圖;

  ( 源碼都上傳到了 GitHub: https://github.com/coneypo/Dlib_face_detection_from_camera

  

  這裏只給出 get_features_from_camera.py 的源碼;

  get_features_from_camera.py:

 

  1 # 調用攝像頭,進行人臉捕獲,和 68 個特徵點的追蹤
  2 
  3 # Author:   coneypo
  4 # Blog:     http://www.cnblogs.com/AdaminXie
  5 # GitHub:   https://github.com/coneypo/Dlib_face_detection_from_camera
  6 
  7 # Created at 2018-02-26
  8 # Updated at 2019-01-28
  9 
 10 import dlib         # 機器學習的庫 Dlib
 11 import numpy as np  # 數據處理的庫 numpy
 12 import cv2          # 圖像處理的庫 OpenCv
 13 import time
 14 import timeit
 15 import statistics
 16 
 17 # 儲存截圖的目錄
 18 path_screenshots = "data/screenshots/"
 19 
 20 detector = dlib.get_frontal_face_detector()
 21 predictor = dlib.shape_predictor('data/dlib/shape_predictor_68_face_landmarks.dat')
 22 
 23 # 建立 cv2 攝像頭對象
 24 cap = cv2.VideoCapture(0)
 25 
 26 # cap.set(propId, value)
 27 # 設置視頻參數,propId 設置的視頻參數,value 設置的參數值
 28 cap.set(3, 480)
 29 
 30 # 截圖 screenshots 的計數器
 31 cnt = 0
 32 
 33 time_cost_list = []
 34 
 35 # cap.isOpened() 返回 true/false 檢查初始化是否成功
 36 while cap.isOpened():
 37 
 38     # cap.read()
 39     # 返回兩個值:
 40     #    一個布爾值 true/false,用來判斷讀取視頻是否成功/是否到視頻末尾
 41     #    圖像對象,圖像的三維矩陣
 42     flag, im_rd = cap.read()
 43 
 44     # 每幀數據延時 1ms,延時爲 0 讀取的是靜態幀
 45     k = cv2.waitKey(1)
 46 
 47     # 取灰度
 48     img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)
 49 
 50     # start point
 51     start = timeit.default_timer()
 52 
 53     # 人臉數
 54     faces = detector(img_gray, 0)
 55 
 56     # print(len(faces))
 57 
 58     # 待會要寫的字體
 59     font = cv2.FONT_HERSHEY_SIMPLEX
 60 
 61     # 標 68 個點
 62     if len(faces) != 0:
 63         # 檢測到人臉
 64         for i in range(len(faces)):
 65             landmarks = np.matrix([[p.x, p.y] for p in predictor(im_rd, faces[i]).parts()])
 66 
 67             for idx, point in enumerate(landmarks):
 68                 # 68 點的座標
 69                 pos = (point[0, 0], point[0, 1])
 70 
 71                 # 利用 cv2.circle 給每一個特徵點畫一個圈,共 68 個
 72                 cv2.circle(im_rd, pos, 2, color=(139, 0, 0))
 73 
 74                 # 利用 cv2.putText 輸出 1-68
 75                 cv2.putText(im_rd, str(idx + 1), pos, font, 0.2, (187, 255, 255), 1, cv2.LINE_AA)
 76 
 77         cv2.putText(im_rd, "faces: " + str(len(faces)), (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA)
 78 
 79         # end point
 80         stop = timeit.default_timer()
 81         time_cost_list.append(stop - start)
 82         print("%-15s %f" % ("Time cost:", (stop - start)))
 83 
 84     else:
 85         # 沒有檢測到人臉
 86         cv2.putText(im_rd, "no face", (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA)
 87 
 88 
 89     # 添加說明
 90     im_rd = cv2.putText(im_rd, "press 'S': screenshot", (20, 400), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
 91     im_rd = cv2.putText(im_rd, "press 'Q': quit", (20, 450), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
 92 
 93     # 按下 's' 鍵保存
 94     if k == ord('s'):
 95         cnt += 1
 96         print(path_screenshots + "screenshot" + "_" + str(cnt) + "_" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".jpg")
 97         cv2.imwrite(path_screenshots + "screenshot" + "_" + str(cnt) + "_" + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + ".jpg", im_rd)
 98 
 99     # 按下 'q' 鍵退出
100     if k == ord('q'):
101         break
102 
103     # 窗口顯示
104     # 參數取 0 能夠拖動縮放窗口,爲 1 不能夠
105     # cv2.namedWindow("camera", 0)
106     cv2.namedWindow("camera", 1)
107 
108     cv2.imshow("camera", im_rd)
109 
110 # 釋放攝像頭
111 cap.release()
112 
113 # 刪除創建的窗口
114 cv2.destroyAllWindows()
115 
116 print("%-15s" % "Result:")
117 print("%-15s %f" % ("Max time:", (max(time_cost_list))))
118 print("%-15s %f" % ("Min time:", (min(time_cost_list))))
119 print("%-15s %f" % ("Average time:", statistics.mean(time_cost_list)))

 

 

實時輸出處理時間:

...
Time cost: 0.065273 Time cost: 0.059348 Time cost: 0.093570 Time cost: 0.091448 Time cost: 0.084946 Time cost: 0.089457 Time cost: 0.084367 Time cost: 0.094103 Time cost: 0.096082 Time cost: 0.073331 Time cost: 0.073685 Time cost: 0.065583 Time cost: 0.061161 Time cost: 0.061650 Time cost: 0.060952 Time cost: 0.084485 Result: Max time: 0.112430 Min time: 0.057525 Average time: 0.085478

 

筆記本 CPU: i5-6200U@2.30GHz, Memory: 8G 處理時間平均在 0.08s;

 

# 請尊重他人勞動成果,轉載或者使用源碼請註明出處:http://www.cnblogs.com/AdaminXie

# 若是對您有幫助,歡迎在 GitHub 上 star 支持下: https://github.com/coneypo/Dlib_face_detection_from_camera

# 若有問題能夠聯繫本人郵箱,商業合做勿擾謝謝: coneypo@foxmail.com

相關文章
相關標籤/搜索