Nhận dạng mặt người (Face recognition) bằng PCA (eigenface) – Matlab code on ORL database

Khi bắt đầu với lĩnh vực nhận dạng mặt (Face Recognition-FR, không phải Face detetion-phát hiện khuôn mặt người trong ảnh), tôi đã mất khá nhiều thời gian cho các thuật toán cơ bản của nhận dạng mặt: PCA, WPCA, LDA, 2DPCA, KPCA, LBP … hay các câu hỏi đại loại như: dùng ngôn ngữ và công cụ gì để cài đặt thuật toán, Matlab, Python, C++ hay C#? Cuối cùng thấy rằng việc chọn Matlab là thích hợp nhất (cho việc nghiên cứu thôi, tất nhiên) và việc hiểu được cặn kẽ các thuật toán cơ bản như PCA là rất quan trọng cho những ai bắt đầu, vì vậy hy vọng bài viết này sẽ có ích cho ai muốn tìm hiểu về nhận dạng mặt người.

Nhận dạng mặt người (Face recognition) là một lĩnh vực nghiên cứu của ngành Computer Vision, và cũng được xem là một lĩnh vực nghiên cứu của ngành Biometrics (tương tự như nhận dạng vân tay – Fingerprint recognition, hay nhận dạng mống mắt – Iris recognition). Xét về nguyên tắc chung, nhận dạng mặt có sự tương đồng rất lớn với nhận dạng vân tay và nhận dạng mống mắt, tuy nhiên sự khác biệt nằm ở bước trích chọn đặt trưng (feature extraction) của mỗi lĩnh vực. Trong khi nhận dạng vân tay và mống mắt đã đạt tới độ chín, tức là có thể áp dụng trên thực tế một cách rộng rãi thì nhận dạng mặt người vẫn còn nhiều thách thức và vẫn là một lĩnh vực nghiên cứu thú vị với nhiều người. So với nhận dạng vân tay và mống mắt, nhận dạng mặt có nguồn dữ liệu phong phú hơn (bạn có thể nhìn thấy mặt người ở bất cứ tấm ảnh, video clip nào liên quan tới con người trên mạng) và ít đòi hỏi sự tương tác có kiểm soát hơn (để thực hiện nhận dạng vân tay hay mống mắt, dữ liệu input lấy từ con người đòi hỏi có sự hợp tác trong môi trường có kiểm soát). Hiện nay các phương pháp nhận dạng mặt được chia thành nhiều hướng theo các tiêu chí khác nhau: nhận dạng với dữ liệu đầu vào là ảnh tĩnh 2D(still image based FR) là phổ biến nhất, tuy nhiên tương lai có lẽ sẽ là 3D FR (vì việc bố trí nhiều camera 2D sẽ cho dữ liệu 3D và đem lại kết quả tốt hơn, đáng tin cậy hơn), cũng có thể chia thành 2 hướng là: làm với dữ liệu ảnh và làm với dữ liệu video. Trên thực tế người ta hay chia các phương pháp nhận dạng mặt ra làm 3 loại: phương pháp tiếp cận toàn cục (global, như Eigenfaces-PCA, Fisherfaces-LDA), phương pháp tiếp cận dựa trên các đặc điểm cục bộ (local feature based, như LBP, Gabor wavelets) và phương pháp lai (hybrid, là sự kết hợp của hai phương pháp toàn cục và local feature). Phương pháp dựa trên các đặc điểm cục bộ đã được chứng minh là ưu việt hơn khi làm việc trong các điều kiện không có kiểm soát và có thể nói rằng lịch sử phát triển của nhận dạng mặt (A never ending story) là sự phát triển của các phương pháp trích chọn đặc trưng (feature extractrion methods) được sử dụng trong các hệ thống dựa trên feature based. Các ứng dụng cụ thể của nhận dạng mặt dựa trên 2 mô hình nhận dạng: identification (xác định danh tính, bài toán 1-N), và verification (xác thực danh tính, bài toán 1-1). Trong bài toán identification, ta cần xác định danh tính của ảnh kiểm tra, còn trong bài toán verification ta cần xác định 2 ảnh có cùng thuộc về một người hay không.

Các pha trong một hệ thống nhận dạng mặt: để xây dựng một hệ thống nhận dạng mặt, cũng không hề đơn giản, bước đầu tiên cần thực hiện là face detection, tức là phát hiện phần ảnh mặt trong dữ liệu input (CSDL ảnh, video …) và cắt lấy phần ảnh mặt để thực hiện nhận dạng (face cropping), bước thứ hai là tiền xử lý ảnh (preprocessing) bao gồm các bước căn chỉnh ảnh (face image alignment) và chuẩn hóa ánh sáng (illumination normalization) (ở đây tôi đang nói tới các ảnh có góc nhìn thẳng – frontal view face image), tiếp đến là bước trích chọn đặc điểm (feature extraction), ở bước này một phương pháp trích chọn đặc điểm nào đó (mẫu nhị phân cục bộ – Local Binary Pattern – LBP, Gabor wavelets, …) sẽ được sử dụng với ảnh mặt để trích xuất các thông tin đặc trưng cho ảnh, kết quả là mỗi ảnh sẽ được biểu diễn dưới dạng một vector đặc điểm (feature vector), bước tiếp theo là bước nhận dạng (recognition) hay phân lớp (classification), tức là xác định danh tính (identity) hay nhãn (label) của ảnh – đó là ảnh của ai. Ở bước classification, thường thì phương pháp k-láng giềng gần nhất (k-nearest neighbor:kNN) sẽ được sử dụng, thực tế cho thấy việc dùng SVM (Support Vector Machine) không mang lại hiệu quả cao hơn mà còn chậm hơn. Dữ liệu cho một hệ thống nhận dạng mặt được chia làm 3 tập: tập huấn luyện (training set), tập tham chiếu (reference set hay gallery set) và tập để nhận dạng (probe set hay query set, đôi khi còn gọi là test set). Trong nhiều hệ thống, tập training trùng với tập reference. Tập training gồm các ảnh được dùng để huấn luyện (hay học-learning), thông thường tập này được dùng để sinh ra một không gian con (projection subspace) là một ma trận và phương pháp hay được sử dụng là PCA (Principal Component Analysis), WPCA (Whitened PCA), LDA (Linear Discriminant Analysis), KPCA (Kernel PCA). Tập reference gồm các ảnh đã biết danh tính được chiếu (projected) vào không gian con ở bước training. Bước training nhằm 2 mục đích: giảm số chiều (dimension reduction) của các vector đặc điểm (feature vector) vì các vector này thường có độ dài khá lớn (vài nghìn tới vài trăm nghìn) nên nếu để nguyên thì việc tính toán sẽ rất rất lâu, thứ hai là làm tăng tính phân biệt (discriminative) giữa các ảnh khác lớp (định danh khác nhau), ngoài ra có thể làm giảm tính phân biệt giữa các ảnh thuộc về một lớp (tùy theo phương pháp, ví dụ như Linear Discriminant Analysis LDA- còn gọi là Fisher Linear Discriminant Analysis-Fisherface là một phương pháp làm việc với tập training mà mỗi đối tượng có nhiều ảnh mặt ở các điều kiện khác nhau). Sau khi thực hiện chiếu tập reference vào không gian con, hệ thống lưu lại kết quả là một ma trận với mỗi cột của ma trận là một vector tương ứng với ảnh (định danh đã biết) để thực hiện nhận dạng (hay phân lớp). Nhận dạng (hay phân lớp) được thực hiện với tập các ảnh probe, sau khi tiền xử lý xong, mỗi ảnh sẽ được áp dụng phương pháp trích chọn đặc điểm (như với các ảnh thuộc tập training và reference) và được chiếu vào không gian con. Tiếp đến việc phân lớp sẽ dựa trên phương pháp k-NN, định danh của một ảnh cần xác định sẽ được gán là định danh của ảnh có khoảng cách (distance) gần với nó nhất. Ở đây cần lưu ý là mỗi ảnh là một vector nên có thể dùng khái niệm hàm khoảng cách giữa hai vector để đo sự khác biệt giữa các ảnh.

Các thách thức đối với nhận dạng mặt: hiện nay các vấn đề sau được coi là thách thức lớn (chưa có phương pháp tốt) đối với nhận dạng mặt:

+ vấn đề hướng (pose variations), các kết quả với các ảnh có hướng thay đổi (>45 độ, không phải chính diện) còn khá khiêm tốn, có lẽ 3D là một hướng giải quyết.

+ vấn đề ảnh có độ phân giải thấp (low resolution): ảnh thu được từ các camera giám sát (surveillance camera) thường có kích thước và chất lượng rất rất thấp, các kết quả nghiên cứu về lĩnh vực này còn chưa nhiều.

+ làm việc với dữ liêu video (video based face recognition): với sự phát triển của các phương tiện multimedia, thông tin mặt người trong các dữ liệu video là vô cùng nhiều, tuy nhiên hầu hết các phương pháp nhận dạng vẫn làm việc với ảnh tĩnh trích xuất từ dữ liệu video, chưa có phương pháp tốt tận dụng hết ưu thế của dữ liệu video.

