iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
AI & Data

[Computer Vision] 電腦視覺下的人臉系列 第 21

[Day 21] Facial Recognition: 只需要OpenCV就可以達成即時人臉辨識

  • 分享至 

  • xImage
  •  

昨天的內容還可以吸收嗎?

也許有人會問:

這些神經網路模型還有GPU、CUDA什麼的我都不懂,能不能有一個最簡單的方式做即時人臉辨識?

也許Google ML Kit比較適合你

OpenCV除了之前提到的,專門處理影像相關功能之外,

它提供了一系列的接口讓你可以載入各種模型 (只要有辦法轉成OpenCV支援的模型格式)

  • cv2.dnn.readNet
  • cv2.dnn.readNetFromCaffe
  • cv2.dnn.readNetFromONNX
  • cv2.dnn.readNetFromTorch
  • cv2.dnn.readNetFromDarknet
  • cv2.dnn.readNetFromModelOptimizer
  • cv2.dnn.readNetFromTensorflow

對,基本上想得到的想不到的模型格式它都支援了,

而OpenCV會自動載入模型結構,

你要做的就是給它輸入跟得到輸出而已。

由於今天的目的是用最簡潔的方式來應用人臉偵測

我們只會使用OpenCV來做人臉偵測與人臉辨識的工作,

當然,還是需要有資料。

我們就開始吧!

本文開始

  1. 開啟之前的專案,參考這一篇準備資料
  2. 在專案的face_recognition下新增一個檔案opencv_realtime.py
  3. 程式碼與相關說明:
     import ntpath
     import sys
    
     # resolve module import error in PyCharm
     sys.path.append(ntpath.dirname(ntpath.dirname(ntpath.abspath(__file__))))
    
     import argparse
     import numpy as np
     import os
     import time
     from urllib.request import urlretrieve
    
     import cv2
     from imutils.video import WebcamVideoStream
     from imutils.video import FPS
     from sklearn.preprocessing import LabelEncoder
     from sklearn.svm import SVC
    
     from dataset.load_dataset import load_images
     from face_detection.opencv_dnns import detect
    
     # 下載模型相關檔案
     embedder_model_url = "https://storage.cmusatyalab.org/openface-models/nn4.small2.v1.t7"
     embedder_model = "nn4.small2.v1.t7"
     if not os.path.exists(embedder_model_url):
         urlretrieve(embedder_model_url, embedder_model)
    
    
     def main():
         # 初始化arguments
         ap = argparse.ArgumentParser()
         ap.add_argument("-i", "--input", type=str, required=True, help="the input dataset path")
         args = vars(ap.parse_args())
    
         # 初始化要使用到的模型
         embedder = cv2.dnn.readNetFromTorch(embedder_model)
    
         print("[INFO] loading dataset....")
         # 篩選掉張數小於10的人臉
         (faces, names) = load_images(args["input"], min_size=10)
         print(f"[INFO] {len(faces)} images in dataset")
    
         # 初始化結果
         known_embeddings = []
         known_names = []
    
         # 建立我們的人臉embeddings資料庫
         print("[INFO] serializing embeddings...")
         start = time.time()
         for (img, name) in zip(faces, names):
             rects = detect(img)
             for rect in rects:
                 (x, y, w, h) = rect["box"]
                 roi = img[y:y + h, x:x + w]
                 faceBlob = cv2.dnn.blobFromImage(roi, 1.0 / 255, (96, 96), (0, 0, 0), swapRB=True, crop=False)
                 embedder.setInput(faceBlob)
                 vec = embedder.forward()
    
                 known_embeddings.append(vec.flatten())
                 known_names.append(name)
    
         end = time.time()
         print(f"[INFO] serializing embeddings done, tooks {round(end - start, 3)} seconds")
    
         # 使用SVM來"訓練"我們的模型可以辨別人臉
         le = LabelEncoder()
         labels = le.fit_transform(known_names)
         print("[INFO] training model...")
         recognizer = SVC(C=1.0, kernel="linear", probability=True)
         recognizer.fit(known_embeddings, labels)
    
         # 啟動WebCam
         vs = WebcamVideoStream().start()
         time.sleep(2.0)
         fps = FPS().start()
    
         while True:
             frame = vs.read()
             # 偵測人臉與將人臉轉為128-d embeddings
             rects = detect(frame)
             for rect in rects:
                 (x, y, w, h) = rect["box"]
                 roi = frame[y:y + h, x:x + w]
                 faceBlob = cv2.dnn.blobFromImage(roi, 1.0 / 255, (96, 96), (0, 0, 0), swapRB=True, crop=False)
                 embedder.setInput(faceBlob)
                 vec = embedder.forward()
    
                 # 辨識人臉
                 preds = recognizer.predict_proba(vec)[0]
                 i = np.argmax(preds)
                 proba = preds[i]
                 name = le.classes_[i]
    
                 text = "{}: {:.2f}%".format(name, proba * 100)
                 _y = y - 10 if y - 10 > 10 else y + 10
                 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
                 cv2.putText(frame, text, (x, _y), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
    
             fps.update()
    
             cv2.imshow("Frame", frame)
             key = cv2.waitKey(1) & 0xFF
             if key == ord("q"):
                 break
    
         fps.stop()
         print("[INFO] Approximate FPS: {:.2f}".format(fps.fps()))
    
         # 清除用不到的物件
         cv2.destroyAllWindows()
         vs.stop()
    
    
     if __name__ == '__main__':
         main()
    
    
  4. 在terminal中輸入python face_recognition/opencv_realtime.py -i dataset/caltech_faces,等待資料庫建立後,辨識看看你自己的臉吧!

opencv_fc_1

程式碼主要處理流程與昨天基本相同:

  1. 初始化模型
  2. 把已知的人臉圖片ROI轉成embeddings資料庫
  3. 訓練 / 分類embeddings資料庫
  4. 啟動攝影機,逐幀與資料庫的人臉比對
  5. 將最相似的人臉名稱取出,顯示結果

可以看到雖然辨識率不高 (主要原因為資料庫中都是未戴口罩的照片,但實際測試是戴上口罩),不過還是可以成功辨識出是誰。

今天的程式碼中是使用與Google FaceNet相同架構的OpenFace預訓練模型,

明天我們將談談FaceNet這個網路。

-- 今日程式碼傳送門


上一篇
[Day 20] Facial Recognition: OpenCV + Dlib可以一次滿足
下一篇
[Day 22] Facial Recognition: Google FaceNet
系列文
[Computer Vision] 電腦視覺下的人臉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
weixun
iT邦新手 5 級 ‧ 2021-12-29 21:42:55

問題已解決,抱歉

不客氣 (雖然不知道問題是什麼 ?

0
u09127104
iT邦新手 5 級 ‧ 2022-06-29 15:54:41

不好意思
請問在opencv_realtime.py專案下
usage: dlib_with_opencv_realtime.py [-h] -i INPUT
dlib_with_opencv_realtime.py: error: the following arguments are required: -i/--input
執行後跑出這個要如何解決

跳出的錯誤應該很清楚了喔!
你缺少了輸入參數INPUT

我要留言

立即登入留言