Haarcascade_frontalface_default xml là gì

Một nhóm lập trình viên nước ngoài phát triển về trí tuệ nhân tạo đã nhận định rằng:

Để đưa ra quyết định thực hiện một việc gì đó thì trước tiên phải nhận dạng được các vật chất xung quanh thế nên chúng tôi đã miệt mài học toán và thuật toán nhằm tối ưu nhất có thể nhận ra một vật thể, cũng là một con mèo nhưng lúc thì nó nhảy, lúc thì nó nằm và còn có lúc nó bị một vật gì đó cản một nửa khuôn mặt thế cho nên rất khó để mà nhận dạng ra được khuôn mặt cúa chúng, thay vào việc mãi mê nghiên cứu và phát triển thuật toán thì chúng tôi đã sử dụng một lượng hình ảnh/dữ liệu về con mèo nạp vào chương trình, cùng là một chi phí hoặc có khả năng thấp hơn nhưng kết quả lại tốt hơn rất nhiều.

Bài viết này giới thiệu đến bạn đọc sử dụng OpenCV với ngôn ngữ mô tả là Python cùng với tệp tin XML Haarcascade để nhận diện khuôn mặt trong một bức ảnh.

Môi trường thử nghiệm

  • Python phiên bản 3.6.5.
  • OpenCV phiên bản 3.4.1.

Các thư viện cần thiết

Sử dụng cửa sổ Command Prompt và thực viện dòng lệnh sau đây

pip install opencv-python

Sử dụng OpenCV trong bài toán nhận diện khuôn mặt

Phần giới thiệu đã đề cập đến dùng hình ảnh/dữ liệu để giảm chi phí cho việc nghiên cứu thuật toán và những dữ liệu này đã được đúc kết thành tệp tin xml.

Haar Cascade là dữ liệu được sử dụng phổ biến nhất, tôi chỉ sử dụng riêng một tệp tin trong bộ Haar Cascade là haarcascade_frontalface_default.xml và ngoài ra còn có các tệp tin về phát hiện mắt, miệng, hình dáng cơ thể trong bộ Haar Cascade.

Đầu tiên khai báo những thư viện sau

import cv2

Bước 1: Đầu vào sẽ là bức ảnh và tệp tin xml

image  = cv2.imread("images/Bill Gates.jpg") face_cascade = cv2.CascadeClassifier("Haar Cascade/haarcascade_frontalface_default.xml")

Bước 2: Tạo một bức ảnh xám từ bức ảnh gốc

grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

Bước 3: Sử dụng phương thức detectMultiScale để phát hiện khuôn mặt trong bức ảnh xám

faces = faceCascade.detectMultiScale( grayImage, scaleFactor = 1.1, minNeighbors = 5 )
  • grayImage: là nguồn/bức ảnh xám.
  • scaleFactor: độ scale sau mỗi lần quét, tính theo 0.01 = 1%. Nếu như để scaleFactor = 1 thì tấm ảnh sẽ giữ nguyên
  • minNeighbors: scale và quét ảnh cho đến khi không thể scale được nữa thì lúc này sẽ xuất hiện những khung ảnh trùng nhau, số lần trùng nhau chính là tham số minNeighbors để quyết định cho việc có chọn khung ảnh này là khuôn mặt hay không.

Ngoài ra còn có các tham số như là maxScale, minScale để cho kích thước khung ảnh bắt đầu và kích thước khung ảnh kết thúc. Có thể hiệu chỉnh tham số scaleFactor, minNeighbors, minScale, maxScale để có kết quả như mong muốn.

Bước 4: Sau khi tính toán thì dữ liệu các khuôn mặt đã có trong biến faces, để muốn xác thực chúng ta vẽ nó lên bức ảnh gốc và phác họa ra màn hình

# Draw for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2) # Show cv2.imshow("Faces found", image)

Kết thúc chương trình với

cv2.waitKey(0) cv2.destroyAllWindows()

Kết quả khi chạy chương trình

Haarcascade_frontalface_default xml là gì

Source code đầy đủ

