Python-OpenCV人臉識(shí)別之?dāng)?shù)據(jù)集生成

上一篇文章中,我們學(xué)習(xí)了如何安裝配置OpenCV和Python,然后寫(xiě)了些代碼玩玩人臉檢測(cè)?,F(xiàn)在我們要進(jìn)行下一步了,即搞一個(gè)人臉識(shí)別程序,就是不只是檢測(cè)還需要識(shí)別到人是誰(shuí)。

來(lái),搞人臉識(shí)別

要搞一個(gè)人臉識(shí)別程序,首先我們需要先用提前裁剪好的標(biāo)注好的人臉照片訓(xùn)練一個(gè)識(shí)別器。比如說(shuō),我們的識(shí)別器需要識(shí)別兩個(gè)人,一個(gè)人的id是1,而另一個(gè)的id是2,于是在數(shù)據(jù)集里面,1號(hào)人的所有照片會(huì)有id 1號(hào),2號(hào)人同理。然后我們就會(huì)使用這些數(shù)據(jù)集照片去訓(xùn)練識(shí)別器,再?gòu)囊粋€(gè)視頻中識(shí)別出1號(hào)人。

我們把要做的事分成三部分:

  1. 創(chuàng)建數(shù)據(jù)集
  2. 訓(xùn)練
  3. 識(shí)別

在本文中,我們會(huì)嘗試寫(xiě)一個(gè)程序來(lái)生成數(shù)據(jù)集。

生成數(shù)據(jù)集

我們來(lái)寫(xiě)一個(gè)數(shù)據(jù)集生成腳本。

首先打開(kāi)我們的Python環(huán)境,不管是Pycharm等IDE,還是簡(jiǎn)單的記事本都行。需要提前準(zhǔn)備的是在目錄中放好haarcascade_frontalface_default.xml,上一篇也有用到過(guò)這個(gè)XML文件,就是OpenCV自帶的。

接下來(lái)使用cv2獲取攝像頭數(shù)據(jù)以及XML文件:

import cv2
cam = cv2.VideoCapture(0)
detector=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

我們的數(shù)據(jù)集需要先從攝像頭采集一些人臉例子照片,當(dāng)然,只能是同一個(gè)人的。然后程序會(huì)給這些例子照片添加id,并將照片保存在一個(gè)文件夾中,這個(gè)文件夾我們就將它命名為dataSet吧。

來(lái),我們?cè)趐y腳本的同目錄下創(chuàng)建一個(gè)dataSet的文件夾。為了不會(huì)將不同的人臉照片弄混,我們需要定一個(gè)命名規(guī)則,用于給照片命名。

例如,命名規(guī)則為User.[ID].[SampleNumber].jpg。如果是2號(hào)人的第十張照片,我們可以將它命名為User.2.10.jpg。

為什么要定義這樣的格式呢?因?yàn)檫@樣,在加載照片訓(xùn)練的時(shí)候,我們就可以只通過(guò)照片的文件名,就能簡(jiǎn)單地判斷是幾號(hào)用戶的人臉照片。

接下來(lái),我們嘗試用比較簡(jiǎn)單的方法,通過(guò)shell輸入,來(lái)獲取人的id,并且初始化計(jì)算器變量來(lái)存儲(chǔ)人們的例子數(shù)。

Id = raw_input('enter your id: ')
sampleNum = 0

然后我們加入一個(gè)主循環(huán),我們會(huì)從視頻流中輸入20個(gè)例子,然后把例子都保存在已經(jīng)創(chuàng)建好的dataSet文件夾。

這是之前寫(xiě)過(guò)的代碼版本,用于人臉檢測(cè):