+ các hệ thống cực lớn (very large scale systems): các cơ sở dữ liệu (CSDL) ảnh mặt được test bởi các nhà nghiên cứu còn khá nhỏ (vài trăm tới vài chục nghìn ảnh mặt), tuy nhiên trên thực tế các CSDL có thể rất lớn, ví dụ CSDL ảnh mặt của cảnh sát của một nước có thể chứa từ hàng triệu tới hơn 1 tỉ ảnh …

+ aging condition: việc nhận dạng ảnh mặt thay đổi theo thời gian thực sự vẫn còn là một vấn đề lớn ngay cả đối với khả năng nhận dạng của con người.

+ illumination (ánh sáng): là một trong những biggest challenges của nhận dạng mặt, chưa có phương pháp tốt cho các ảnh chụp ở điều kiện out door unconstrained.

Nguồn gốc của các thách thức trên là do tập training thường chỉ có một ảnh cho mỗi đối tượng (lớp) với các điều kiện cố định, trong khi tập probe lại gồm các ảnh ở các điều kiện khác (như đã liệt kê ở trên), làm gia tăng sự khác biệt giữa ảnh training, gallery và probe.

Nghiên cứu về nhận dạng mặt: vì có nhiều bước và còn nhiều thách thức nên có thể lựa chọn một khía cạnh trong một bước để tiến hành, ví dụ như chỉ nghiên cứu về illumination normalization, hay chỉ làm với ảnh low resolution, nhận dạng cảm xúc của khuôn mặt, hoặc thậm chí cụ thể hơn nữa, chỉ làm về face image alignment … Tuy nhiên hầu hết các nhà nghiên cứu đều tập trung vào bước feature extraction, tức là tìm một cách thức trích chọn đặc điểm hiệu quả cho nhận dạng mặt.

CSDL cho nhận dạng mặt: điều đầu tiên cần thiết khi nghiên cứu về nhận dạng mặt là phải có các CSDL ảnh mặt và cách thức chuẩn (standard protocol) để thực hiện test trên các CSDL đó, vì còn phải so sánh với các kết quả đã có khác trên các CSDL đó. ORL là một CSDL nhỏ và cũ của AT&T nhưng khá thích hợp với người mới bắt đầu. Nó gồm 400 ảnh của 40 người, mỗi người có 10 ảnh với các biểu hiện (facial expression) và điều kiệu về hướng, ánh sáng khác nhau. Các CSDL khác nên test là: FERET, FRGC v2.0, SCFace, LFW, AR. Trong các CSDL này, ảnh mặt đã được chuẩn bị sẵn, tức là chúng ta không cần thực hiện bước face detection, chỉ cần dựa vào các thông tin được cung cấp để thực hiện cắt phần ảnh mặt cần thiết cho nhận dạng. Để download database ORL, các bạn có thể truy cập tới địa chỉ này. Lưu ý là CSDL này gồm các ảnh ở format .pgm, format này hơi lạ với các chương trình đọc ảnh của Windows, nhưng với Matlab thì không có vấn đề gì, các bạn có thể save lại thành định dạng .bmp hoặc .jpg để có thể nhận thấy rõ ràng hơn.

Trong bài viết này, tôi chỉ nói về PCA dành cho nhận dạng mặt theo phương pháp eigenface, sẽ không có các bước chuẩn hóa ánh sáng và trích chọn đặc điểm. CSDL được sử dụng minh họa là ORL, tập training trùng với tập reference và mỗi lớp (mỗi người) sẽ chọn n=1,2,3,4 hoặc 5 ảnh đưa vào tập training, số còn lại (10-n cho mỗi lớp) sẽ được dùng cho tập probe.

Phương pháp PCA cho nhận dạng mặt (eigenface): Mỗi ảnh có kích thước WxH (kích thước phổ biến là 128×128) sẽ được chuyển thành một vector cột có độ dài W*H (cho cả tập training và probe) (gọi là các vector Xi). Ở bước training, một vector trung bình của tất cả các ảnh training sẽ được tính (vector M), sau đó mỗi vector thuộc tập training sẽ bị mean-subtracted: Xi=Xi-M, ma trận hiệp phương sai được tính bằng C = A’*A, trong đó A’ là ma trận chuyển vị của A và A =[X1, X2, …Xk] là ma trận với các cột là các vetor Xi, k là số ảnh thuộc tập training (k=40*n với CSDL ORL). A sẽ có kích thước là (W*H)xk, còn ma trận C sẽ có kích thước là kxk, do k nhỏ hơn W*H rất nhiều nên việc tính k vector riêng (eigenvectors) và giá trị riêng tương ứng (eigenvalues) của C là dễ. Ta sẽ tìm được k giá trị riêng tương ứng với k vector riêng của C. Các vector riêng được sắp xếp theo thứ tự giảm dần của các giá trị riêng tương ứng, việc sử dụng tất cả các vector riêng là không cần thiết nên chỉ có N (N viết hoa nhé) giá trị riêng đầu tiên tương ứng với N vector riêng được sử dụng (chính về thế nên phương pháp này được gọi là phân tích thành phần chính-Principal Component Analysis). N vector riêng này sẽ tạo thành một ma trận có kích thước (W*H)xN là ma trận của không gian con nhận được (ta gọi ma trận này là Cp). Tiếp đến các ảnh thuộc tập training (ở đây cũng là tập reference) sẽ được chiếu vào không gian con bằng phép nhân: Ap = Cp’ * A, tương tự các ảnh của tập probe sẽ được chiếu vào không gian con bằng phép nhân: Bp = Cp’*B. Ap và Bp sẽ có kích thước tương ứng là NxNoTrain (NoTrain là số ảnh training, tức là bẳng k) và NxNoTest (NoTest là số ảnh của tập probe), nghĩa là mỗi ảnh tương ứng được biểu diễn bẳng một vector cột. Ở bước phân lớp, với mỗi ảnh thuộc tập probe, ta tìm ảnh thuộc tập training gần với nó nhất. Ở bước này các hàm khoảng cách: euclidean, mahalanobis, cosine angle distance đều có thể sử dụng.

