iT邦幫忙

2022 iThome 鐵人賽

DAY 7
2

這篇教學會介紹使用 OpenCV 內建的 LBPH 人臉訓練功能 ( cv2.face.LBPHFaceRecognizer_create()),搭配人臉特徵模型,訓練判斷不同人臉的模型檔案,完成後就能透過攝影機的影像,辨識出不同的人臉,標記出對應的名字。

原文參考:OpenCV 辨識不同人臉

因為程式中的 OpenCV 會需要使用鏡頭或 GPU,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) ,並安裝 OpenCV 函式庫 ( 參考:OpenCV 函式庫 )。

Python 教學 - OpenCV 辨識不同人臉

安裝 opencv_contrib_python

要使用 cv2.face.LBPHFaceRecognizer_create(),必須先安裝 opencv_contrib_python,輸入下列指令進行安裝,opencv_contrib_python 提供 opencv 更多的操作方法。

如果使用 Anaconda Jupyter 搭配命令提示字元或終端機安裝,雖然可以順利安裝,但程式執行後可能會出現「module 'cv2' has no attribute 'face'」提示,有兩種解決方法:

  • 第一、改成在 Jupyter 裡使用 !pip 直接安裝。
  • 第二,移除 opencv-python 和 opencv_contrib_python,再次重新安裝。
pip install opencv_contrib_python

使用人臉圖片,訓練模型

如果要辨識不同的人臉,必須先「訓練」不同人臉的模型,透過 cv2.face.LBPHFaceRecognizer_create() 方法,將收集好的人臉圖片 ( 同樣的人,不同角度的照片 20~30 張 ),以每個 id 為一個人的單位進行影像訓練,保留相關特徵值,屆時只要比對特徵值,就能得到人臉辨識的信心指數。

Python 教學 - OpenCV 辨識不同人臉

首先準備一些菜英文 ( 打出真正名字就不能發文,是哪招? ) 的照片和川普的照片 ( 使用 Google 搜尋 )

Python 教學 - OpenCV 辨識不同人臉

Python 教學 - OpenCV 辨識不同人臉

接著撰寫下方的程式,除了訓練菜英文 ( 打出真正名字就不能發文,是哪招? ) 和川普的照片,也搭配一組使用攝影鏡頭記錄自己的人臉影像,經過訓練後產生 yml 模型檔案儲存。

import cv2
import numpy as np
detector = cv2.CascadeClassifier('xml/haarcascade_frontalface_default.xml')  # 載入人臉追蹤模型
recog = cv2.face.LBPHFaceRecognizer_create()      # 啟用訓練人臉模型方法
faces = []   # 儲存人臉位置大小的串列
ids = []     # 記錄該人臉 id 的串列

for i in range(1,31):
    img = cv2.imread(f'face01/{i}.jpg')           # 依序開啟每一張菜英文的照片
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 色彩轉換成黑白
    img_np = np.array(gray,'uint8')               # 轉換成指定編碼的 numpy 陣列
    face = detector.detectMultiScale(gray)        # 擷取人臉區域
    for(x,y,w,h) in face:
        faces.append(img_np[y:y+h,x:x+w])         # 記錄菜英文人臉的位置和大小內像素的數值
        ids.append(1)                             # 記錄菜英文人臉對應的 id,只能是整數,都是 1 表示菜英文的 id 為 1

for i in range(1,16):
    img = cv2.imread(f'face02/{i}.jpg')           # 依序開啟每一張川普的照片
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 色彩轉換成黑白
    img_np = np.array(gray,'uint8')               # 轉換成指定編碼的 numpy 陣列
    face = detector.detectMultiScale(gray)        # 擷取人臉區域
    for(x,y,w,h) in face:
        faces.append(img_np[y:y+h,x:x+w])         # 記錄川普人臉的位置和大小內像素的數值
        ids.append(2)                             # 記錄川普人臉對應的 id,只能是整數,都是 1 表示川普的 id 為 1

print('camera...')                                # 提示啟用相機
cap = cv2.VideoCapture(0)                         # 啟用相機
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, img = cap.read()                         # 讀取影片的每一幀
    if not ret:
        print("Cannot receive frame")
        break
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 色彩轉換成黑白
    img_np = np.array(gray,'uint8')               # 轉換成指定編碼的 numpy 陣列
    face = detector.detectMultiScale(gray)        # 擷取人臉區域
    for(x,y,w,h) in face:
        faces.append(img_np[y:y+h,x:x+w])         # 記錄自己人臉的位置和大小內像素的數值
        ids.append(3)                             # 記錄自己人臉對應的 id,只能是整數,都是 1 表示川普的 id
    cv2.imshow('oxxostudio', img)                      # 顯示攝影機畫面
    if cv2.waitKey(100) == ord('q'):              # 每一毫秒更新一次,直到按下 q 結束
        break

print('training...')                              # 提示開始訓練
recog.train(faces,np.array(ids))                  # 開始訓練
recog.save('face.yml')                            # 訓練完成儲存為 face.yml
print('ok!')

根據模型,辨識不同人臉

已經訓練好 yml 模型檔後,就可以開始進行辨識,當辨識到人臉,會回傳 id 與該 id 的信心指數 confidence,信心指數數值越小表示越準確,藉由 id 與信心指數就能判斷出現在畫面中的人臉,並進一步標記對應的名字,下方的程式碼會標記出菜英文、川普以及 oxxostudio 三個人臉,如果辨識的人臉不屬於這三個人,則會標記 ??? 的文字。

import cv2
recognizer = cv2.face.LBPHFaceRecognizer_create()         # 啟用訓練人臉模型方法
recognizer.read('face.yml')                               # 讀取人臉模型檔
cascade_path = "xml/haarcascade_frontalface_default.xml"  # 載入人臉追蹤模型
face_cascade = cv2.CascadeClassifier(cascade_path)        # 啟用人臉追蹤

cap = cv2.VideoCapture(0)                                 # 開啟攝影機
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, img = cap.read()
    if not ret:
        print("Cannot receive frame")
        break
    img = cv2.resize(img,(540,300))              # 縮小尺寸,加快辨識效率
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  # 轉換成黑白
    faces = face_cascade.detectMultiScale(gray)  # 追蹤人臉 ( 目的在於標記出外框 )

    # 建立姓名和 id 的對照表
    name = {
        '1':'Tsai',
        '2':'Trump',
        '3':'oxxostudio'
    }

    # 依序判斷每張臉屬於哪個 id
    for(x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)            # 標記人臉外框
        idnum,confidence = recognizer.predict(gray[y:y+h,x:x+w])  # 取出 id 號碼以及信心指數 confidence
        if confidence < 60:
            text = name[str(idnum)]                               # 如果信心指數小於 60,取得對應的名字
        else:
            text = '???'                                          # 不然名字就是 ???
        # 在人臉外框旁加上名字
        cv2.putText(img, text, (x,y-5),cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2, cv2.LINE_AA)

    cv2.imshow('oxxostudio', img)
    if cv2.waitKey(5) == ord('q'):
        break    # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

Python 教學 - OpenCV 辨識不同人臉

更多 Python 教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 6 ) OpenCV 行人偵測
下一篇
( Day 8 ) OpenCV 單物件追蹤
系列文
Python x AI 影像辨識好好玩32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
oxxo
iT邦研究生 1 級 ‧ 2022-09-18 01:04:49

如果把菜英文的「菜打成蔡」就不能發文?這是哪招?
浪費我兩三個小時在找哪裡有問題,只是因為不能打出總統的名字????
https://ithelp.ithome.com.tw/upload/images/20220918/20091306Gk160ITaSJ.jpg

Felix Lin iT邦新手 5 級 ‧ 2022-09-19 22:53:12 檢舉

這未免太扯,超前部署的網路言論審查嗎? /images/emoticon/emoticon38.gif

0
oxxo
iT邦研究生 1 級 ‧ 2022-09-18 01:07:05

找了半天找不到如何聯絡管理員?是怎樣?

mike95375 iT邦新手 5 級 ‧ 2024-02-23 15:48:02 檢舉

想請問作者為甚麼我放的照片它沒有辦法成功識別

0
khll1l7
iT邦新手 5 級 ‧ 2022-10-24 23:01:02

您好 想請問照片集要放在哪個檔案夾才能訓練~謝謝!!

oxxo iT邦研究生 1 級 ‧ 2022-10-25 10:03:47 檢舉

可以看一下程式碼裡面的路徑,
模型應該是在同一層的 xml 資料夾裡,
臉應該是在 face01 和 face02 資料夾中

0
mike95375
iT邦新手 5 級 ‧ 2024-02-22 16:27:23

想請問作者它要擷取人臉區域的方式要如何擷取,而且我按q的時候會沒有回應

我要留言

立即登入留言