while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray, 1.3, 5)
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

    cv2.imshow('frame', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

現(xiàn)在我們將它改造成數(shù)據(jù)集生成程序:

while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray, 1.3, 5)
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # 增加例子數(shù)
        sampleNum = sampleNum + 1
        # 把照片保存到數(shù)據(jù)集文件夾
        cv2.imwrite("dataSet/user." + str(Id) + '.' + str(sampleNum) + ".jpg", gray[y:y + h, x:x + w])

        cv2.imshow('frame', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

我們添加了兩行代碼,用以計(jì)算例子數(shù),以及將人臉照片按照我們的命名規(guī)則保存為jpg格式。

其中有一個(gè)值得注意的地方,就是gray[y : y + h, x : x + w]。此處我們是把一張灰度圖片看成一個(gè)二維數(shù)組(或二維矢量),然后使用python中[]截取OpenCV檢測(cè)出來(lái)的人臉區(qū)域。

不過(guò)這樣的代碼會(huì)在一秒內(nèi)快速地生成許多照片,比如說(shuō)20張。我們不想要那么快,我們需要的是更好的素材,比如說(shuō)從不同角度拍攝出來(lái)的照片,這樣的話,要求慢一點(diǎn)。

為了慢一點(diǎn),我們需要提高一下兩次拍攝之間的延遲。同時(shí),我們素材不需要太多,20張就好。

while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray, 1.3, 5)
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # 增加例子數(shù) 
        sampleNum = sampleNum + 1
        # 把照片保存到數(shù)據(jù)集文件夾
        cv2.imwrite("dataSet/User." + str(Id) + '.' + str(sampleNum) + ".jpg", gray[y:y + h, x:x + w])  #

        cv2.imshow('frame', img)
    # 延遲100毫秒 
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break
    # 超過(guò)20張就可以停了
    elif sampleNum > 20:
        break

好,繼續(xù),現(xiàn)在的代碼就會(huì)在兩個(gè)拍攝間延遲100毫秒,100毫秒足夠讓我們?nèi)ヒ苿?dòng)我們?nèi)四樀慕嵌攘耍〞r(shí)間不夠長(zhǎng)就再加)。而且,在拍攝20張后就停止了。

最后記得釋放資源:

cap.release()
cv2.destroyAllWindows()

放出完整代碼:

import cv2

detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
sampleNum = 0
Id = raw_input('enter your id: ')

while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = detector.detectMultiScale(gray, 1.3, 5)
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # incrementing sample number
        sampleNum = sampleNum + 1
        # saving the captured face in the dataset folder
        cv2.imwrite("dataSet/User." + str(Id) + '.' + str(sampleNum) + ".jpg", gray[y:y + h, x:x + w])  #

        cv2.imshow('frame', img)
    # wait for 100 miliseconds
    if cv2.waitKey(100) & 0xFF == ord('q'):
        break
    # break if the sample number is morethan 20
    elif sampleNum > 20:
        break

cap.release()
cv2.destroyAllWindows()

生成結(jié)果

image

如圖,已經(jīng)生成了一堆訓(xùn)練素材了。

先這樣吧

原文,若有錯(cuò)誤之處請(qǐng)指出,更多地關(guān)注煎魚(yú)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇文章十分的長(zhǎng),大概有2萬(wàn)7千字左右。 一、發(fā)展史 1、人臉識(shí)別的理解: 人臉識(shí)別(Face Recogniti...
    放飛人夜閱讀 20,484評(píng)論 8 122
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,637評(píng)論 19 139
  • 一點(diǎn)背景知識(shí) OpenCV 是一個(gè)開(kāi)源的計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)庫(kù)。它包含成千上萬(wàn)優(yōu)化過(guò)的算法,為各種計(jì)算機(jī)視覺(jué)應(yīng)用提...
    沬日十七閱讀 1,088評(píng)論 0 4
  • 就在2008年1(原創(chuàng))父親啊,您怎么就這樣拋下我了?1月21日的夜里11點(diǎn)半左右,我們正在酣睡中,突然聽(tīng)到電話鈴...
    西瓜甜甜啦閱讀 844評(píng)論 17 22
  • 手寫(xiě)快排,算法練習(xí)題 借用SDL的庫(kù),來(lái)演示一下幾個(gè)排序算法的效果:依次測(cè)試了 "快排、選擇、插入和冒泡"。 廢話...
    碼腦閱讀 756評(píng)論 0 49

友情鏈接更多精彩內(nèi)容