0. 引言
利用 Python 開發,借助 Dlib 庫進行人臉檢測 / face detection 和剪切;
1. crop_faces_show.py :
將檢測到的人臉剪切下來,依次排序平鋪顯示在新的圖像上;
實現的效果如 圖1 所示,將 圖1 原圖中的 6 張人臉檢測出來,然后剪切下來,在圖像窗口中依次輸出顯示人臉;
2. crop_faces_save.py :
將檢測到的人臉存儲為單個人臉圖像;
圖 1 原圖 和 crop_faces_show.py 處理后得到的平鋪人臉圖像窗口
圖 2 crop_faces_save.py 處理后得到的多個單張人臉圖像文件
源碼上傳到了我的 Github;
如果對您有幫助或者感興趣,歡迎 Star 支持下: https://github.com/coneypo/Dlib_face_cut
1. 開發環境
Python: 3.6.3
Dlib: 19.7
OpenCv, NumPy
import dlib # 人臉檢測的庫 Dlib import numpy as np # 數據處理的庫 numpy import cv2 # 圖像處理的庫 OpenCv
2. 實現過程
工作內容主要以下兩大塊:Dlib 人臉檢測 和 處理檢測到的人臉圖像
2.1 Dlib 人臉檢測
利用已經訓練好的 Dlib 正向人臉檢測器 detector = dlib.get_frontal_face_detector() 進行人臉檢測;
可以得到人臉外接矩形的坐標,用來之后進行裁剪;
具體 Dlib 的使用,請參考我另一篇博客;
( link: Python 3 利用 Dlib 19.7 進行人臉檢測);
1 # Dlib 檢測器 2 detector = dlib.get_frontal_face_detector() 3 4 # 讀取圖像 5 path = "/***/image_path/" 6 img = cv2.imread(path+"test_faces.jpg") 7 # print("img/shape:", img.shape) 8 9 # Dlib 檢測 10 faces = detector(img, 1) 11 12 print("人臉數:", len(faces))
2.2 繪制新圖像
如果你想讓檢測出來的人臉並排顯示的話,需要遍歷兩次( for k, d in enumerate (faces) ):
第一次遍歷:記錄下我們需要生成的圖像窗口的大小,因為需要將多張照片顯示在一張圖像上,所以需要知道每張人臉照片的大小;
第二次遍歷:根據之前得到的圖像尺寸新建空白圖像,然后開始用人臉矩形填充圖像;
2.2.1 確定空白圖像尺寸
( 這部分首先要根據檢測到的人臉數和人臉大小,來確定繪制圖像所需要的尺寸)
第一次遍歷:多張人臉要輸出到一行,所以先進行一次人臉的遍歷j記下每張人臉的大小,記每張人臉的尺寸為 [ 高度 height * 寬度 width ](高度和寬度說明見 圖 3 ):
圖 3 圖像尺寸說明
我取的生成空白圖像的尺寸:height_max(最大高度)和 width_sum(寬度之和),然后根據尺寸大小來新建空白圖像:
img_blank = np.zeros((height_max, width_sum, 3), np.uint8)
圖 4 圖像尺寸 height_max 和 width_sum
2.2.2 圖像填充
第二次遍歷:多根據之前得到的圖像尺寸新建空白圖像,然后開始用人臉矩形填充圖像,每次 width 方向從 blank_start 位置開始,每次填完一張之后記得更新起始位置:( blank_start += width ):
for i in range(height): for j in range(width): img_blank[i][blank_start + j] = img[d.top() + i][d.left() + j]
如果想訪問圖像的某點像素,可以利用 img [height] [width]:
存儲像素其實是一個三維數組,先高度 height,然后寬度 width;
返回的是一個顏色數組( 0-255,0-255,0-255 ),按照( B, G, R )的順序;
比如 藍色 就是(255,0,0),紅色 是(0,0,255);
3. 源碼
3.1 crop_faces_show.py
# created at 2018-01-22 # updated at 2018-09-29 # Author: coneypo # Blog: http://www.cnblogs.com/AdaminXie # GitHub: https://github.com/coneypo/Dlib_face_cut import dlib # 人臉識別的庫dlib import numpy as np # 數據處理的庫numpy import cv2 # 圖像處理的庫OpenCv # Dlib 檢測器 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat') # 讀取圖像 path = "faces_for_test/" img = cv2.imread(path+"test_faces_1.jpg") # Dlib 檢測 dets = detector(img, 1) print("人臉數:", len(dets), "\n") # 記錄人臉矩陣大小 height_max = 0 width_sum = 0 # 計算要生成的圖像 img_blank 大小 for k, d in enumerate(dets): # 計算矩形大小 # (x,y), (寬度width, 高度height) pos_start = tuple([d.left(), d.top()]) pos_end = tuple([d.right(), d.bottom()]) # 計算矩形框大小 height = d.bottom()-d.top() width = d.right()-d.left() # 處理寬度 width_sum += width # 處理高度 if height > height_max: height_max = height else: height_max = height_max # 繪制用來顯示人臉的圖像的大小 print("窗口大小:" , '\n', "高度 / height:", height_max , '\n', "寬度 / width: ", width_sum) # 生成用來顯示的圖像 img_blank = np.zeros((height_max, width_sum, 3), np.uint8) # 記錄每次開始寫入人臉像素的寬度位置 blank_start = 0 # 將人臉填充到img_blank for k, d in enumerate(dets): height = d.bottom()-d.top() width = d.right()-d.left() # 填充 for i in range(height): for j in range(width): img_blank[i][blank_start+j] = img[d.top()+i][d.left()+j] # 調整圖像 blank_start += width cv2.namedWindow("img_faces")#, 2) cv2.imshow("img_faces", img_blank) cv2.waitKey(0
實現效果:
圖 5 原圖和處理后得到的圖像窗口
3.2 crop_faces_save.py
如果你想將識別出來的人臉保存成單個的圖像,方便之后處理用,只需將上述代碼進行略微修改;
只需一次遍歷,根據每次檢測到的人臉尺寸,新建空白圖像后寫入,然后利用 cv2.imwrite 寫入到本地:
crop_faces_save.py:
1 # created at 2018-01-22 2 # updated at 2018-09-29 3 4 # Author: coneypo 5 # Blog: http://www.cnblogs.com/AdaminXie 6 # GitHub: https://github.com/coneypo/Dlib_face_cut 7 8 import dlib # 人臉識別的庫dlib 9 import numpy as np # 數據處理的庫numpy 10 import cv2 # 圖像處理的庫OpenCv 11 import os 12 13 # 讀取圖像的路徑 14 path_read = "faces_for_test/" 15 img = cv2.imread(path_read+"test_faces_3.jpg") 16 17 # 用來存儲生成的單張人臉的路徑 18 path_save = "faces_separated/" 19 20 21 # Delete old images 22 def clear_images(): 23 imgs = os.listdir(path_save) 24 25 for img in imgs: 26 os.remove(path_save + img) 27 28 print("clean finish", '\n') 29 30 31 clear_images() 32 33 34 # Dlib 預測器 35 detector = dlib.get_frontal_face_detector() 36 predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat') 37 38 39 # Dlib 檢測 40 faces = detector(img, 1) 41 42 print("人臉數:", len(faces), '\n') 43 44 for k, d in enumerate(faces): 45 46 # 計算矩形大小 47 # (x,y), (寬度width, 高度height) 48 pos_start = tuple([d.left(), d.top()]) 49 pos_end = tuple([d.right(), d.bottom()]) 50 51 # 計算矩形框大小 52 height = d.bottom()-d.top() 53 width = d.right()-d.left() 54 55 # 根據人臉大小生成空的圖像 56 img_blank = np.zeros((height, width, 3), np.uint8) 57 58 for i in range(height): 59 for j in range(width): 60 img_blank[i][j] = img[d.top()+i][d.left()+j] 61 62 # cv2.imshow("face_"+str(k+1), img_blank) 63 64 # 存在本地 65 print("Save to:", path_save+"img_face_"+str(k+1)+".jpg") 66 cv2.imwrite(path_save+"img_face_"+str(k+1)+".jpg", img_blank)
圖 6 生成的單個人臉圖像文件
# 請尊重他人勞動成果,轉載或者使用源碼請注明出處:http://www.cnblogs.com/AdaminXie
# 如果對您有幫助,歡迎在 GitHub 上 Star 本項目: https://github.com/coneypo/Dlib_face_cut
# 如有問題請留言或者聯系郵箱 coneypo@foxmail.com