Hệ thống phát gạo nhận diện khuôn mặt (Phần 1)

Tram Ho

Như đã giới thiệu, phần đầu tiên này mình xin nói về hệ thống AI cho hệ thống nhé.
Trong bài toán nhận diện khuôn mặt này, có vài yêu cầu như sau:

  • Vì lượng người ra vào nhiều nên không có thời gian để huấn luyện mô hình nhận diện khuôn mặt.
  • Data mặt người đó thường chỉ có một hoặc vài ảnh là cùng. Nếu trong cùng một ngày thì chỉ có một, nếu không gặp phải mấy ông bà lầy lội ra xin nhiều lần.

Vì thế, bài toán này mình sẽ đưa ra hướng giải quyết là sử dụng mô hình object detection pretrain cho bài toán nhận diện khuôn mặt. Sau đó, ta sẽ trích xuất đặc trưng khuôn mặt người đó ra bằng một mạng tích chập pretrain nốt. Nói một cách dễ hiểu là con người ta sẽ chỉ nhìn mặt người đó, rồi tìm những đặc điểm như mũi cao, nốt ruồi đâu đó, … để phân biệt nhưng chỉ khác là máy tính xử lý trên giá trị pixel ảnh. Sau đó ta sẽ sử dụng các cây tìm kiếm hoặc đồ thị tìm kiếm. Với mỗi người mới ta sẽ đưa vào đồ thị đặc trưng của người đó để tìm kiếm sau này.

Phần giải thích AI

Ở đây, mình xin giải thích qua về một vài lý thuyết AI mà mình sử dụng. Nếu bạn chỉ quan tâm đến phần code xin hãy vào phần code ngay. Lưu ý, bỏ qua phần này không ảnh hưởng đến việc code.

Ở đây, mình sử dụng MTCNN. Mình biết là các bạn sẽ kiểu: Ewww insert the meme here. Sao không xài FaceNet hay CenterNet-Resnet 50 gì đó cho xịn. Lí do là vì khi mình tra xem có cái thư viện nào pretrain để phát triển nhanh hệ thống thì repo MTCNN được viết bằng torch đập ngay vào mặt và tiện ở chỗ ngươi ta còn làm pip install cho nó rồi. CenterNet mà cho vào docker thì lằng nhằng, FaceNet thì lại dùng MXNet.
Paper gốc: https://arxiv.org/pdf/1604.02878v1.pdf.

MTCNN bao gồm 3 mạng:

  • P-Net
  • R-Net
  • O-Net

    Đầu vào hình ảnh được resize thành nhiều kích thước tạo thành một Image Pyramid. Sau đó pyramid sẽ được đưa vào P-Net:


Kiến trúc PNet

Có thể thấy ở đây, P-Net là một mạng dạng FCN – Fully convolutional network. Nhiệm vụ của nó là xác định các window ảnh bao gồm mặt người nhưng lại lấy nhiều, nhanh và thiếu chính xác. Output đầu ra gồm có:

  • Face classificationcó shape (1x1x2).
  • BBox regressioncó shape (1x1x4).

Các mạng R-Net và O-Net có cấu trúc tương tự nhau chỉ khác nhau về độ sâu và đầu ra. Với đầu vào R-Net là các bounding box từ P-Net và đầu vào O-Net là các bounding box từ R-Net. Nhiệm vụ của chúng là lọc ra các bounding boxes chính xác hơn nhờ vào việc tặn độ sâu của mô hình.


Kiến trúc RNet



Kiến trúc ONet

2 mạng trên có thêm lớp Fully connected. Vì thế mà đầu ra của chúng:

  • Face classificationcó shape (2).
  • BBox regressioncó shape (4).

Phần thực hiện code

Bạn có thể tự git clone repo này để sử dụng hoặc sử dụng pip. Nếu không có ý định chỉnh sửa behaviour của các lớp trong repo thì nên sử dụng pip cho tiện lợi khi config đường dẫn, …
Đầu tiên, tạo folder backend trong folder project. Và hãy tạo các file sau đây:

  • face_detector.py
  • face_searcher.py

Phần trích xuất đặc trưng

Ta sẽ khởi tạo một class đảm nhiệm cho việc định vị khuôn mặt và trích xuất đặc trưng qua một mạng tích chập trong file face_detector.py

Giải thích về một vài param:

  • MTCNN:
    • image_size: kích thức ảnh mặt crop
    • min_face_size: kích thước mặt nhỏ nhất trên nahr gốc để tìm kiếm
    • threshold: mức độ confidence để nhận mặt. Array ba giá trị cho ba mạng.
    • factor: đơn vị scale ảnh trên pyramid
  • InceptionResnetV1:
    • pretrain: chọn mô hình pretrain để sử dụng
    • classify: nếu ta sử dụng True thì mạng sẽ đi qua cả lớp Logits và là bài toán phân loại. Ở đây ta sẽ set False để lấy đặc trưng ảnh.

Giờ ta sẽ tiếp tục code nhận diện khuôn mặt:

Hàm trên trả về ảnh ở dạng torch tensor

Hàm trên sẽ trả về vector đặc trưng có shape (512, ) trong bài toán của ta. Tiếp theo ta sẽ viết các hàm để lấy vector từ ảnh trực tiếp và từ một folder (trường hợp khởi động lợi server ta cần đưa hết các ảnh đã có lại vào hệ thống).

Phần đưa vào đồ thị tìm kiếm

Phần này mình sử dụng Hnswlib vì 2 lí do sau đây:

  • Thư viện trên cho phép add thêm các giá trị mới sau khi xây dựng đồ thị. Các thư viện như Annoy không cho phép làm như vậy.
  • Theo benchmark, Hnswlib tốt hơn nhiều thư viện khác ở cả tốc độ lẫn độ chính xác Recall
    benchmark

Ta sẽ viết một class phụ trách việc tìm kiếm trong face_searcher.py:

Các tham số của hnswlib.Index bao gồm:

  • space: cách thức tính khoảng cách: Squared L2, Inner product, Inner product
  • dim: độ dài vector truyền vào, ở đây là 512

Cách tham số như ef, M, … hãy xem ở đây

Ở phần tiếp theo, chúng ta sẽ xây dựng hệ thống server với flask.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo