- Thu được shape khởi tạo chính là khuôn mặt trung bình sau khi thực hiện phép align.
Lưu ý, vì hình chữ nhật tạo ra bởi thuật toán Viola-Jones có kích thước lớn hơn khuôn mặt thật nên sẽ làm ảnh hưởng đến kết quả của việc kết xuất khuôn mặt khởi tạo. Vì vậy, trước khi tiến hành phép align, ta cần thu nhỏ hình chữ nhật đến một kích thước phù hợp. Trong đồ án, hình chữ nhật được thu nhỏ 20%.
b. Kết xuất shape kiểm thử:
Ở bước này, nhiệm vụ của ta là dựa vào shape khởi tạo có được từ bước trên để kết xuất shape kiểm thử. Trước khi bắt đầu, ta thêm vào một tham số hằng cho chương trình là nPixSearch [19]:
- nPixSearch là tham số thể hiện số pixel sẽ được chọn để lấy mẫu profile dọc theo đỉnh của shape khởi tạo. Hay nói cách khác, đây chính là độ dài whisker của shape khởi tạo. Whisker này không phải là whisker chứa thông tin của profile của đỉnh shape khởi tạo như whisker trong bước huấn luyện, mà là whisker chứa các pixel ảnh sẽ được chọn để làm điểm khởi tạo. Ví dụ, nPixSearch = 5, ta sẽ tiến hành lấy mẫu profile của pixel thứ -2 đến pixel thứ +2 tính từ đỉnh đang xét của shape khởi tạo.
Cách tạo profile cho một điểm, cũng như cách vẽ whisker đã được trình bày ở những phần trên. Ở đây ta chọn nPixSearch = 15. Có thể tiến hành thay đổi tham số này để chọn ra kết quả tốt nhất.
Sau khi chọn được tham số thích hợp, ta tiến hành đánh giá các pixel đã lấy mẫu bằng cách tính khoảng cách Mahalanobis theo công thức (2.8). Dựa trên khoảng cách Mahalanobis tính được, ta chọn ra profile tốt nhất và lấy pixel tương ứng với profile đó làm điểm kiểm thử. Làm tương tự với các điểm khác, ta có được tập hợp các điểm kiểm thử tạo thành shape kiểm thử.
52
c. Kết xuất ra khuôn mặt chính thức:
Việc kết xuất khuôn mặt chính thức dựa trên việc tinh chỉnh các lỗi sai shape kiểm thử sao cho các đỉnh trên shape kiểm thử khớp với khuôn mặt trong ảnh.
Khuôn mặt chính thức được sinh ra từ công thức như đã trình bày ở phần trước:
= ̅ + Φ
Mấu chốt của công thức này chính là việc tìm vector tham số b. Việc tìm nó đã
được trình bày khá chi tiết bằng thuật toán ở phần 2.2.3.b.
Trước khi bắt đầu thuật toán tìm b, ta cần phải tìm ra ma trận hiệp phương sai Φ,
các vector riêng và trị riêng của nó. Việc tính toán ma trận hiệp phương sai có thể được thực hiện dễ dàng bằng công thức (2.11). Chỉ lưu ý một điều, vì chúng ta lưu trữ các shape dưới dạng vector có kích thước (2nVer × 1), nên ma trận hiệp phương sai của chúng ta sẽ có kích thước (2nVer × 2nVer).
Sau khi có ma trận hiệp phương sai, ta tính trị riêng và vector riêng của nó. Hiện nay, đã có nhiều thuật toán hỗ trợ trong việc tìm trị riêng và vector riêng của ma trận mà điển hình nhất là thuật toán QR cùng nhiều thuật toán cải tiến về mặt tốc độ. Trong khuôn khổ của đồ án, ta sẽ không bàn luận quá sâu vào cách thức tìm kiếm cũng như vấn đề giải thuật cho việc tìm trị riêng và vector riêng.
Các thuật toán tìm trị riêng và vector riêng đã được tích hợp vào nhiều thư viện mã nguồn mở nên việc sử dụng chúng là khá dễ dàng. Tuy nhiên, việc tiếp cận với các bộ thư việc mã nguồn mở, các vấn đề sử dụng cũng như biên dịch chúng trên nền window là khá khó khăn. Vì vậy, xin được đề xuất sử dụng một bộ thư viện hỗ trợ trong việc tính toán trị riêng và vector riêng bằng một thư viện
Bluebit.MatrixLibrary xây dựng trên nền C#.
Sau đây là đoạn chương trình tính trị riêng và vector riêng:
Matrix conmat;// khai báo biến ma trận conmat
int n_conmat, num;
CVector V; // Khai báo vector V
// Load ma trận hiệp phương sai
LoadMat(@"resource/mean_conmat_shape.txt", out n_conmat, out conmat);
Eigen E = new Eigen(conmat); // load ma trận hiệp phương sai vào đối tượng tính toán trị riêng và vector riêng
V = E.Eigenvalues; // tính trị riêng và lưu vào vector V
num = GetNumEi(V); // lấy số lượng trị riêng // Lưu lại các trị riêng
SaveEigenvalues(@"resource/eigenvalues_conmat_shape.txt", V.Length, num, V);
CMatrix mat_EV = E.Eigenvectors; // tính các vector riêng và lưu thành ma trận vector riêng
// lưu ma trận vector riêng
SaveEigenvectorMatrix(@"resource/eigenvectors_conmat_shape.txt", mat_EV.Rows, num, mat_EV);
53
Sau khi tính được trị riêng và vector riêng, ta tiến hành tìm vector tham số b theo thuật toán đã trình bày ở 2.2.3.b. Thế b vào công thức (2.9), ta suy ra được khuôn mặt chính thức cần tìm.
Hình 3.26 Result Window
3.3 Xử Lí Dữ Liệu Chuyển Động Và Áp Lên Mô Hình 3D
Sau khi hoàn thành khâu phát hiện các điểm đặc trưng của khuôn mặt. Ta xem nó như là các điểm đánh dấu vật lí trên các phương pháp MoCap truyền thống. Việc tiếp theo cần làm là ghi lại dữ liệu chuyển động của các điểm này qua các frame ảnh của video để tiến hành áp cử động lên mô hình 3D.
Để thực hiện công việc này, ta ghi dữ liệu chuyển động theo cấu trúc file “c3d”. Ta chọn cấu trúc file này vì đây là cấu trúc file khá phổ biến đã được sử dụng từ lâu. Hơn nữa, cấu trúc file này có tài liệu mô tả chi tiết [28] và được hỗ trợ bằng các chương trình xử lí 3D thông dụng hiện tại.
File c3d là một file nhị phân được chia thành các block với độ dài 512 bytes. Trong đó, phần header gồm các thông tin sau [18][28]:
- Số lượng điểm đánh được sử dụng trong quá trình MoCap. - Số lượng các khoảng cách analog được sử dụng ở mỗi frame. - Chỉ số frame đầu tiên.
- Chỉ số frame cuối cùng. - Độ lệch cho phép lớn nhất. - Hệ số tỉ lệ 3 chiều.
- Số lượng block dữ liệu đầu tiên. - Số lượng mẫu analog trong mỗi frame
54
- Nhãn chú thích dữ liệu - Dữ liệu sự kiện.
Những block dữ liệu tiếp theo sẽ chứa thông tin về vị trí của các điểm đánh dấu thể hiện trên mỗi frame. Lưu ý, các dữ liệu tọa độ lấy trực tiếp trên frame chỉ là dữ liệu 2D. Ta cần phải chuyển sang dữ liệu 3D tương ứng để áp lên môi trường 3D. Sau khi có được dữ liệu chuyển động được ghi trong file c3d, ta sử dụng chương trình Autodesk Motion Builder để truy xuất cũng như biểu diễn file này.
Để thể hiện chuyển động khuôn mặt đã bắt được, ta cần có một file c3d chuẩn và một mô hình khuôn mặt 3D. Ta có thể sử dụng các mô hình sẵn có trên mạng hoặc mô hình demo có sẵn trong chương trình. Import file c3d vừa tạo và mapping các điểm đánh dấu lên khuôn mặt, chương trình sẽ tự động xử lí chuyển động theo như dữ liệu đã ghi trong file c3d.