Thực chất, ở nguyên bản của phương pháp PCA ma trận C = A*A’, và có kích thước là (W*H)x(W*H), tức là một ma trận rất, rất lớn nên Mathew A. Turk and Alex P. Pentland (tác giả của phương pháp eigenface) đã sử dụng một thủ thuật là tìm N vector riêng vi (i=1..N) và giá trị riêng của ma trận L=A’*A (dễ hơn do ma trận có kích thước nhỏ hơn) sau đó tính N vector riêng của C=A*A’ bằng công thức ui=A*vi.

Việc tìm các vector riêng của ma trận hiệp phương sai C (trên thực tế là với ma trận L) có hai cách: dùng phương pháp eigen decomposition (hàm eig của matlab) hoặc singular value decomposition-SVD (hàm svd của matlab), tuy nhiên svd có vẻ nhanh và cho kết quả tốt hơn so với eig.

Sau đây là bảng tỉ lệ kết quả nhận dạng (Rank-1 Recognition Rate-RR) với số ảnh huấn luyện cho mỗi đối tượng là từ 1->5:

Eigenfaces

Why matlab? Vì matlab nhanh và thích hợp cho việc nghiên cứu, thử nghiệm. Nên nhớ rằng PCA hay một phương pháp nào đó bạn nghĩ ra có thể chưa phải là tốt nhất, vì thế nên việc sử dụng C/C++/C# hay một ngôn ngữ lập trình ứng dụng nào đó để cài đặt là không thực sự cần thiết, bạn sẽ thấy tốc độ cũng không nhanh hơn (thường là chậm hơn, trừ khi bạn dùng GPU hoặc tối ưu mã nguồn), rất mất thời gian và chắc gì thuật toán của bạn đã có hiệu quả đủ tốt để đầu tư công sức cho việc lập trình, với lại một hệ thống nhận dạng mặt có thể chạy trên thực tế gồm rất nhiều bước khác nữa, ở đây bạn mới làm với các ảnh frontal của một database đã có sẵn, vì thế đừng có lăn tăn nhiều.

Cuối cùng, nếu bạn muốn trao đổi về nội dung bài viết hay lấy source code của PCA (eigenface), hãy để email lại qua mục comment của bài viết này, tôi sẽ gửi lại cho bạn qua email.

P/S (ngày 18/08/2014): sau một thời gian dài nhận được nhiều yêu cầu gửi code của nhiều bạn, tôi đã cố gắng nhanh nhất có thể gửi cho hầu hết các bạn với mục đích cung cấp một chút gì đó gọi là cơ sở và hy vọng có sự trao đổi với những ai cùng quan tâm. Nhưng sự trao đổi thì khá ít mà một số câu hỏi kiểu “chạy cái này thế nào?” hay “Sao không thấy gì?” thì phổ biến nên tôi mong muốn các bạn hãy đọc kỹ, xem kỹ trước khi yêu cầu và theo đuổi lĩnh vực này vì nhận dạng mặt và phương pháp eigenfaces không phải là những thứ dễ dàng (để hiểu và code) theo kiểu google search, download, click and get the results.

Update ngày 24/06/2015:

Face recognition with OpenCV tutorial.

Update ngày 17/06/2013:

More about eigenfaces

Java code

OpenCV based source code 1

OpenCV source code 2

C# based PCA source code 1

C# based PCA for shape matching

EmguCV C# tutorial

EgmuCV C# face detection

EgmuCV C# multiple faces detection and recognition

Eye tracking 1

Eye tracking 2

OpenCV based Eye tracking 3

OpenCV based face and eyes detection