Haarcascade_frontalface_default xml là gì
Bill Gates và Steve Jobs import cv2 # Bước 1: Tấm ảnh và tệp tin xml face_cascade = cv2.CascadeClassifier("Haar Cascade/haarcascade_frontalface_default.xml") image = cv2.imread("images/Bill Gates.jpg") # Bước 2: Tạo một bức ảnh xám grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Bước 3: Tìm khuôn mặt faces = face_cascade.detectMultiScale( grayImage, scaleFactor = 1.1, minNeighbors = 5, ) # Bước 4: Vẽ các khuôn mặt đã nhận diện được lên tấm ảnh gốc for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2) # Bước 5: Vẽ lên màn hình cv2.imshow("Faces found", image) cv2.waitKey(0) cv2.destroyAllWindows()

Haarcascade_frontalface_default xml là gì

Nhận diện khuôn mặt là gì?

Nhận diện khuôn mặt là một công nghệ máy tính đang được sử dụng trong nhiều ứng dụng khác nhau để xác định khuôn mặt người trong hình ảnh kỹ thuật số. Nhận diện khuôn mặt cũng đề cập đến quá trình tâm lý mà con người xác định vị trí và quan sát khuôn mặt trong một cảnh trực quan.

Haar Cascades là gì?

  • Bộ phân loại Haar Cascade là một cách hiệu quả để phát hiện đối tượng.
  • Được đề xuất bởi Paul Viola và Michael Jones trong bài báo của họ Phát hiện đối tượng nhanh bằng cách sử dụng một tầng tăng cường các tính năng đơn giản ↗
  • Đây là một cách tiếp cận dựa trên máy học, trong đó rất nhiều hình ảnh tích cực và tiêu cực được sử dụng để đào tạo bộ phân loại.
    • Hình ảnh tích cực - Những hình ảnh này chứa những hình ảnh mà chúng tôi muốn bộ phân loại của mình xác định.
    • Hình ảnh Âm bản - Hình ảnh của mọi thứ khác, không chứa đối tượng mà chúng tôi muốn phát hiện.

(Biết thêm tại đây↗).

Phát hiện thác tầng trong Python (OpenCV)

  • OpenCV xuất hiện như một bộ dò sử dụng Haar Cascade.
  • Trong nhận diện khuôn mặt, chúng tôi sử dụng Haarcascade Frontal Face có xmlđịnh dạng.

Những yêu cầu bạn cần phải có trước khi chạy mã (tất cả phiên bản mới nhất)

--- python --- opencv-python --- haarcascade_frontalface_default.xml

Tải xuống các tệp thác haar tại đây↗

Đầu tiên, chúng ta cần tải các bộ phân loại XML cần thiết. Sau đó tải hình ảnh đầu vào (hoặc video) của chúng tôi ở chế độ thang độ xám.

import numpy as np #importing the OpenCV Lib import cv2 #Loading the haarcascade front face file faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') #Reading the face image img = cv2.imread('testFace.jpg') #Converting the image into grayscale image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Bây giờ chúng ta tìm thấy các khuôn mặt trong hình ảnh. Nếu các khuôn mặt được tìm thấy, nó sẽ trả về vị trí của các khuôn mặt được phát hiện dưới dạng Rect (x, y, w, h).

#Detecting the face face = faceCascade.detectMultiScale(gray, 1.1,4) #Draw rectangle around the face for(x,y,w,h) in face: cv2.rectangle(img, (x,y),(x+w, y+h), (255,0,0),2)

Bây giờ chúng tôi sẽ hiển thị đầu ra

#Display the result with face detected cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()

Face Detection (Phát hiện khuôn mặt) là một ứng dụng của Computer Vision được sử dụng trong nhiều lĩnh vực, với chức năng phát hiện khuôn mặt con người trong một bức ảnh kỹ thuật số.

Mặc dù Deep Learning ngày càng có nhiều đột phá (thực thế thì OpenCV 3 đã cung cấp bộ Face Detection dựa trên Deep Learning), nhưng Cascade Classifier vẫn là một thuật toán được sử dụng phổ biến cho bài toán Object Detection vì tốc độ cao và độ chính xác khá ổn. Bài viết này sẽ giới thiệu về Cascade Classifier với Haar-like features được cung cấp sẵn bởi OpenCV.

