简易机器学习笔记(十一)opencv 简易使用-人脸识别、分类任务
前言
前段時間摸了下機器學習,然后我發現其實openCV還是一個很浩瀚的庫的,現在也正在寫一篇有關yolo的博客,不過感覺理論偏多,所以在學yolo之前先摸一下opencv,簡單先寫個項目感受感受opencv。
流程
openCV實際上已經有一個比較完整的模型了,下載在haarcascades
這里我們下haarcascade_frontalface_default.xml以備用。
在做人臉識別的時候流程就比較簡單了
- 讀取圖片
- 創建Haar級聯器
- 圖片轉灰度圖(可以不轉,轉了能更快而已)
- 通過Haar級聯分類器來檢測人臉面部特征,返回faces結構
- 使用openCV的接口,在原圖上框選出結果,并展示
編碼
這里代碼偏簡單,就不過多介紹了
import numpy as np
import cv2
img = './faces/lena.bmp'
#臉部Haar級聯器
facer_path = './faces/haarcascade_frontalface_default.xml'
facer = cv2.CascadeClassifier(facer_path)
img = cv2.imread(img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#執行人臉識別
#現在可以使用Haar級聯分類器來檢測人臉和其他面部特征
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()
結果:
進階
且不看運行的結果如何,但從結果你就可以看出來,這里只是把人臉從圖片中框出來了。但這還不夠,我們實際上不僅希望你可以把人臉圈出來,還希望能把人臉分類,比如A是A,B是B這樣。
OpenCV提供了3種人臉識別方法,分別是Eigenfaces、Fisherfaces和LBPH。這3種方法都是通過對比樣本的特征最終實現人臉識別。因為這3種算法提取特征的方式不一樣,側重點不同,所以不能分出孰優孰劣,只能說每種方法都有各自的識別風格。 OpenCV為每一種人臉識別方法都提供了創建識別器、訓練識別器和識別3種方法,這3種方法的語法非常相似。我這里只簡單說說Eigenfaces怎么調用,至于其他的兩種讀者感興趣可以自己去搜索。
Eigenfaces人臉識別器
Eigenfaces也叫作“特征臉”。Eigenfaces通過PCA(主成分分析)方法將人臉數據轉換到另外一個空間維度做相似性計算。在計算過程中,算法可以忽略一些無關緊要的數據,僅識別一些具有代表性的特征數據,最后根據這些特征識別人臉。 開發者需要通過以下3種方法完成人臉識別操作。
(1)通過cv2.face.EigenFaceRecognizer_create()方法創建Eigenfaces人臉識別器,其語法如下:
recognizer = cv2.face.EigenFaceRecognizer_create(num_components, threshold)
參數說明:
num_components:可選參數,PCA方法中保留的分量個數,建議使用默認值。
threshold:可選參數,人臉識別時使用的閾值,建議使用默認值。
返回值說明:
recognizer:創建的Eigenfaces人臉識別器對象。
(2)創建識別器對象后,需要通過對象的train()方法訓練識別器。建議每個人都給出2幅以上的人臉圖像作為訓練樣本。train()方法的語法如下:
recognizer.train(src, labels)
對象說明:
recognizer:已有的Eigenfaces人臉識別器對象。 參數說明:
src:用來訓練的人臉圖像樣本列表,格式為list。樣本圖像必須寬、高一致。
labels:樣本對應的標簽,格式為數組,元素類型為整數。數組長度必須與樣本列表長度相同。樣本與標簽按照插入順序一一對應。
(3)訓練識別器后可以通過識別器的predict()方法識別人臉,該方法對比樣本的特征,給出最相近的結果和評分,其語法如下:
label, confidence = recognizer.predict(src)
對象說明:
recognizer:已有的Eigenfaces人臉識別器對象。 參數說明:
src:需要識別的人臉圖像,該圖像寬、高必須與樣本一致。 返回值說明:
label:與樣本匹配程度最高的標簽值。
confidence:匹配程度最高的信用度評分。評分小于5000匹配程度較高,0分表示2幅圖像完全一樣。 下面通過一個實例來演示Eigenfaces人臉識別器的用法。
確定流程
最后我們來確定一下流程:
- 讀取數據
- 創建特征臉識別器
- 輸入圖片和labels開始訓練
- 輸入需要識別的人臉圖像
- 得到輸出
我這里把我的訓練集整理了以下,名稱打在前面。我這里照片是我自己找的,具體的圖片訓練集大伙可以自己去設定。
具體代碼如下,代碼的功能可以參考注釋
import numpy as np
import cv2
import os
face_path = './faces'
photos = list()
labels = list()
# 設置期望的圖像大小
desired_size = (811, 843)
#定義labels
names = {"0":"mengzi","1":"qy","2":"lx","3":"qq"}
# 從當前路徑中讀取到所有的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)
# 圖片需要設置到期望大小,因為模型輸入的圖片大小都必須是統一值,否則會無法訓練
img_resized = cv2.resize(img, desired_size)
# 根據圖片的人臉,對應到names,插入到labels
if 'mengzi' in file:
# 讀取圖像并調整大小
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)
#創建人臉識別器
recognizer = cv2.face.EigenFaceRecognizer_create()
recognizer.train(photos, np.array(labels))
# 讀取測試圖像并調整大小
target = cv2.imread(face_path + '/test5.jpg', 0)
target_resized = cv2.resize(target, desired_size)
#輸出待識別對象
label, confidence = recognizer.predict(target_resized)
print('confidence = ' + str(confidence))
print(names[str(label)])
結果
這里代碼其實也能看得出,最后之能輸出圖片中人物的label和執行度,這樣我們倒是完成了一個分類的工作。但是這里有個問題,就是我們不僅僅需要分類,還需要知道人臉的具體位置。
結合Haar級聯器和Eigenfaces人臉識別器實現人臉劃分
前言
剛剛說了兩種,一個是劃分區域,一個是打標簽,那么能不能即劃分區域,又打上標簽呢?當然是可以的,接下來就簡單說說怎么做。
流程
實際上流程就是把兩個模式結合起來,先使用Haar級聯器劃分出臉部區域,然后再用Eigenfaces人臉識別器去檢查分出的臉部區域的對象名稱,然后將標簽放在圖片上即可。
- 加載Haar級聯分類器
- 讀取文件并訓練Eigenfaces人臉識別器
- 讀取目標圖片
- 通過Haar級聯分類器掃描得到目標圖片中的所有人臉框
- 對所有人臉框使用Eigenfaces人臉識別器進行識別
- 畫上方框,并打上標簽
代碼
代碼如下:
import numpy as np
import cv2
import os
# 加載Haar級聯分類器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
face_path = './faces'
photos = list()
labels = list()
# 讀取學習圖片
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:
# 讀取圖像并調整大小
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)
# 訓練人臉識別器
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))
# 對于每個檢測到的人臉
for (x, y, w, h) in faces:
# 在原圖上繪制矩形框出人臉
cv2.rectangle(target, (x, y), (x+w, y+h), (255, 0, 0), 2)
# 提取人臉區域并調整到期望大小
face_region = target_gray[y:y+h, x:x+w]
face_resized = cv2.resize(face_region, desired_size)
# 使用EigenFaceRecognizer進行預測
label, confidence = recognizer.predict(face_resized)
# 將識別的名字和置信度打印在圖像上方
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()
測試結果:
雖然打了馬賽克,但是實際上結果是可以置信的。在這里,還可以根據置信程度來對不同的人臉進行篩選,比如不想要的臉或者置信程度不高的臉可以再進行舍棄。
總結
以上是生活随笔為你收集整理的简易机器学习笔记(十一)opencv 简易使用-人脸识别、分类任务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM学习-Class文件结构
- 下一篇: 通过 KernelUtil.dll 劫持