基於OpenCV & Dlib & MTCNN的人臉檢測的效果對比


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))
View Code

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()
View Code

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
View Code

人臉檢測效果對比:

 

 PS: 還有一些測試沒有弄完,我先發一版,持續更新~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM