opencv3 人臉檢測和識別
阿新 • • 發佈:2019-01-08
人臉部檢測
輸入:face_detection_still.py
import cv2 from skimage import io filename = 'people.jpg' def detect(filename): face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./cascades/cascadeshaarcascade_eye.xml') img = cv2.imread(filename) #gray = io.imread(r"D:\F\eclipse-workspace\imagop\src\faces\vikings.jpg",as_grey=True) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #faces = face_cascade.detectMultiScale(gray, 1.3, 5) faces = face_cascade.detectMultiScale(gray, 1.3, 9) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) cv2.namedWindow('Vikings Detected!!') img = cv2.resize(img, (900, 900), interpolation=cv2.INTER_CUBIC) cv2.imshow('Vikings Detected!!', img) cv2.imwrite('./vikings.jpg', img) cv2.waitKey(0) detect(filename)
輸出:
檢測人的臉部和眼睛
''' Created on 2018年7月1日 @author: hcl ''' import cv2 def detect(): face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml') camera = cv2.VideoCapture(0) while (True): ret,frame = camera.read() gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3, 5) #檢測人臉,注意要轉換成灰度圖 1.3表示壓縮率 5表示保留近鄰數目的最小值 for (x,y,w,h) in faces: img = cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h,x:x+w] roi_color = img[y:y+h,x:x+w] eyes = eye_cascade.detectMultiScale(roi_gray,1.03,5,0,(40,40))#,0 #在上檢測的人臉中檢測眼睛 40*40限制對眼睛搜尋的的最小尺寸 for (ex,ey,ew,eh) in eyes: cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)#書上用的是img 會有問題 cv2.imshow('camera',frame) if cv2.waitKey(5) & 0xff == ord('q'): break camera.release() cv2.destroyAllWindows() if __name__ == "__main__": detect()
輸出:臉部能準確圈出,但是眼部只能圈出未佩戴眼鏡者
開啟攝像頭在檢測的人臉中顯示姓名
1、首先獲取人臉特徵資料:
import cv2 def generate(): face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml') # 開啟攝像頭 camera = cv2.VideoCapture(0) count = 0 while (True): ret, frame = camera.read() print(ret) # 把攝像頭的每一幀影象轉換成灰度影象,這時書上就比較亂了 # 有用cv2.cvtColor(frame, 1)也有用下面的,其實都一樣 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 檢測人臉 faces = face_cascade.detectMultiScale(gray, 1.3, 5) # 接下來就是迴圈儲存圖片了 for (x, y, w, h) in faces: # 先畫一個正方形,這很簡單 img = cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2) # 接下來把影象全部格式化成200x200畫素 f = cv2.resize(gray[y: y+h, x:x+w], (200, 200)) # 儲存圖片為opencv專用的*.pgm格式 cv2.imwrite('./data/hcl/%s.pgm' % str(count), f) count += 1 cv2.imshow("camera", frame) if cv2.waitKey(int(1000/12)) & 0xff == ord("q"): break # 釋放攝像頭控制代碼 camera.release() # 銷燬視窗,這句很重要 cv2.destroyAllWindows() # 開始執行 if __name__ == "__main__": generate()
2、驗證資料人臉特徵資料是否生成
import cv2
# 開啟1.pgm檔案,並儲存為灰度影象
img = cv2.imread('./data/hcl/1.pgm', cv2.IMREAD_GRAYSCALE)
print (img)
# 在名為img的視窗上顯示圖片,畫素為200x200
cv2.imshow('img',img)
cv2.waitKey()
在執行程式中,安裝了opencv的補充包opencv_contrib_python-3.4.1.15-cp36-cp36m-win_amd64.whl,在https://pypi.org/project/opencv-contrib-python/#files下載適合自己電腦安裝版本的包,然後再再anaconda中安裝pip install D:\F\Anaconda3\Lib\opencv_contrib_python-3.4.1.15-cp36-cp36m-win_amd64.whl即可
3、真正進入人臉識別
三種實現方式:EigenFace、FisherFace、LBPHFace
import os
import sys
import cv2
import numpy as np
# 圖片的路徑
filepath = './data/hcl/'
# 定義2個數組,X存放每幅圖片的陣列列表,y存放每幅圖片的序號,後面有句print函式
# 可以在IDLE裡看哪張圖片特徵最匹配實時檢測到的臉,並給出置信度
X = []
y = []
# 顧名思義,讀取特徵圖片
def read_images(path):
# 初始化計數器
c = 0
# 掃描路徑下的路徑名,檔名,不明白的可以在下面print一下
for dirname, dirnames, filenames in os.walk(path):
# print dirname, dirnames, filename
# 提取每個檔案並儲存到X,y數組裡,這裡做了點改動,因為我的特徵圖片路徑沒有書上程式碼那麼深
for filename in filenames:
try:
# 組合路徑和檔名,得到特徵圖的絕對路徑D:\F\eclipse-workspace\imagop\src\faces\data\hcl\1.pgm
filename = os.path.join(path, filename)
# 把特徵圖以灰度圖讀取
im = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
# 重新格式化圖片為200x200畫素,原書估計打錯字了
if (im is not None):
im = cv2.resize(im, (200, 200))
# 把特徵圖片陣列新增到X陣列中,組成一個大的特徵陣列
X.append(np.asarray(im, dtype=np.uint8))
y.append(c)
# 輸入輸出錯誤檢查
# except IOError, (errno, strerror):
# print "I/O error({0}): {1}".format(errno, strerror)
except:
print ("Unexpected error:", sys.exc_info()[0])
raise
c = c + 1
#print X
#print y
# 估計到這,這陣列的維度大得嚇人了
return [X, y]
# 顧名思義,人臉檢測開始了
def face_rec():
# 定義一個名字的陣列,隨便瞎打幾個英文字母,等會下面會用到
#names = ['hcl', 'ln', 'hn']
names = ['hcl' for i in range(20)]
# 載入特徵圖片
[x, y] = read_images(filepath)
# 把y陣列儲存為int32格式的陣列,用asarry()不用開闢新的記憶體,其實array()函式也可以,現在誰的電腦記憶體沒個幾G啊
y = np.asarray(y, dtype=np.int32)
# 載入EigenFaceRecognizer演算法,這裡必須改為EigenFaceRecognizer_create,原書createEigenFaceRecognizer
# 需要安裝opencv擴充套件庫,基礎庫只能做到人臉識別,但是分不清是誰, pip install opencv-contrib-python
#這裡面是3中不同的人臉識別方法
model = cv2.face.EigenFaceRecognizer_create()
#model = cv2.face.FisherFaceRecognizer_create()
#model = cv2.face.LBPHFaceRecognizer_create()
# 訓練資料集,貌似機器學習,好高深,不深究
model.train(np.asarray(X), np.asarray(y))
# 和第一步裡generate()裡的用法一樣,懶得解釋了
face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')
camera = cv2.VideoCapture(0)
while (True):
read, img = camera.read()
faces = face_cascade.detectMultiScale(img, 1.3, 5)
for (x, y, w, h) in faces:
img = cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
roi = gray[x: x+w, y: y+h]
try:
# 選出感興趣的區域,使用內插法,還是老規矩自行百度
roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
# 預測實時圖片,這裡老衲也沒看明白,下次有時間去看看EigenFaceRecognizer的方法
params = model.predict(roi)
print(params)
# 把匹配的特徵和置信度列印在IDLE內
print ("Label: %s, Confidence: %.2f" % (params[0], params[1]))
# 把匹配的名字顯示在方框左上角,有時候會瞎顯示,以後研究,還有就是現在無法顯示中文字元,也以後吧 :P
#後期可以把所有不同人的照片放到一個資料夾內,然後利用 姓名+計數 命名,然後通過對params[0]進行分割 去除數字 留下姓名 這樣就可以做到識別多人了
cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
except:
continue
cv2.imshow("camera", img)
if cv2.waitKey(int(1000 / 12)) & 0xff == ord("q"):
break
cv2.destroyAllWindows()
if __name__ == "__main__":
face_rec()
識別不同人臉思路:後期可以把所有不同人的照片放到一個資料夾內,然後利用 姓名+計數 命名,然後通過對params[0]進行分割 去除數字 留下姓名 這樣就可以做到識別多人了