前言
前段時(shí)間摸了下機(jī)器學(xué)習(xí),然后我發(fā)現(xiàn)其實(shí)openCV還是一個(gè)很浩瀚的庫的,現(xiàn)在也正在寫一篇有關(guān)yolo的博客,不過感覺理論偏多,所以在學(xué)yolo之前先摸一下opencv,簡單先寫個(gè)項(xiàng)目感受感受opencv。
流程
openCV實(shí)際上已經(jīng)有一個(gè)比較完整的模型了,下載在haarcascades
這里我們下haarcascade_frontalface_default.xml以備用。
在做人臉識(shí)別的時(shí)候流程就比較簡單了
- 讀取圖片
- 創(chuàng)建Haar級(jí)聯(lián)器
- 圖片轉(zhuǎn)灰度圖(可以不轉(zhuǎn),轉(zhuǎn)了能更快而已)
- 通過Haar級(jí)聯(lián)分類器來檢測人臉面部特征,返回faces結(jié)構(gòu)
- 使用openCV的接口,在原圖上框選出結(jié)果,并展示
編碼
這里代碼偏簡單,就不過多介紹了
import numpy as np
import cv2
img = './faces/lena.bmp'
#臉部Haar級(jí)聯(lián)器
facer_path = './faces/haarcascade_frontalface_default.xml'
facer = cv2.CascadeClassifier(facer_path)
img = cv2.imread(img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#執(zhí)行人臉識(shí)別
#現(xiàn)在可以使用Haar級(jí)聯(lián)分類器來檢測人臉和其他面部特征
faces = facer.detectMultiScale(gray,1.35,3)
for(x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
roi_img = img[y:y+h, x:x+w]
cv2.imshow('img', img)
cv2.waitKey()
結(jié)果:
進(jìn)階
且不看運(yùn)行的結(jié)果如何,但從結(jié)果你就可以看出來,這里只是把人臉從圖片中框出來了。但這還不夠,我們實(shí)際上不僅希望你可以把人臉圈出來,還希望能把人臉分類,比如A是A,B是B這樣。
OpenCV提供了3種人臉識(shí)別方法,分別是Eigenfaces、Fisherfaces和LBPH。這3種方法都是通過對(duì)比樣本的特征最終實(shí)現(xiàn)人臉識(shí)別。因?yàn)檫@3種算法提取特征的方式不一樣,側(cè)重點(diǎn)不同,所以不能分出孰優(yōu)孰劣,只能說每種方法都有各自的識(shí)別風(fēng)格。 OpenCV為每一種人臉識(shí)別方法都提供了創(chuàng)建識(shí)別器、訓(xùn)練識(shí)別器和識(shí)別3種方法,這3種方法的語法非常相似。我這里只簡單說說Eigenfaces怎么調(diào)用,至于其他的兩種讀者感興趣可以自己去搜索。
Eigenfaces人臉識(shí)別器
Eigenfaces也叫作“特征臉”。Eigenfaces通過PCA(主成分分析)方法將人臉數(shù)據(jù)轉(zhuǎn)換到另外一個(gè)空間維度做相似性計(jì)算。在計(jì)算過程中,算法可以忽略一些無關(guān)緊要的數(shù)據(jù),僅識(shí)別一些具有代表性的特征數(shù)據(jù),最后根據(jù)這些特征識(shí)別人臉。 開發(fā)者需要通過以下3種方法完成人臉識(shí)別操作。
(1)通過cv2.face.EigenFaceRecognizer_create()方法創(chuàng)建Eigenfaces人臉識(shí)別器,其語法如下:
recognizer = cv2.face.EigenFaceRecognizer_create(num_components, threshold)
參數(shù)說明:
num_components:可選參數(shù),PCA方法中保留的分量個(gè)數(shù),建議使用默認(rèn)值。
threshold:可選參數(shù),人臉識(shí)別時(shí)使用的閾值,建議使用默認(rèn)值。
返回值說明:
recognizer:創(chuàng)建的Eigenfaces人臉識(shí)別器對(duì)象。
(2)創(chuàng)建識(shí)別器對(duì)象后,需要通過對(duì)象的train()方法訓(xùn)練識(shí)別器。建議每個(gè)人都給出2幅以上的人臉圖像作為訓(xùn)練樣本。train()方法的語法如下:
recognizer.train(src, labels)
對(duì)象說明:
recognizer:已有的Eigenfaces人臉識(shí)別器對(duì)象。 參數(shù)說明:
src:用來訓(xùn)練的人臉圖像樣本列表,格式為list。樣本圖像必須寬、高一致。
labels:樣本對(duì)應(yīng)的標(biāo)簽,格式為數(shù)組,元素類型為整數(shù)。數(shù)組長度必須與樣本列表長度相同。樣本與標(biāo)簽按照插入順序一一對(duì)應(yīng)。
(3)訓(xùn)練識(shí)別器后可以通過識(shí)別器的predict()方法識(shí)別人臉,該方法對(duì)比樣本的特征,給出最相近的結(jié)果和評(píng)分,其語法如下:
label, confidence = recognizer.predict(src)
對(duì)象說明:
recognizer:已有的Eigenfaces人臉識(shí)別器對(duì)象。 參數(shù)說明:
src:需要識(shí)別的人臉圖像,該圖像寬、高必須與樣本一致。 返回值說明:
label:與樣本匹配程度最高的標(biāo)簽值。
confidence:匹配程度最高的信用度評(píng)分。評(píng)分小于5000匹配程度較高,0分表示2幅圖像完全一樣。 下面通過一個(gè)實(shí)例來演示Eigenfaces人臉識(shí)別器的用法。
確定流程
最后我們來確定一下流程:
- 讀取數(shù)據(jù)
- 創(chuàng)建特征臉識(shí)別器
- 輸入圖片和labels開始訓(xùn)練
- 輸入需要識(shí)別的人臉圖像
- 得到輸出
我這里把我的訓(xùn)練集整理了以下,名稱打在前面。我這里照片是我自己找的,具體的圖片訓(xùn)練集大伙可以自己去設(shè)定。
具體代碼如下,代碼的功能可以參考注釋
import numpy as np
import cv2
import os
face_path = './faces'
photos = list()
labels = list()
# 設(shè)置期望的圖像大小
desired_size = (811, 843)
#定義labels
names = {"0":"mengzi","1":"qy","2":"lx","3":"qq"}
# 從當(dāng)前路徑中讀取到所有的file
for root, dirs, files in os.walk(face_path):
for file in files:
if '.xml' in file:
continue
img_path = os.path.join(root, file)
img = cv2.imread(img_path, 0)
# 圖片需要設(shè)置到期望大小,因?yàn)槟P洼斎氲膱D片大小都必須是統(tǒng)一值,否則會(huì)無法訓(xùn)練
img_resized = cv2.resize(img, desired_size)
# 根據(jù)圖片的人臉,對(duì)應(yīng)到names,插入到labels
if 'mengzi' in file:
# 讀取圖像并調(diào)整大小
labels.append(0)
elif 'qy' in file:
labels.append(1)
elif 'lx' in file:
labels.append(2)
elif 'qq' in file:
labels.append(3)
else:
continue
photos.append(img_resized)
#創(chuàng)建人臉識(shí)別器
recognizer = cv2.face.EigenFaceRecognizer_create()
recognizer.train(photos, np.array(labels))
# 讀取測試圖像并調(diào)整大小
target = cv2.imread(face_path + '/test5.jpg', 0)
target_resized = cv2.resize(target, desired_size)
#輸出待識(shí)別對(duì)象
label, confidence = recognizer.predict(target_resized)
print('confidence = ' + str(confidence))
print(names[str(label)])
結(jié)果
這里代碼其實(shí)也能看得出,最后之能輸出圖片中人物的label和執(zhí)行度,這樣我們倒是完成了一個(gè)分類的工作。但是這里有個(gè)問題,就是我們不僅僅需要分類,還需要知道人臉的具體位置。
結(jié)合Haar級(jí)聯(lián)器和Eigenfaces人臉識(shí)別器實(shí)現(xiàn)人臉劃分
前言
剛剛說了兩種,一個(gè)是劃分區(qū)域,一個(gè)是打標(biāo)簽,那么能不能即劃分區(qū)域,又打上標(biāo)簽?zāi)兀慨?dāng)然是可以的,接下來就簡單說說怎么做。
流程
實(shí)際上流程就是把兩個(gè)模式結(jié)合起來,先使用Haar級(jí)聯(lián)器劃分出臉部區(qū)域,然后再用Eigenfaces人臉識(shí)別器去檢查分出的臉部區(qū)域的對(duì)象名稱,然后將標(biāo)簽放在圖片上即可。
- 加載Haar級(jí)聯(lián)分類器
- 讀取文件并訓(xùn)練Eigenfaces人臉識(shí)別器
- 讀取目標(biāo)圖片
- 通過Haar級(jí)聯(lián)分類器掃描得到目標(biāo)圖片中的所有人臉框
- 對(duì)所有人臉框使用Eigenfaces人臉識(shí)別器進(jìn)行識(shí)別
- 畫上方框,并打上標(biāo)簽
代碼
代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-810326.html
import numpy as np
import cv2
import os
# 加載Haar級(jí)聯(lián)分類器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
face_path = './faces'
photos = list()
labels = list()
# 讀取學(xué)習(xí)圖片
desired_size = (811, 843)
names = {"0":"mengzi","1":"qy","2":"lx","3":"qq","4":"ch"}
for root, dirs, files in os.walk(face_path):
for file in files:
if '.xml' in file:
continue
img_path = os.path.join(root, file)
img = cv2.imread(img_path, 0)
img_resized = cv2.resize(img, desired_size)
if 'mengzi' in file:
# 讀取圖像并調(diào)整大小
labels.append(0)
elif 'qy' in file:
labels.append(1)
elif 'lx' in file:
labels.append(2)
elif 'qq' in file:
labels.append(3)
elif 'ch' in file:
labels.append(4)
else:
continue
photos.append(img_resized)
# 訓(xùn)練人臉識(shí)別器
recognizer = cv2.face.EigenFaceRecognizer_create()
recognizer.train(photos, np.array(labels))
# 讀取測試圖像
target = cv2.imread(face_path + '/test_ch.jpg')
target_gray = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
# 檢測人臉
faces = face_cascade.detectMultiScale(target_gray, scaleFactor=1.2, minNeighbors=5, minSize=(30, 30))
# 對(duì)于每個(gè)檢測到的人臉
for (x, y, w, h) in faces:
# 在原圖上繪制矩形框出人臉
cv2.rectangle(target, (x, y), (x+w, y+h), (255, 0, 0), 2)
# 提取人臉區(qū)域并調(diào)整到期望大小
face_region = target_gray[y:y+h, x:x+w]
face_resized = cv2.resize(face_region, desired_size)
# 使用EigenFaceRecognizer進(jìn)行預(yù)測
label, confidence = recognizer.predict(face_resized)
# 將識(shí)別的名字和置信度打印在圖像上方
cv2.putText(target, f'{names[str(label)]} - {confidence:.2f}', (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)
# 顯示圖像
cv2.imshow('Face Recognition', target)
cv2.waitKey(0)
cv2.destroyAllWindows()
測試結(jié)果:
雖然打了馬賽克,但是實(shí)際上結(jié)果是可以置信的。在這里,還可以根據(jù)置信程度來對(duì)不同的人臉進(jìn)行篩選,比如不想要的臉或者置信程度不高的臉可以再進(jìn)行舍棄。文章來源地址http://www.zghlxwxcb.cn/news/detail-810326.html
到了這里,關(guān)于簡易機(jī)器學(xué)習(xí)筆記(十一)opencv 簡易使用-人臉識(shí)別、分類任務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!