全套 | 人臉檢測 & 人臉關鍵點檢測 & 人臉卡通化
點擊上方“AI算法與圖像處理”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
來源:CVPy

人臉檢測歷險記
可能跟我一樣,人臉檢測是很多人學習圖像處理的第一個自驅動型的任務,OpenCV剛上手沒幾天可能就想先跑一跑人臉檢測,然后一個坑接著一個坑的往里跳。我個人對人臉檢測的大概歷程應該是下面這樣的:
-
找一個直接能執(zhí)行的 OpenCV的人臉檢測程序,直接執(zhí)行看效果。雖然這貌似是最簡單的一步,但是由于最初水平實在太低,所以這一步可能是耗時最長的。當時初學的時候還在用C++,想要直接跑程序,首先你要先配置好環(huán)境!曾經(jīng)因為環(huán)境問題嘗試了不同版本OpenCV未果、重裝VS未果、重裝Windows系統(tǒng)仍未果...當年的環(huán)境配置簡直是不堪回首,說多了都是淚。而且根據(jù)我的經(jīng)驗,不論是因為版本還是還是系統(tǒng)問題,在網(wǎng)上找一個直接拿來就能跑的代碼實在是太難了... -
按照千辛萬苦跑起來的程序,自己敲一遍。明明感覺沒啥差別,為啥就是跑不起來呢...所有的坑都會自己跳進去,所有的低級錯誤都會犯不止一遍。 -
嘗試找數(shù)據(jù)或者標注數(shù)據(jù),嘗試自己訓練一個人臉檢測模型, OpenCV提供了用來訓練的exe,參數(shù)超多,一直感覺很難用...當時可謂是屢敗屢戰(zhàn),屢戰(zhàn)屢敗。 -
找一個能直接執(zhí)行的深度學習的人臉檢測程序,直接執(zhí)行看效果。(雖然這貌似是最簡單的一步,但是由于最初水平實在太低,所以這一步可能是耗時最長的。當時初學的時候還在用 Caffe,想要直接跑程序,首先你要先配置好環(huán)境!Caffe的環(huán)境配置...當年的環(huán)境配置簡直是不堪回首,說多了都是淚。???好像在哪里聽過?) -
同2. -
嘗試找數(shù)據(jù)或者標注數(shù)據(jù),嘗試自己訓練一個人臉檢測模型。 Caffe...對,我當時用的是TensorFlow Object Detection API(當時這個環(huán)境配置過程也很感人)。 -
找一個能直接能用的人臉檢測模型,直接跑起來看看效果....如果不能跑,嘗試改改,也許就該好了呢。 -
跑起來一個人臉檢測模型,加點其他效果?
要不就先看看效果吧,畢竟看到效果才更有動力走下去。【視頻有聲提示!】
上面用的是深度學習模型的人臉檢測,但是在此之前還是稍微回顧下OpenCV自帶的人臉檢測器。
OpenCV自帶的人臉檢測
OpenCV自帶了基于級聯(lián)分類器的人臉檢測模型,只能檢測正臉,在前深度學習時代,效果已經(jīng)是很好的了。OpenCV中的使用方式是用級聯(lián)分類器加載人臉檢測模型,大家一般默認用haarcascade_frontalface_default.xml。這個文件在C++源碼路徑下很容易找到,大概在opencv/sources/data/haarcascades路徑下,Python的話,我用的Anaconda,所以路徑在/Anaconda3/Lib/site-packages/cv2/data/。不同版本想來差異不會太大。
然后用多尺度滑窗法去檢測人臉,函數(shù)參數(shù)含義和代碼示例如下:
直接【執(zhí)行】看效果:【視頻有聲提示!】
基于深度學習的人臉檢測
想要深入學習的小伙伴可以嘗試自己訓練一個人臉檢測模型練手,這里直接在Github上找一個能跑的模型CenterFace。代碼和模型都來自這里https://github.com/Star-Clouds/CenterFace。由于模型是ONNX格式的,所以用OpenCV的readNetFromONNX函數(shù)加載模型centerface.onnx。
摘取主體代碼并注釋如下:
class CenterFace(object):
def __init__(self):
# readNetFromONNX 加載模型
self.net = cv2.dnn.readNetFromONNX(os.path.join(model_path, 'centerface.onnx'))
self.img_h_new, self.img_w_new, self.scale_h, self.scale_w = 0, 0, 0, 0
def __call__(self, img, height, width, threshold=0.5, landmarks=True):
# 圓整圖片大小為32的倍數(shù)
self.img_h_new, self.img_w_new, self.scale_h, self.scale_w = self.transform(height, width)
# 推理,即前向傳播一次
return self.inference_opencv(img, threshold, landmarks)
def inference_opencv(self, img, threshold, landmarks=True):
# 圖像預處理,這里主要是 Reisze 和 BGR2RGB
blob = cv2.dnn.blobFromImage(img, scalefactor=1.0, size=(self.img_w_new, self.img_h_new), mean=(0, 0, 0), swapRB=True, crop=False)
self.net.setInput(blob)
begin = time.time()
# 前向傳播一次
heatmap, scale, offset, lms = self.net.forward(["537", "538", "539", '540'])
end = time.time()
print("dtime = ", end - begin)
# 后處理,主要是根據(jù)閾值 threshold 從輸出獲取人臉框和人臉關鍵點的位置
return self.postprocess(heatmap, lms, offset, scale, threshold, landmarks)
def transform(self, h, w):
# 圓整圖片大小為32的倍數(shù)
img_h_new, img_w_new = int(np.ceil(h / 32) * 32), int(np.ceil(w / 32) * 32)
scale_h, scale_w = img_h_new / h, img_w_new / w
return img_h_new, img_w_new, scale_h, scale_w
這一步模型可以同時給出人臉框和人臉關鍵點的位置。【視頻有聲提示!】
人臉卡通化
僅僅是人臉檢測,顯得略微有些沒意思,所以在人臉檢測的基礎上,加點其他的更有意思的東西,比如上次剛玩過的卡通化。這是國內(nèi)大佬的一篇文章,開源了代碼和模型,在這里:https://github.com/SystemErrorWang/White-box-Cartoonization/。代碼細節(jié)可以到這個鏈接查看,這里只給出人臉檢測之后和卡通化結合部分的代碼:
def face_detect(self, image, landmarks: bool, cartoon: bool):
# 加載模型
centerface = CenterFace()
h, w = image.shape[:2]
# 人臉檢測
dets, lms = centerface(image, h, w, threshold=0.5, landmarks=landmarks)
print("檢測到的人臉:", dets)
if len(dets):
for det in dets:
boxes, score = det[:4], det[4]
x1, y1, x2, y2 = int(boxes[0]), int(boxes[1]), int(boxes[2]), int(boxes[3])
box_w, box_h = x2 - x1, y2 - y1
# 人臉框稍微往外擴一點,個人感覺這么會好一點
face_box = image[max(0, y1 - int(box_h * 0.1)): min(y2 + int(box_h * 0.1), h), max(
0, x1 - int(box_w * 0.1)):min(x2 + int(box_w * 0.1), w)]
if cartoon:
# 人臉卡通化之后
cartoonized_face = cartoonize(face_box)
# 貼回原圖,覆蓋原圖人臉部分
image[max(0, y1 - int(box_h * 0.1)): min(y2 + int(box_h * 0.1), h), max(
0, x1 - int(box_w * 0.1)):min(x2 + int(box_w * 0.1), w)] = cartoonized_face
# 畫出人臉框框
draw_box(image, [x1, y1, x2, y2], color=(0, 255, 255))
# cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 255), min(h, w) // 200)
if landmarks:
for lm in lms:
for i in range(0, 5):
cv2.circle(image, (int(lm[i * 2]), int(lm[i * 2 + 1])),
min(h, w) // 100, (0, 0, 255), -1)
else:
cv2.putText(image, "No Face?", (int(w * 0.1), int(h * 0.1)), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), min(h, w) // 200)
return image
流程如下:
-
先加載 CenterFace的模型(參考上一節(jié)的CenterFace的__init__) -
進行人臉檢測,獲取人臉框和人臉關鍵點的位置 -
稍微擴充下人臉框,進行卡通化操作 -
把卡通化后的人臉貼回原圖中人臉的位置
完整效果
看一下完整的效果吧:【視頻有聲提示!】
結語-玩一下
想要自己嘗試實現(xiàn)的小伙伴,可以按照我給的鏈接找到源碼位置自己跑跑試試。如果想要立刻就體驗一下效果的話,想必你已經(jīng)看出來了,這個人臉檢測 & 卡通化已經(jīng)被我做成了一個體驗網(wǎng)頁了。手機和電腦均可訪問。
-
電腦: http://cvpy.net/studio/cv/func/DeepLearning/face/face_detection/page/ -
手機:掃碼進入體驗,覺得不錯的話,可以給個在看哦。
下載1:動手學深度學習
在「AI算法與圖像處理」公眾號后臺回復:動手學深度學習,即可下載547頁《動手學深度學習》電子書和源碼。該書是面向中文讀者的能運行、可討論的深度學習教科書,它將文字、公式、圖像、代碼和運行結果結合在一起。本書將全面介紹深度學習從模型構造到模型訓練,以及它們在計算機視覺和自然語言處理中的應用。
個人微信(如果沒有備注不拉群!)
請注明:地區(qū)+學校/企業(yè)+研究方向+昵稱

