ref: https://github.com/vipstone/faceai
ref: https://github.com/imistyrain/MTCNN
PS: 1 安裝dlib庫花了好長時間,最終在CSDN上花錢下載了一個輪子,安裝:pip3 install dlib-19.17.0-cp37-cp37m-win_amd64
鏈接:https://pan.baidu.com/s/1h7uyJkmxHNVbGlE93eI8VQ
提取碼:j8rc
2 我用於測試的圖片,是身份證正反面復印件(銀行的數據,有的人臉非常模糊~~~)
3 安裝mxnet庫:pip install mxnet-cu100 (我的cuda是v10.0)
我把原作者的代碼改了一下,用於遍歷一個文件夾下的所有圖片
PS: 用於人臉識別的.dat文件:
鏈接: https://pan.baidu.com/s/1yo_aawFgly0vjtBatxLrSw 提取碼: yh5v
Dlib人臉檢測:

1 #coding=utf-8 2 #圖片檢測 - Dlib版本 3 import cv2 4 import dlib 5 import glob 6 import datetime 7 8 dealedimg = "img/dealedimg/" # 檢測到一個人臉,並框正確 9 unhandledimg = "img/unhandledimg/" # 檢測不到人臉 10 errorhandledimg = "img/errorhandledimg/" # 檢測錯誤 11 multiFaceimg = "img/multiFaceimg/" # 多張人臉 12 originalimg = "img/originalimg/" 13 14 15 #人臉分類器 16 detector = dlib.get_frontal_face_detector() 17 # 獲取人臉檢測器 18 predictor = dlib.shape_predictor( 19 "D:\\software\\anaconda3\\Lib\\site-packages\\dlib\\shape_predictor_68_face_landmarks.dat" 20 ) 21 # 程序開始時間 22 startTime = datetime.datetime.now() 23 # 循環遍歷originalimg路徑下的所有圖片 24 count = 0 25 count1 = 0 26 for index, filename in enumerate(glob.glob(originalimg + '*.jpg')): 27 img = cv2.imread(filename) # 讀取圖片 28 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 轉換灰色 29 # 預測出的臉的集合,第二個參數代表圖片的放大倍數 30 dets = detector(img, 3) 31 faceCounts = len(dets) 32 imgName = filename.split("\\")[1] 33 # 檢測到多個人臉 34 if faceCounts > 1: 35 print("檢測到多個人臉==========================") 36 cv2.imwrite(multiFaceimg + imgName, img) 37 continue 38 # 檢測不到人臉 39 if faceCounts == 0: 40 count = count + 1 41 print("未檢測到人臉。。。。。count = " + count.__str__()) 42 cv2.imwrite(unhandledimg + imgName, img) 43 continue 44 # 檢測到一個人臉 45 if faceCounts: 46 # 尋找人臉的68個標定點 47 shape = predictor(img, dets[0]) 48 # 特征點個數 49 characterCounts = len(shape.parts()) 50 if characterCounts < 68: 51 # 如果特征點個數不足68個,就可以說明不是人臉(不能完全說明??) 52 print("框到的矩形不是人臉+++++++++++++++++++++++") 53 cv2.imwrite(errorhandledimg + imgName, img) 54 continue 55 # 框到了正確的一個人臉,則遍歷所有點,打印出其坐標,並圈出來 56 count1 = count1 + 1 57 print("--------------框到的特征點的個數: " + characterCounts.__str__() + "個,第" + count1.__str__() + "張識別正確的圖----------------") 58 for pt in shape.parts(): 59 pt_pos = (pt.x, pt.y) 60 cv2.circle(img, pt_pos, 1, (0, 255, 0), 2) 61 # 在圖片中標注人臉,並顯示 62 left = dets[0].left() 63 top = dets[0].top() 64 right = dets[0].right() 65 bottom = dets[0].bottom() 66 cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 2) 67 cv2.imwrite(dealedimg + imgName, img) 68 # 程序結束時間 69 endTime = datetime.datetime.now() 70 print((endTime - startTime))
OpenCV人臉檢測:

1 #coding=utf-8 2 #圖片檢測 - OpenCV版本 3 import cv2 4 import datetime 5 import glob 6 7 dealedimg = "img/dealedimg/" 8 unhandledimg = "img/unhandledimg/" 9 originalimg = "img/originalimg/" 10 multiFaceimg = "img/multiFaceimg/" # 多張人臉 11 filepath = "img/originalimg/" 12 # OpenCV人臉識別分類器 13 # 在使用OpenCV的人臉檢測之前,需要一個人臉訓練模型,格式是xml的,我們這里使用OpenCV提供好的人臉分類模型xml 14 # 調用已經訓練好的模型 15 classifier = cv2.CascadeClassifier( 16 "D:\software\Python37\Lib\site-packages\opencv-master\data\haarcascades\haarcascade_frontalface_default.xml" 17 ) 18 19 # 程序開始時間 20 startTime = datetime.datetime.now() 21 # 循環遍歷filepath路徑下的所有圖片 22 count = 0 23 for index, filename in enumerate(glob.glob(originalimg + '*.jpg')): 24 25 img = cv2.imread(filename) # 讀取圖片 26 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 轉換灰色 27 # 直接閾值化是對輸入的單通道矩陣逐像素進行閾值分割。 28 ret, binary44 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE) 29 # 大津法二值化 30 ret, binaryOTSU = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU) 31 # 自適應閾值化能夠根據圖像不同區域亮度分布,改變閾值 32 binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 10) 33 # 高斯濾波 - 去噪 34 img_GaussianBlur = cv2.GaussianBlur(binary, (7, 7), 0) 35 36 color = (0, 255, 0) # 定義繪制顏色 37 # 調用識別人臉 38 # classifier.detectMultiScale()參數講解: 39 # 參數1:image - -待檢測圖片,一般為灰度圖像加快檢測速度; 40 # 41 # 參數2:objects - -被檢測物體的矩形框向量組; 42 # 參數3:scaleFactor - -表示在前后兩次相繼的掃描中,搜索窗口的比例系數。默認為1 43 # .1 44 # 即每次搜索窗口依次擴大10 %; 45 # 參數4:minNeighbors - -表示構成檢測目標的相鄰矩形的最小個數(默認為3個)。 46 # 如果組成檢測目標的小矩形的個數和小於 47 # min_neighbors - 1 48 # 都會被排除。 49 # 如果min_neighbors 50 # 為 51 # 0, 則函數不做任何操作就返回所有的被檢候選矩形框, 52 # 這種設定值一般用在用戶自定義對檢測結果的組合程序上; 53 # 參數5:flags - -要么使用默認值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果設置為 54 # 55 # CV_HAAR_DO_CANNY_PRUNING,那么函數將會使用Canny邊緣檢測來排除邊緣過多或過少的區域, 56 # 57 # 因此這些區域通常不會是人臉所在區域; 58 # 參數6、7:minSize和maxSize用來限制得到的目標區域的范圍。 59 # 圖片放大 60 fx = 2 61 fy = 2 62 img2 = cv2.resize(img, (0, 0), fx=fx, fy=fy, interpolation=cv2.INTER_CUBIC) 63 64 faceRects = classifier.detectMultiScale( 65 img2, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32)) 66 imgName = filename.split("\\")[1] 67 faceCounts = len(faceRects) 68 if faceCounts > 1: # 檢測到多個人臉 69 print("檢測到多個人臉==========================") 70 cv2.imwrite(multiFaceimg + imgName, img) 71 continue 72 # 檢測不到人臉 73 if faceCounts == 0: 74 count = count + 1 75 print("未檢測到人臉。。。。。count = " + count.__str__()) 76 cv2.imwrite(unhandledimg + imgName, img) 77 continue 78 # 檢測到一個人臉 79 if faceCounts: # 大於0則檢測到人臉 80 for faceRect in faceRects: # 單獨框出每一張人臉 81 x, y, w, h = faceRect 82 # 框出人臉 83 cv2.rectangle(img, (x, y), (x + h, y + w), color, 2) 84 # 左眼 85 cv2.circle(img, (x + w // 4, y + h // 4 + 30), min(w // 8, h // 8), 86 color) 87 # 右眼 88 cv2.circle(img, (x + 3 * w // 4, y + h // 4 + 30), min(w // 8, h // 8), 89 color) 90 # 嘴巴 91 cv2.rectangle(img, (x + 3 * w // 8, y + 3 * h // 4), 92 (x + 5 * w // 8, y + 7 * h // 8), color) 93 # 程序結束時間 94 endTime = datetime.datetime.now() 95 print((endTime - startTime)) 96 # 保存畫了框的圖片 97 # 保存圖像 98 x = x + 1 99 # img_saving_path = filepath.replace('.jpg', str(x) + '.jpg') 100 # print(str) 101 cv2.imwrite(dealedimg + imgName, img) 102 height, width = img.shape[:2] 103 size = (int(width * 0.5), int(height * 0.5)) 104 img2 = cv2.resize(img, size, interpolation=cv2.INTER_AREA) 105 # cv2.imshow("image", img2) # 顯示圖像 106 # cv2.waitKey(0) 107 cv2.destroyAllWindows()
MTCNN人臉檢測:

