導讀
本文給大家分享一個基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效的執行個體,并附實作步驟和源碼。(公衆号:OpenCV與AI深度學習)
背景介紹
OpenCV傳統人臉檢測是使用Haar特征的級聯分類器實作的。Harr級聯是一個基于Haar特征的級聯分類器。級聯分類器是什麼?它是一個把弱分類器串聯成強分類器的過程。弱分類器和強分類器分别是什麼呢?弱分類器是性能受限的分類器,它們沒法正确地區分所有事物。如果你的問題很簡單,它的輸出結果會在一個可以接受的範圍内。強分類器可以正确地對資料進行分類。下圖展示了它們是如何組合在一起的。Haar級聯的另一個重要部分是Haar特征,這些特征簡單地總結了不同的長方形區域的差別,如下圖所示:
計算ABCD區域的Haar特征,隻需要計算這個區域白色像素和有色像素的差別。在上面四張圖表中使用了不同的圖案建立Haar 特征,同時其他圖案也被使用了。這些圖案使用了多重尺度法以確定系統的拉伸是不變的。多重尺度法指把圖像縮小再次計算同樣的特征。這樣可以在給出對象大小有差異的時候候,獲得一個可靠的結果。
檢測、鼻子檢測和身體檢測等,如下圖所示:
比如使用haarcascade_frontalface_alt.xml,我們可以很快實作一個人臉檢測功能:
#公衆号:OpenCV與AI深度學習
import sys
import numpy as np
import cv2
#加載xml分類器檔案
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
font = cv2.FONT_HERSHEY_SIMPLEX
def face_detect(img):
strText=""
cv2.imshow('原圖', img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#轉為灰階圖
#gray = cv2.equalizeHist(gray)#直方圖均衡化
#人臉檢測
faces = face_cascade.detectMultiScale(gray,1.1,2,0|cv2.CASCADE_SCALE_IMAGE,(30,30))#OpenCV3.x
for (x,y,w,h) in faces: #周遊檢測結果
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)#框出人臉區域
#cv2.circle(img,(int(x+w/2),int(y+h/2)),int(w/2),(0,255,0),3)
face_num = len(faces)
if face_num==0:
print ("There is no face!")
strText="There is no face!"
elif face_num==1:
print ("There is 1 face!")
strText="There is 1 face!"
else:
print ("There are %s faces!"%face_num)
strText="There are %s faces!"%face_num
cv2.putText(img, strText, (20,30), font, 1, (0,0,255), 2)
cv2.imshow('結果圖',img)
print ('Finished')
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
img = cv2.imread('./pics/5.jpg')
face_detect(img)
實作步驟
【1】準備面具圖檔并處理成透明背景
【2】人臉檢測并确定人臉ROI
【3】将面具圖檔縮放到人臉ROI大小,并對Alpha通道門檻值提取分離面具部分
Mat faceMask = imread("./mask/mask2.png", -1);
if (faceMask.empty())
{
cerr << "Error loading mask image. Exiting!" << endl;
return -1;
}
Mat alpha, channels[4];
split(faceMask, channels);
alpha = channels[3];
threshold(alpha, alpha, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("thresMask", alpha);
cout << alpha.channels() << endl;
vector<Mat>bgrImg;
bgrImg.push_back(channels[0]);
bgrImg.push_back(channels[1]);
bgrImg.push_back(channels[2]);
merge(bgrImg, faceMask);
waitKey();
【4】用Mat的copyTo方法将面具貼到人臉部分
faceMaskResized.copyTo(faceROI, grayMaskResized)
【5】擴充到眼鏡、胡須和鼻子特效:
haarcascade_frontalface_alt.xml---人臉檢測
haarcascade_smile.xml---嘴唇檢測
haarcascade_mcs_nose.xml---鼻子檢測
haarcascade_eye.xml---眼睛檢測
實作效果:
完整C++ OpenCV源碼請在公衆号背景回複人臉面具擷取。