VIOLA-JOHN DETECTOR

Ở phần này chúng ta sẽ tìm hiểu khái quát về Viola-John detector, giải thuật được sử dụng trong Cascade Classifier. Ban đầu giải thuật này chỉ hỗ trợ Haar-like features (Haar Cascade Classifier), nhưng kể từ OpenCV 3.x thì đã hỗ trợ thêm Local Binary Pattern Histogram (LBP Cascade Classifier).

Với bài toán Face Detection, mỗi bức ảnh được đưa vào detector sẽ được “scan” bởi một “sliding window” có kích thước cố định ở nhiều tỉ lệ của bức ảnh, hình 1.

Haarcascade_frontalface_default xml là gì
Hình 1 – Sliding window

Tại mỗi “window”, các Haar-like features (hình 2) có trong vùng hình ảnh đó sẽ được tính toán bằng cách áp dụng Summed Area Tables (còn gọi là Integral Image).

Haarcascade_frontalface_default xml là gì
Hình 2 – Haar-like featues

Từ mỗi “window” có thể tính toán ra rất nhiều Haar-like features (khoảng 180000 features cho “window” có kích thước 24×24). Để có thể xử lý hết số lượng feature khổng lồ này, Viola-John detector sử dụng một phương pháp gọi là Rejection Cascade, hình 3.

Haarcascade_frontalface_default xml là gì
Hình 3 – Rejection Cascade được sử dụng trong Viola-John detector.

Bản chất mỗi node (F1, F2,…, Fn) trong Rejection Cascade là một AdaBoosted Decision Tree classifier được train từ một dataset rất lớn gồm hàng (chục) nghìn bức ảnh chứa và không chứa khuôn mặt (OpenCV đã cung cấp sẵn một số file cascade classifier để phát hiện khuôn mặt nên chúng ta không cần phải tự train nữa!). Thông thường, mỗi node sẽ dựa trên 1 feature (và tối đa không quá 3 features) để đưa ra quyết định xem vùng “window” đó có thể chứa khuôn mặt hay không. Nếu có, nó sẽ được đưa tới node tiếp theo để xử lý; ngược lại thì quá trình xử lý kết thúc. Chỉ những “window” nào vượt qua tất cả n nodes thì mới được công nhận là chứa khuôn mặt. Viola-John detector có tốc độ xử lý rất nhanh, vì đa số “window” không chứa khuôn mặt sẽ bị loại bỏ ngay từ một vài node đầu tiên của Rejection Cascade.

Nhờ áp dụng Summed Area Tables, AdaBoost algorithm và Rejection Cascade nên Haar cascade tính toán rất nhanh và có thể phát hiện khuôn mặt ở nhiều vị trí và tỉ lệ, cũng như rất phù hợp cho các ứng dụng real-time.

Tuy nhiên Haar cascade có những điểm yếu sau:

  • Thời gian training cho cascade rất lớn, vì phải train cho hàng chục node, mỗi node lại là một AdaBoosted Decision Tree classifier;
  • Tỉ lệ False-positive và False-negative cao do khó tìm được các tham số tối ưu;
  • Cần tinh chỉnh các tham số cho phù hợp với từng bức ảnh để đạt được kết quả tốt nhất.

FACE DETECTION IN OPENCV

Cùng tìm hiểu một số function của OpenCV 3 sẽ được sử dụng trong Face Detection nào.

  • CascadeClassifier = cv2.CascadeClassifier(cascadeFile) – Load a classifier from a file.

Trong đó:

cascadeFile – Cascade file, thường nằm tại folder ..\opencv\build\share\OpenCV. Trong bài viết này chúng ta sẽ sử dụng Haarcascades.

  • detectedObjects = CascadeClassifier.detectMultiScale(image, scaleFactor,  minNeighbors, flags, minSize) – Phát hiện các đối tượng (được qui định trong Classifier) với các kích thước khác nhau có trong bức ảnh. Các đối tượng được phát hiện sẽ được trả về ở dạng “a list of rectangles“.

Trong đó:

image – input image.
scaleFactor – được sử dụng để tạo “scale pyramid” cho phép phát hiện đối tượng ở multiple scales.
minNeighbors – số lượng overlap window ít nhất trên một vùng hình ảnh để vùng đó được công nhận là có chứa khuôn mặt, thường có giá trị trong khoảng [3, 4, 5, 6]. Tham số này giúp giảm “false detection”.
+ minSize – kích thước nhỏ nhất của đối tượng có thể được phát hiện, thường là (30, 30). Các đối tượng có kích thước nhỏ hơn minSize sẽ bị bỏ qua.

FACE DETECTION IN IMAGES

Example 1 – faceDetection.py

import argparse import cv2 class FaceDetector: def __init__(self, faceCascadePath): self.faceCascade = cv2.CascadeClassifier(faceCascadePath) def detect(self, image, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)): rects = self.faceCascade.detectMultiScale(image, scaleFactor=scaleFactor, minNeighbors=minNeighbors, minSize=minSize, flags=cv2.CASCADE_SCALE_IMAGE) return rects ap = argparse.ArgumentParser() ap.add_argument("-f", "--face") ap.add_argument("-i", "--image") args = vars(ap.parse_args()) image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) fd = FaceDetector(args["face"]) faceRects = fd.detect(gray, scaleFactor=1.1, minNeighbors=6, minSize=(30, 30)) print("I found {} face(s)".format(len(faceRects))) for (x,y,w,h) in faceRects: cv2.rectangle(image, (x,y), (x+w, y+h), (0,255,0), 2) cv2.imshow("Faces", image) cv2.waitKey(0)

Execution:
$ python faceDetection.py -i images -f ..\haarcascades\haarcascade_frontalface_default.xml

Kết quả:

Hình 4 – Footballists

Hình 5 – Arsenal FC

Hình 6 – Cesc Fabregas

Với các tham số không đổi, ở Figure 4, cả 5 khuôn mặt đều được phát hiện, tuy nhiên ở Figure 5, chúng ta lại phát hiện sót khuôn mặt của anh da đen, còn ở Figure 6 có đến 2 khuôn mặt được phát hiện!!!.

Thử thay đổi scaleFactor = 1.05 xem nào:

Hình 7 – Footballists

Hình 8 – Arsenal FC

Hình 9 – Cesc Fabregas

Cuối cùng thì khuôn mặt của anh da đen cũng đã được phát hiện. Tuy nhiên trong bức ảnh của Cesc Fabregas lại phát hiện đến 3 khuôn mặt!!!

Chúng ta sẽ thay scaleFactor = 1.15 xem kết quả thay đổi thế nào:

Hình 10 – Footballists

Hình 11 – Arsenal FC

Hình 12 – Cesc Fabregas

Lần này thì chúng ta đã phát hiện đúng khuôn mặt trong bức ảnh của Cesc Fabregas, tuy nhiên bức ảnh của Arsenal FC đã bị phát hiện thiếu vài khuôn mặt.

Qua các ví dụ trên có thể thấy rằng Haarcascade mặc dù khá nhanh nhưng có 2 điểm yếu nổi bật là:

  1. Điểm yếu đầu tiên, để có được kết quả tốt nhất chúng ta buộc phải điều chỉnh các tham số như scaleFactor, minNeighbors cho phù hợp với riêng từng bức ảnh. Điều này là bất khả thi nếu chúng ta cần phải xử lý hàng ngàn tấm ảnh.
  2. Điểm yếu tiếp theo chính là “False positive“, có nghĩa là Haarcascade phát hiện ra các khuôn mặt trong bức ảnh mặc dù thực tế là chẳng có khuôn mặt nào ở vị trí đó. Figure 6 là một ví dụ. Tất nhiên các khuyết điểm này có thể được loại bỏ bằng cách “điều chỉnh các tham số như scaleFactor, minNeighbors cho phù hợp với riêng từng bức ảnh“.

Mình cũng rút ra một kinh nghiệm, nếu phát hiện thiếu các khuôn mặt thì hãy giảm giá trị scaleFactor, nếu gặp “False Positive” thì tăng giá trị scaleFactor. Giá trị minNeighbors tốt nhất là 5 hoặc 6.