1 # coding: utf-8 2 import mxnet as mx 3 from mtcnn_detector import MtcnnDetector 4 import cv2 5 import os 6 import time 7 import glob 8 import datetime 9 10 dealedimg = "../imgs/dealedimg/" # 檢測到一個人臉,並框正確 11 unhandledimg = "../imgs/unhandledimg/" # 檢測不到人臉 12 errorhandledimg = "../imgs/errorhandledimg/" # 檢測錯誤 13 multiFaceimg = "../imgs/multiFaceimg/" # 多張人臉 14 originalimg = "../imgs/originalimg/" 15 # 程序開始時間 16 startTime = datetime.datetime.now() 17 # 循環遍歷originalimg路徑下的所有圖片 18 19 20 def testimg(detector): 21 count = 0 22 count1 = 0 23 for index, filename in enumerate(glob.glob(originalimg + '*.jpg')): 24 img = cv2.imread(filename) # 讀取圖片 25 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 轉換灰色 26 imgName = filename.split("\\")[1] 27 t1 = time.time() 28 results = detector.detect_face(img) 29 print('time: ', time.time() - t1) 30 if results is not None: 31 faceCounts = len(results[0]) 32 total_boxes = results[0] 33 points = results[1] 34 print("-------------length is: " + faceCounts.__str__()+"--------------") 35 # 檢測到多個人臉 36 if faceCounts > 1: 37 print("檢測到多個人臉==========================") 38 for b in total_boxes: 39 cv2.rectangle(img, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (0, 255, 0)) 40 41 for p in points: 42 for i in range(5): 43 cv2.circle(img, (p[i], p[i + 5]), 1, (0, 255, 0), 2) 44 cv2.imwrite(multiFaceimg + imgName, img) 45 continue 46 # 檢測不到人臉 47 if faceCounts == 0: 48 count = count + 1 49 print("未檢測到人臉。。。。。count = " + count.__str__()) 50 cv2.imwrite(unhandledimg + imgName, img) 51 continue 52 # 檢測到一個人臉 53 if faceCounts: 54 # draw = img.copy() 55 for b in total_boxes: 56 cv2.rectangle(img, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (0, 255, 0), 2) 57 58 for p in points: 59 for i in range(5): 60 cv2.circle(img, (p[i], p[i + 5]), 1, (0, 255, 0), 2) 61 62 # 框到了正確的一個人臉 63 count1 = count1 + 1 64 print("第" + count1.__str__() + "個識別正確的圖片") 65 cv2.imwrite(dealedimg + imgName, img) 66 # 程序結束時間 67 endTime = datetime.datetime.now() 68 print((endTime - startTime)) 69 else: 70 print("===========未檢測到人臉===================" ) 71 cv2.imwrite(errorhandledimg + imgName, img) 72 continue 73 # -------------- 74 # test on camera 75 # -------------- 76 # def testcamera(detector): 77 # 78 # camera = cv2.VideoCapture(0) 79 # while True: 80 # grab, frame = camera.read() 81 # img = cv2.resize(frame, (640,480)) 82 # 83 # t1 = time.time() 84 # results = detector.detect_face(img) 85 # print('time: ',time.time() - t1) 86 # 87 # if results is None: 88 # cv2.imshow("detection result", img) 89 # cv2.waitKey(1) 90 # continue 91 # 92 # total_boxes = results[0] 93 # points = results[1] 94 # 95 # draw = img.copy() 96 # for b in total_boxes: 97 # cv2.rectangle(draw, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (255, 255, 255)) 98 # 99 # for p in points: 100 # for i in range(5): 101 # cv2.circle(draw, (p[i], p[i + 5]), 1, (255, 0, 0), 2) 102 # cv2.imshow("detection result", draw) 103 # key=cv2.waitKey(1) 104 # if 'q'==chr(key & 255) or 'Q'==chr(key & 255): 105 # break; 106 107 108 if __name__=="__main__": 109 detector = MtcnnDetector(model_folder='../model/mxnet', ctx=mx.cpu(0), num_worker = 4 , accurate_landmark = False) 110 testimg(detector) 111 # testcamera(detector)c
人臉檢測效果對比:
PS: 還有一些測試沒有弄完,我先發一版,持續更新~~~