Haar Cascade
功能說明
哈爾特徵(haar cascade)是目前檢測人臉的流行算法之一,可以用來檢視臉部、眼睛、鼻子、耳朵等,它的計算成本較低,算法速度快,並且精度高。
OpenCV 帶有許多預訓練的分類器。這些 haar-cascade的xml文件可以通過 cv2 模塊的 cascadeClassifier 方法加載。
Haar級聯預訓練的模型
OpenCV包含預先訓練好的Haar聯集模型,包括:
haarcascade_frontalface_default.xml:檢測臉部
haarcascade_frontalface_alt.xml:檢測臉部
haarcascade_frontalface_alt2.xml:檢測臉部
haarcascade_frontalface_alt_tree.xml:檢測臉部
haarcascade_eye.xml:檢測左眼和右眼
haarcascade_smile.xml:檢測面部是否存在嘴部
haarcascade_eye_tree_eyeglasses.xml:檢測是否帶墨鏡
haarcascade_frontalcatface.xml:檢測貓臉
haarcascade_frontalcatface_extended.xml:檢測貓臉延伸
haarcascade_fullbody.xml:檢測全身
haarcascade_lefteye_2splits.xml:檢測左眼
haarcascade_licence_plate_rus_16stages.xml
haarcascade_lowerbody.xml:檢測下半身
haarcascade_profileface.xml:檢測證件
haarcascade_righteye_2splits.xml:檢測右眼
haarcascade_russian_plate_number.xml:檢測俄羅斯字母車牌號
haarcascade_upperbody.xml:檢測上半身
其中關於正面人臉分類器就包含了4個,alt、alt2、alt_tree、default。有網友針對這4個分類器進行了實驗,發現對比下來發現alt和alt2的效果比較好,alt_tree耗時較長,default是一個輕量級的,經常出現誤檢測。針對alt和alt2兩者,在同一個視頻的對比中檢測部分alt要略微好於alt2。
語法1:
detector = cv2.CascadeClassifier(xml分類器路徑)
語法2:
cv.CascadeClassifier.detectMultiScale(image,objects,scaleFactor = 1.1, minNeighbors = 3,flags = 0,minSize = Size(),maxSize = Size() )
參數1:image–待檢測圖片,一般為灰度圖像加快檢測速度;
參數2:objects–被檢測物體的矩形框向量組;
參數3:scaleFactor–表示在前後兩次相繼的掃描中,搜索窗口的比例係數。預設為1.1即每次搜索窗口依次擴大10%。 由於某些人臉可能離相機更近,因此它們看起來會比後面的人臉大。 比例因數對此進行了補償。
參數4:minNeighbors–表示構成檢測目標的相鄰矩形的最小個數(預設為3個)。如果組成檢測目標的小矩形的個數和小於min_neighbors - 1 都會被排除。如果min_neighbors 為0, 則函數不做任何操作就返回所有的被檢候選矩形框。
參數5:flags–使用預設值或使用CV_HAAR_DO_CANNY_PRUNING,函數將會使用Canny邊緣檢測來排除邊緣過多或過少的區域, 因為這些區域通常不會是人臉所在區域。
參數6、7:minSize和maxSize用來限制得到的目標區域的範圍。如果視頻中誤檢到很多無用的小方框,那麼就把minSize的尺寸改大一些,預設為30*30。
官方下載連結:
https://github.com/opencv/opencv/tree/master/data/haarcascades
程式範例:照片人臉辨識
#載入OpenCV函式庫
import cv2
#讀取照片資料
img = cv2.imread('pic.jpg')
#將照片轉成灰階,加快辨識速度
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#載入需要的Haar檔案
haar_cascade = cv2.CascadeClassifier('/home/pi/.local/lib/python3.9/site-packages/cv2/data/haarcascade_frontalface_alt.xml')
#人臉檢測,1.1和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
faces_rect = haar_cascade.detectMultiScale(gray_img, 1.1, 3)
#匡列人臉
for (x, y, w, h) in faces_rect:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
#顯示影像
cv2.imshow('Detected faces', img)
#保存圖片
#cv2.imwrite( "result.jpg", img )
#給定的時間內(單位毫秒)等待使用者的按鍵觸發,否則持續循環
cv2.waitKey(0)
程式範例:影片人臉辨識
import cv2
def CatchVideo(window_name):
#只有一個鏡頭就填0,兩個鏡頭填0或1(選鏡頭)
cap = cv2.VideoCapture(0)
#也可以讀取影片
#cap = cv2.VideoCapture("filename")
#告訴OpenCV使用人臉識別分類器
classfier_path='/home/pi/.local/lib/python3.9/site-packages/cv2/data/'
classfier = cv2.CascadeClassifier(classfier_path + 'haarcascade_frontalface_alt.xml')
#識別出人臉後要畫的邊框的顏色,RGB格式
facecolor = (0, 255, 0)
while True:
#讀取鏡頭資料,ret為成功與否的回傳值,frame為影格
ret, frame = cap.read()
#如果讀取錯誤就停止
if ret==False:
break
#將當前影格轉換成灰階,加快辨識速度
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#人臉檢測,1.1和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.1, minNeighbors = 3, minSize = (32, 32))
#大於0則檢測到人臉
if len(faceRects) > 0:
#單獨框出每一張人臉
for x, y, w, h in faceRects:
cv2.rectangle(frame, (x, y ), (x + w ,y + h), facecolor, 2)
#顯示影像
cv2.imshow(window_name, frame)
#10 ms等待使用者的按鍵觸發,否則持續循環,如果輸入為q則停止
if cv2.waitKey(10) & 0xFF == ord('q'):
break
#釋放鏡頭
cap.release()
#關閉視窗
cv2.destroyAllWindows()
if __name__ == '__main__':
CatchVideo("Vedio")
程式範例:照片臉部各部位辨識
#載入OpenCV函式庫
import cv2
#讀取照片資料
img = cv2.imread('pic_o.jpg')
#調整圖片尺寸
#img = cv2.resize(img, (900,600))
#將照片轉成灰階,加快辨識速度
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#載入需要的Haar檔案
classfier_path='/home/pi/.local/lib/python3.9/site-packages/cv2/data/'
classfier_face = cv2.CascadeClassifier(classfier_path + 'haarcascade_frontalface_alt2.xml')
classfier_eye = cv2.CascadeClassifier(classfier_path + 'haarcascade_eye.xml')
#classfier_mouse = cv2.CascadeClassifier(classfier_path + 'haarcascade_smile.xml')
#人臉檢測,1.1和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
faces_rect = haar_face.detectMultiScale(gray_img, 1.1, 3)
#迴圈檢測人臉
for (fx, fy, fw, fh) in faces_rect:
#將面部範圍切出來,再進一步檢測眼睛或其他
gray_face = gray_img[fy:(fy+fh), fx:(fx+fw)]
#眼睛檢測,1.1和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
eyes_rect = haar_eye.detectMultiScale(gray_face, 1.1, 3)
#mouse_rect = haar_mouse.detectMultiScale(gray_face, 1.1, 3)
#繪製臉部方框
cv2.rectangle(img, (fx, fy), (fx+fw, fy+fh), (0, 255, 0), 2)
#加入說明文字
cv2.putText(img, "face", (fx, fy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
#繪製眼睛方框
for (ex, ey, ew, eh) in eyes_rect:
cv2.rectangle(img, (fx+ex, fy+ey), (fx+ex+ew, fy+ey+eh), (0, 0, 255), 2)
#加入說明文字
cv2.putText(img, "eye", (fx+ex, fy+ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
'''
for (mx, my, mw, mh) in mouse_rect:
cv2.rectangle(img, (fx+mx, fy+my), (fx+mx+mw, fy+my+mh), (255, 0, 0), 2)
'''
#顯示影像
cv2.imshow('Detected faces', img)
#保存圖片
#cv2.imwrite( "result.jpg", img )
#給定的時間內(單位毫秒)等待使用者的按鍵觸發,否則持續循環
cv2.waitKey(0)
程式範例:影片臉部各部位辨識
import cv2
def CatchVideo(window_name):
#只有一個鏡頭就填0,兩個鏡頭填0或1(選鏡頭)
cap = cv2.VideoCapture(0)
#也可以讀取影片
#cap = cv2.VideoCapture("filename")
#告訴OpenCV使用人臉識別分類器
classfier_path='/home/pi/.local/lib/python3.9/site-packages/cv2/data/'
classfier_face = cv2.CascadeClassifier(classfier_path + 'haarcascade_frontalface_alt2.xml')
classfier_eye = cv2.CascadeClassifier(classfier_path + 'haarcascade_eye.xml')
#classfier_mouse = cv2.CascadeClassifier(classfier_path + 'haarcascade_smile.xml')
#識別出人臉後要畫的邊框的顏色,RGB格式
facecolor = (0, 255, 0)
eyecolor=(0,0,255)
mousecolor=(255,0,0)
while True:
#讀取鏡頭資料,ret為成功與否的回傳值,frame為影格
ret, frame = cap.read()
#如果讀取錯誤就停止
if ret==False:
break
#將當前影格轉換成灰階,加快辨識速度
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#人臉檢測,1.2和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
haar_face = classfier_face.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
#大於0則檢測到人臉
if len(haar_face) > 0:
#單獨框出每一張人臉
for fx, fy, fw, fh in haar_face:
#將面部範圍切出來,再進一步檢測眼睛或其他
grey_face = grey[fy:(fy+fh), fx:(fx+fw)]
#繪製臉部方框
cv2.rectangle(frame, (fx, fy ), (fx + fw ,fy + fh), facecolor, 2)
#加入說明文字
cv2.putText(frame, "face", (fx, fy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, facecolor, 2)
#眼睛檢測,1.2和3分別為圖片縮放比例和需要檢測到多少有效數量才保留
harr_eyes = classfier_eye.detectMultiScale(grey_face, 1.2, 3)
#mouse_rect = haar_mouse.detectMultiScale(grey_face, 1.1, 3)
#繪製眼睛方框
for (ex, ey, ew, eh) in harr_eyes:
cv2.rectangle(frame, (fx+ex, fy+ey), (fx+ex+ew, fy+ey+eh), eyecolor, 2)
#加入說明文字
cv2.putText(frame, "eye", (fx+ex, fy+ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.4, eyecolor, 1)
'''
for (mx, my, mw, mh) in mouse_rect:
cv2.rectangle(frame, (fx+mx, fy+my), (fx+mx+mw, fy+my+mh), (255, 0, 0), 2)
'''
#顯示影像
cv2.imshow(window_name, frame)
#10 ms等待使用者的按鍵觸發,否則持續循環,如果輸入為q則停止
if cv2.waitKey(10) & 0xFF == ord('q'):
break
#釋放鏡頭
cap.release()
#關閉視窗
cv2.destroyAllWindows()
if __name__ == '__main__':
CatchVideo("Vedio")
OpenCV官方範例
#!/usr/bin/env python
'''
face detection using haar cascades
USAGE:
facedetect.py [--cascade <cascade_fn>] [--nested-cascade <cascade_fn>] [<video_source>]
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# local modules
from video import create_capture
from common import clock, draw_str
def detect(img, cascade):
rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30),
flags=cv.CASCADE_SCALE_IMAGE)
if len(rects) == 0:
return []
rects[:,2:] += rects[:,:2]
return rects
def draw_rects(img, rects, color):
for x1, y1, x2, y2 in rects:
cv.rectangle(img, (x1, y1), (x2, y2), color, 2)
def main():
import sys, getopt
args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade='])
try:
video_src = video_src[0]
except:
video_src = 0
args = dict(args)
cascade_fn = args.get('--cascade', "data/haarcascades/haarcascade_frontalface_alt.xml")
nested_fn = args.get('--nested-cascade', "data/haarcascades/haarcascade_eye.xml")
cascade = cv.CascadeClassifier(cv.samples.findFile(cascade_fn))
nested = cv.CascadeClassifier(cv.samples.findFile(nested_fn))
cam = create_capture(video_src, fallback='synth:bg={}:noise=0.05'.format(cv.samples.findFile('samples/data/lena.jpg')))
while True:
_ret, img = cam.read()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray = cv.equalizeHist(gray)
t = clock()
rects = detect(gray, cascade)
vis = img.copy()
draw_rects(vis, rects, (0, 255, 0))
if not nested.empty():
for x1, y1, x2, y2 in rects:
roi = gray[y1:y2, x1:x2]
vis_roi = vis[y1:y2, x1:x2]
subrects = detect(roi.copy(), nested)
draw_rects(vis_roi, subrects, (255, 0, 0))
dt = clock() - t
draw_str(vis, (20, 20), 'time: %.1f ms' % (dt*1000))
cv.imshow('facedetect', vis)
if cv.waitKey(5) == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
相關連結
教學推薦:https://pyimagesearch.com/2021/04/12/opencv-haar-cascades/
官方文件:
https://www.geeksforgeeks.org/face-detection-using-cascade-classifier-using-opencv-python/
http://www.codebaoku.com/it-python/it-python-222465.html
metadatahttps://www.tensorflow.org/lite/convert/metadata
cv2.waitkey是OpenCV內置的函式,用途是在給定的時間內(單位毫秒)等待使用者的按鍵觸發,否則持續循環。
0xFF是十六進制常數,二進制值為11111111。這個寫法只留下原始的最後8位,和後面的ASCII碼對照——不必深入理解,此處是為了防止BUG。
ord(' ')可以將字符轉化為對應的整數(ASCII碼)。
如上面的判斷式——如果使用者没有按下q键,就會持續等待(循環),直到觸發後執行break跳出迴圈。