Tất nhiên không có gì là hoàn hảo, hãy cứ vui với kết quả chúng ta vừa nhận được nhé! Mọi thứ chỉ mới bắt đầu.

FACE DETECTION IN VIDEO

Để phát hiện khuôn mặt trên video (từ webcam), chúng ta sẽ xử lý từng frame của video đó, tương tự như đối với từng bức ảnh riêng biệt ở ví dụ trước.

Trong bài viết này mình sử dụng Webcam Logitech C270.

Example 2 – webcamFaceDetection.py

import argparse import cv2 from threading import Thread class FaceDetector: def __init__(self, faceCascadePath): self.faceCascade = cv2.CascadeClassifier(faceCascadePath) def detect(self, image, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)): rects = self.faceCascade.detectMultiScale(image, scaleFactor=scaleFactor, minNeighbors=minNeighbors, minSize=minSize, flags=cv2.CASCADE_SCALE_IMAGE) return rects class WebcamVideoCapture: def __init__(self, src=0): # initialize the video camera stream and read the first frame # from the stream self.stream = cv2.VideoCapture(src) (self.grabbed, self.frame) = self.stream.read() # initialize the variable used to indicate if the thread should # be stopped self.stopped = False def start(self): # start the thread to read frames from the video stream Thread(target=self.update, args=()).start() return self def update(self): # keep looping infinitely until the thread is stopped while True: # if the thread indicator variable is set, stop the thread if self.stopped: self.stream.release() return # otherwise, read the next frame from the stream (self.grabbed, self.frame) = self.stream.read() def read(self): # return the frame most recently read return self.grabbed, self.frame def stop(self): # indicate that the thread should be stopped self.stopped = True ap = argparse.ArgumentParser() ap.add_argument("-f", "--face") args = vars(ap.parse_args()) video = WebcamVideoCapture(src=0).start() fd = FaceDetector(args["face"]) while True: grabbed, frame = video.read() if not grabbed: continue gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faceRects = fd.detect(gray, scaleFactor=1.1, minNeighbors=6, minSize=(30, 30)) count = 0 for (x,y,w,h) in faceRects: count += 1 cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2) cv2.putText(frame, "Face [{}]".format(count), (x,y-15), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2, cv2.LINE_AA) cv2.imshow("Faces", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video.stop() cv2.destroyAllWindows()

Execution:
$ python faceDetection.py -f ..\haarcascades\haarcascade_frontalface_default.xml

Như các bạn thấy, các function xử lý hình ảnh đều tương tự ví dụ 1, chỉ khác ở chỗ chúng ta sẽ xử lý liên tiếp các frame nhận được từ webcam. Ngoài ra ở ví dụ này mình còn sử dụng class WebcamVideoCapture để capture hình ảnh từ webcam với một thread riêng biệt nhằm hạn chế độ trễ.

Tại dòng 66 mình có sử dụng function cv2.putText() để thêm các ký tự lên bức ảnh:

cv2.putText(image, text, (x,y), font, size, color, thickness, lineType)

Trong đó:

  • image – hình ảnh cần chèn ký tự.
  • text – nội dung cần chèn vào bức ảnh.
  • (x,y) – tọa độ đoạn text.
  • font – thường sử dụng font cv2.FONT_HERSHEY_SIMPLEX.
  • color – màu chữ ở hệ (B,G,R).
  • thickness – độ dày của nét chữ.
  • lineType – thường dùng cv2.LINE_AA (đối với OpenCV3), cv2.CV_AA (đối với OpenCV 2.4)

Như vậy chúng ta đã làm quen với chức năng phát hiện khuôn mặt trên OpenCV, hãy tiếp tục khám phá nhé. Cảm ơn các bạn đã theo dõi bài viết.

Thân ái và quyết thắng.

Reference:
[1] StackOverFlow – Recommended values for OpenCV detectMultiScale() parameters.
[2] Increasing webcam FPS with Python and OpenCV.
[3] Drawing functions OpenCV 3.
[4] Face Detection using Haar Cascades