"""
==================== 訓練臉部數據 ==================
"""
學習要有一種空杯的心態,先跟着來---------------------------------->>>
一、準備臉部圖片:
我們將要檢測的臉部圖片命名爲"姓名_數字編號.jpg"的形式,注意編號不連續,創建一個facePics文件夾專門放圖片的。
完整代碼如下:
# 訓練臉部數據 ===============================================
print('*'*50)
print('\t'*5,'訓練臉部數據程序')
print('*'*50)
import os
import cv2 as cv
import numpy as np
from PIL import Image
# 檢查圖片數據是否存在
array_of_img = []
def read_directory(directory_name):
for filename in os.listdir(directory_name):
img = cv.imread(directory_name + "/" + filename)
array_of_img.append(img)
# 圖片文件夾
directory = os.getcwd()+'\\facePics'
read_directory(directory)
count = len(array_of_img)
if count == 0:
print('facePics文件夾下不存在用於訓練的圖片,將退出!')
input('按任意鍵退出')
quit()
print('開始訓練數據...')
# 人臉檢測器
face_detector=cv.CascadeClassifier('haarcascade_frontalface_default.xml')
# 獲取訓練圖片和對應的標籤id
def getImageAndLabels(path):
# 人臉區域數組
faceSamples=[]
# 圖像id數組
ids=[]
# 合併圖片全路徑名稱存入列表
imgPaths=[os.path.join(path,f) for f in os.listdir(path)]
#print(imgPaths)
# 遍歷列表中的圖片
for impath in imgPaths:
# 打開圖片
PIL_img=Image.open(impath).convert('L') # 轉爲灰度圖
# 將圖像轉換爲數組
img_numpy=np.array(PIL_img,'uint8')
# 將面部圖片數組傳入檢測器,獲取人臉數據
faces=face_detector.detectMultiScale(img_numpy)
# 獲取每張圖片的id
splitStr = os.path.split(impath) # 切分路徑
#print(splitStr) # ('C:\\Users\\Administrator\\Desktop\\python學習筆記\\facePics', '小明_1.jpg')
idStr = splitStr[1].split('.')[0]
idStr = idStr.split('_')[1] # 小明_1
id = int(idStr)
for x,y,w,h in faces:
# 提取人臉
faceSamples.append(img_numpy[y:y+h,x:x+w]) # 二維數組切片:獲取y:y+h行,x:x+w列
ids.append(id)
return faceSamples,ids
if __name__=='__main__':
# 圖片路徑
path='facePics'
# 獲取圖像數組和id標籤數組
faces, ids = getImageAndLabels(path)
# 獲取訓練對象
recognizer = cv.face.LBPHFaceRecognizer_create() # 注:如果報錯可能因爲未安裝contrib(用於訓練數據),嘗試pip install opencv-contrib-python
# 訓練數據
recognizer.train(faces,np.array(ids)) # train(面部數據,圖片id數組)
# 保存文件
recognizer.write('trainer.yml')
print('臉部數據 trainer.yml 訓練成功')
input('按任意鍵退出')
quit()
如果你的機器環境都OK,且程序無誤,那麼運行上述代碼將會生成trainer.yml數據文件。
"""
=================== 攝像頭識別併發出問候音 ==================
"""
二、找一臺有攝像頭的機器,運行以下代碼,將開啓人臉識別模式
完整代碼如下:
# 檢測視頻人臉 ========================================================================
import os
from win32com.client import Dispatch
print(os.getcwd()) # 獲得當前目錄
print('================================= 人臉識別程序 ==============================')
_input=input('按任意鍵開始!')
# 檢查訓練數據是否存在
exist = os.path.exists(os.getcwd()+'\\trainer.yml');
if not exist: # 文件不存在
print('訓練數據 trainer.yml 不存在,系統將退出!')
input('請按任意鍵退出')
quit()
# 獲取所有圖片的id和對應名稱
names={}
#{1:'貝提',1:'魯姆',1:'傑米',1:'大衛',1:'米妮'}
def getNamesDic(imgPaths):
for impath in imgPaths:
# 獲取每張圖片的id
splitStr = os.path.split(impath) # 切分路徑
#print(splitStr) # ('C:\\Users\\Administrator\\Desktop\\python學習筆記\\facePics', '小明_1.jpg')
fulnam = splitStr[1].split('.')[0] # 小明_1
idStr = fulnam.split('_')[1] # 1
nam = fulnam.split('_')[0] # 小明
id = int(idStr)
names[id] = nam
imgPaths = []
def read_directory(directory_name):
for filename in os.listdir(directory_name):
picname = directory_name + "/" + filename
imgPaths.append(picname)
# 圖片文件夾
directory = os.getcwd()+'\\facePics'
read_directory(directory)
getNamesDic(imgPaths)
# 使用文字轉語音功能,發出問候音:xx,你好!
def welcome(id):
msg='你好,'+str(id)
speaker=Dispatch('SAPI.SpVoice')
speaker.Speak(msg)
del speaker
# cv2.VideoCapture(0)代表調取攝像頭資源,其中0代表電腦攝像頭,1代表外接攝像頭(usb攝像頭)
# cap.read()按幀讀取視頻,ret,frame是獲cap.read()方法的兩個返回值。其中ret是布爾值,
# 如果讀取幀是正確的則返回True,如果文件讀取到結尾,它的返回值就爲False,如果沒有攝像頭則返回False。frame就是每一幀的圖像,是個三維矩陣。
print('正在打開攝像頭...')
cap = cv.VideoCapture(0) # 調用自己的攝像頭
ret,frame = cap.read()
if not ret:
cap = cv.VideoCapture(1)
ret,frame = cap.read()
if not ret:
print('未發現電腦攝像頭,或未能打開攝像頭,將進行本地視頻人臉識別') # False
cap = cv.VideoCapture('video.mkv')
ret,frame = cap.read()
if not ret:
quit()
def face_detect_demo(img):
#print(type(img)) # <class 'numpy.ndarray'>
# 將圖片灰度
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 加載訓練數據集文件
recognizer = cv.face.LBPHFaceRecognizer_create()
recognizer.read('trainer.yml')
# 加載特徵數據
# 'D:\\opencv_3.4.7\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml'
#
face_detector = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = face_detector.detectMultiScale(gray)
for x,y,w,h in faces:
cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
# 識別是哪一個
id,confidence=recognizer.predict(gray[y:y+h,x:x+w])
# 播放歡迎語音...
if confidence<50:
print('標籤id:',id,' 置信評分:',confidence,end='\t')
print('你好,',names[id])
# 在人臉下畫一個有名字的標籤;cv2.putText 不支持中文所以這裏換一種方法
cv.putText(img, str(id), (x,y), cv.FONT_HERSHEY_SIMPLEX, 1.0, (255, 255, 255), 1) # 圖像,文字內容, 座標 ,字體,大小,顏色,字體厚度
##font=ImageFont.truetype('msyh.ttc',20) # 微軟雅黑20號字體,此處未指定路徑會從Windows字體目錄查找
##img_pil = Image.fromarray(img)
##draw = ImageDraw.Draw(img_pil)
##d#raw.text( (x,y), names[id], font=font, fill=(255, 255, 255))
##frame = np.array(img_pil)
welcome(names[id])
cv.imshow('result',img)
print('加載人臉特徵數據...')
while True:
flag,frame=cap.read()
#print('flag: ',flag,'frame.shape: ',frame.shape) # flag: True frame.shape: (720, 1280, 3)
if not flag:
break
# 將視頻幀的大小調整爲1/2以加快人臉識別處理
#frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5)
face_detect_demo(frame)
if ord('q') == cv.waitKey(10):
break
cv.destroyAllWindows() # 釋放內存
cap.release() # 清理空間
如果攝像頭識別到相似度高的人臉,將啓動問候音:“xx,你好!”
特別注意:安裝的opencv的版本和python的版本都需要考慮到,不然會很麻煩!我們需要將臉部數據特徵xml文件,和訓練出來的數據yml文件放好位置;
最後鏈接附上源碼和相關資源
注:(由於CSDN有上傳文件大小限制,我打包好的exe可執行程序就不上傳了,需要加微信:2463954659)