天天看點

基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

導讀

本文給大家分享一個基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效的執行個體,并附實作步驟和源碼。(公衆号:OpenCV與AI深度學習)

 背景介紹

    OpenCV傳統人臉檢測是使用Haar特征的級聯分類器實作的。Harr級聯是一個基于Haar特征的級聯分類器。級聯分類器是什麼?它是一個把弱分類器串聯成強分類器的過程。弱分類器和強分類器分别是什麼呢?弱分類器是性能受限的分類器,它們沒法正确地區分所有事物。如果你的問題很簡單,它的輸出結果會在一個可以接受的範圍内。強分類器可以正确地對資料進行分類。下圖展示了它們是如何組合在一起的。Haar級聯的另一個重要部分是Haar特征,這些特征簡單地總結了不同的長方形區域的差別,如下圖所示:

基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

    計算ABCD區域的Haar特征,隻需要計算這個區域白色像素和有色像素的差別。在上面四張圖表中使用了不同的圖案建立Haar 特征,同時其他圖案也被使用了。這些圖案使用了多重尺度法以確定系統的拉伸是不變的。多重尺度法指把圖像縮小再次計算同樣的特征。這樣可以在給出對象大小有差異的時候候,獲得一個可靠的結果。

檢測、鼻子檢測和身體檢測等,如下圖所示:

基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

比如使用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)      
基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

 實作步驟

【1】準備面具圖檔并處理成透明背景

基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

【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---眼睛檢測

實作效果:

基于OpenCV實作簡單人臉面具、眼鏡、胡須、鼻子特效(詳細步驟 + 源碼)

完整C++ OpenCV源碼請在公衆号背景回複人臉面具擷取。