步驟:
- 準備人臉:用CascadeClassifier的haarcascade_frontalface_alt.xml模型來辨frame中的人臉,將人臉的擷取下來.
- 準備面具:讀入面具圖檔,將面具reshape成與擷取的人臉一樣大,把面具變成灰階,把面具變成兩階mask,把面具用cv2.bitwise_and()取出來.
- 把mask反tone,把人臉用cv2.bitwise_and()取出來.
- 把步驟2-3做好的面具和人臉用cv2.add()拼貼再一起,在放回frame中.
程式碼:
- import cv2
- import numpy as np
- from PIL import *
- from pylab import *
- #載入辨識人臉的classifier
- face_cascade = cv2.CascadeClassifier('./cascade_files/haarcascade_frontalface_alt.xml')
- if face_cascade.empty():
- raise IOError('Unable to load the face cascade classifier xml file')
- #載入面具
- face_mask = cv2.imread('./images/mask_hannibal.png')
- h_mask, w_mask = face_mask.shape[:2]
- #設定攝影機
- cap = cv2.VideoCapture(1)
- scaling_factor = 0.5
- while True:
- ret, frame = cap.read()
- #把讀入的frame做縮放
- frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)
- #辨識人臉
- face_rects = face_cascade.detectMultiScale(frame, scaleFactor=1.3, minNeighbors=3)
- #用for迴圈讀取辨識的人臉
- for (x,y,w,h) in face_rects:
- if h <= 0 or w <= 0: pass
- #微調要擷取的人臉範圍(需要和mask對齊)
- h, w = int(1.4*h), int(1.0*w)
- y -= int(0.1*h)
- x = int(x)
- # 擷取frame中的人臉
- frame_roi = frame[y:y+h, x:x+w]
- #把面具 resize成擷取的人臉大小
- face_mask_small = cv2.resize(face_mask, (w, h), interpolation=cv2.INTER_AREA)
- # 把面具轉換成灰階
- gray_mask = cv2.cvtColor(face_mask_small, cv2.COLOR_BGR2GRAY)
- #把面具轉換成二階圖(binary)
- ret, mask = cv2.threshold(gray_mask, 180, 255, cv2.THRESH_BINARY_INV)
- mask=mask.astype('uint8')
- #建立反tone的mask
- mask_inv = cv2.bitwise_not(mask).astype('uint8')
- # 把面具用mask擷取出來
- masked_face = cv2.bitwise_and(face_mask_small, face_mask_small, mask=mask)
- # 把人臉用用反tone的mask擷取出來
- masked_frame = cv2.bitwise_and(frame_roi, frame_roi, mask=mask_inv)
- # 把擷取出的面具和人臉合併,並且拼貼回原來的frame中
- frame[y:y+h, x:x+w] = cv2.add(masked_face, masked_frame)
- cv2.imshow('Face Detector', frame)
- c = cv2.waitKey(1)
- if c == 27:
- break
- cap.release()
- cv2.destroyAllWindows()
結果: