Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK

Giới thiệu Face Detection API trên Android

Read Time: 14 mins

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Được giới thiệu cùng với các thư viện Vision trong Play Services 8.1, Face Detection API giúp một nhà phát triển dễ dàng phân tích một video hoặc hình ảnh để xác định khuôn mặt của con người. Một khi bạn đã có một danh sách các khuôn mặt được phát hiện trên một hình ảnh, bạn có thể thu thập thông tin về từng khuôn mặt, chẳng hạn như hướng, khả năng người đó đang cười, có thể có ai đó đang mở hoặc nhắm mắt, và các landmark cụ thể trên khuôn mặt của họ.

Thông tin này có thể hữu ích cho nhiều ứng dụng khác nhau, chẳng hạn như một ứng dụng camera tự động chụp ảnh khi mọi người trong khung hình đang mỉm cười cùng với đôi mắt của họ đang mở, hoặc để bổ sung cho hình ảnh bằng những hiệu ứng mê mẩn, chẳng hạn như thêm sừng kỳ lân. Điều quan trọng cần lưu ý là Phát hiện Khuôn mặt không phải là nhận diện khuôn mặt. Mặc dù thông tin có thể thu thập được về một một khuôn mặt, nhưng thông tin đó không được được sử dụng bởi thư viện Vision để xác định xem hai khuôn mặt có phải là của cùng một người hay không.

Hướng dẫn này sẽ sử dụng một hình ảnh tĩnh để chạy Face Detection API và thu thập thông tin về những người có trong bức ảnh, đồng thời minh họa thông tin đó bằng đồ họa xếp chồng. Tất cả các code cho hướng dẫn này có thể được tìm thấy trên GitHub.

Example of a silly effect adding a unicorn horn to a faceExample of a silly effect adding a unicorn horn to a faceExample of a silly effect adding a unicorn horn to a face

1. Thiết lập Dự án

Để thêm thư viện Vision vào dự án của bạn, bạn cần import Play Services 8.1 trở lên vào dự án của bạn. Hướng dẫn này chỉ import thư viện Vision của Play Services. Mở tập tin build.gradle của dự án và thêm dòng compile sau đây vào nút dependencies.

Khi bạn đã bao gồm Play Services vào dự án của mình, bạn có thể đóng tập tin build.gradle của dự án và mở AndroidManifest.xml. Bạn cần phải thêm một phần tử meta-data xác định phụ thuộc face dưới nút application của tập tin manifest. Điều này cho phép thư viện Vision biết rằng bạn có kế hoạch phát hiện khuôn mặt trong ứng dụng của bạn.

Khi bạn đã hoàn tất thiết lập AndroidManifest.xml, bạn có thể đóng nó lại. Tiếp theo, bạn cần phải tạo một lớp mới có tên là FaceOverlayView.java. Lớp này mở rộng View và chứa logic cho việc phát hiện khuôn mặt trong dự án, hiển thị ảnh bitmap được phân tích và vẽ bên trên hình ảnh để minh họa các điểm.

Bây giờ, hãy bắt đầu bằng cách thêm các biến thành viên ở trên cùng của lớp và định nghĩa hàm xây dựng. Đối tượng Bitmap sẽ được sử dụng để lưu trữ ảnh bitmap sẽ được phân tích và các đối tượng SparseArray của Face sẽ lưu trữ từng khuôn mặt được tìm thấy trong ảnh bitmap.

Tiếp theo, hãy thêm một phương thức mới bên trong FaceOverlayView được gọi là setBitmap(Bitmap bitmap). Tạm thời, code này chỉ đơn giản là lưu bitmap được truyền đến nó, tuy nhiên sau này bạn sẽ sử dụng phương thức này để phân tích hình ảnh.

Tiếp theo, bạn cần một ảnh bitmap. Tôi đã kèm theo một hình trong dự án mẫu trên GitHub, nhưng bạn có thể sử dụng bất kỳ hình ảnh nào mà bạn thích để làm việc với tính năng Phát hiện Khuôn mặt và xem cái nào hoạt động và cái nào không hoạt động. Khi bạn đã chọn được một hình ảnh, hãy đặt nó vào thư mục res/raw. Hướng dẫn này sẽ giả định rằng hình ảnh này được đặt tên là face.jpg.

Sau khi bạn đã đặt hình ảnh của bạn vào thư mục res/raw, hãy mở res/layout/activity_main.xml. Bố cục này chứa một tham chiếu đến FaceOverlayView để nó được hiển thị trong MainActivity.

Sau khi đã xác định được bố cục, hãy mở MainActivity và thiết lập FaceOverlayView từ onCreate(). Bạn thực hiện việc này bằng cách tham chiếu đến view, đọc tập tin hình ảnh face.jpg từ thư mục raw dưới dạng một input stream, và chuyển đổi nó thành một bitmap. Một khi bạn đã có bitmap, bạn có thể gọi setBitmap trên FaceOverlayView để truyền hình ảnh vào view tuỳ biến của bạn.

2. Nhận biết Khuôn mặt

Bây giờ dự án của bạn đã được thiết lập xong, đã đến lúc để bắt đầu phát hiện khuôn mặt. Trong setBitmap(Bitmap bitmap) bạn cần tạo một FaceDetector. Điều này có thể được thực hiện bằng cách sử dụng một FaceDetector.Builder, cho phép bạn định nghĩa nhiều tham số ảnh hưởng đến tốc độ phát hiện khuôn mặt và các dữ liệu khác mà FaceDetector sẽ tạo ra.

Các cài đặt mà bạn chọn tuỳ thuộc vào những gì mà bạn đang cố gắng thực hiện trong ứng dụng của bạn. Nếu bạn kích hoạt tìm kiếm landmark, thì khuôn mặt sẽ được phát hiện chậm hơn. Cũng như hầu hết các thứ trong lập trình, mọi thứ đều có những sự cân bằng của nó. Để tìm hiểu thêm về các tùy chọn sẵn có cho FaceDetector.Builder, bạn có thể tham khảo tài liệu chính thức trên trang web nhà phát triển Android.

Bạn cũng cần phải kiểm tra xem FaceDetector có đang hoạt động hay không. Khi một người dùng lần đầu sử dụng tính năng phát hiện khuôn mặt trên thiết bị của họ, thì Play Services cần phải đi ra ngoài và lấy về một bộ nhỏ thư viện gốc để xử lý yêu cầu của ứng dụng của bạn. Mặc dù việc này hầu như luôn được thực hiện trước khi ứng dụng của bạn đã khởi động xong, nhưng điều quan trọng là phải xử lý tình huống khi mà việc đó thất bại.

Nếu FaceDetector hoạt động, thì bạn có thể chuyển đổi bitmap của bạn thành một đối tượng Frame và truyền nó vào detector để thu thập dữ liệu về khuôn mặt trong tấm hình. Khi bạn đã hoàn tất, bạn sẽ cần phải giải phóng detector để tránh bị rò rỉ bộ nhớ. Khi bạn đã hoàn tất việc phát hiện khuôn mặt, hãy gọi invalidate() để kích hoạt việc vẽ lại view.

Bây giờ bạn đã phát hiện được khuôn mặt trong tấm hình của bạn, đã đến lúc sử dụng chúng. Đối với ví dụ này, bạn chỉ cần vẽ một hộp màu xanh lá cây xung quanh mỗi khuôn mặt. Vì invalidate() được gọi sau khi khuôn mặt đã được phát hiện, nên bạn có thể thêm tất cả các logic cần thiết vào onDraw(Canvas canvas). Phương thức này đảm bảo rằng ảnh bitmap và khuôn mặt được thiết lập, sau đó vẽ bitmap lên trên canvas, và sau đó vẽ một cái hộp xung quanh mỗi mặt.

Vì các thiết bị khác nhau có kích thước màn hình khác nhau, nên bạn cũng sẽ theo dõi kích thước co giãn của bitmap để toàn bộ hình ảnh luôn được nhìn thấy trên thiết bị và tất cả các lớp phủ được vẽ một cách thích hợp.

Phương thức drawBitmap(Canvas canvas) vẽ ảnh bitmap của bạn lên trên canvas và điều chỉnh kích thước hình ảnh một cách hợp lý đồng thời trả về một hệ số co giãn kích thước khác của bạn một cách chính xác.

Phương thức drawFaceBox(Canvas canvas, double scale) có một chút thú vị. Mỗi khuôn mặt được phát hiện và lưu lại có một giá trị vị trí ở trên và ở bên trái mỗi khuôn mặt. Phương thức này sẽ lấy vị trí đó và vẽ một hình chữ nhật màu xanh lá cây từ nó để bao quanh mỗi khuôn mặt dựa trên chiều rộng và chiều cao của nó.

Bạn cần phải xác định đối tượng Paint của bạn và sau đó lặp qua từng Face trong SparseArray để tìm vị trí, chiều rộng và chiều cao của nó, và vẽ hình chữ nhật trên canvas bằng thông tin đó.

Lúc này, bạn sẽ có thể chạy ứng dụng của bạn và nhìn thấy hình ảnh của bạn với các hình chữ nhật xung quanh mỗi khuôn mặt đã được phát hiện. Điều quan trọng cần lưu ý là Face Detection API vẫn còn khá mới mẻ vào thời điểm viết bài này và nó có thể không phát hiện ra tất cả các khuôn mặt. Bạn có thể tinh chỉnh một số cài đặt trong đối tượng FaceDetector.Builder để hy vọng là thu thập được thêm nhiều dữ liệu, mặc dù điều đó không đảm bảo.

Faces detected and bound by a drawn rectangleFaces detected and bound by a drawn rectangleFaces detected and bound by a drawn rectangle

3. Hiểu về Landmark

Landmark là những điểm đáng chú ý trên một khuôn mặt. Face Detection API không sử dụng landmark để phát hiện một khuôn mặt, mà thay vào đó phát hiện một khuôn mặt trong trạng thái nguyên vẹn của nó trước khi tìm kiếm landmark. Đó là lý do tại sao việc khám phá landmark là một thiết lập không bắt buộc có thể được kích hoạt thông qua FaceDetector.Builder.

Bạn có thể sử dụng những landmark này như là một nguồn thông tin bổ sung, chẳng hạn như đôi mắt của đối tượng nằm ở đâu, từ đó bạn có thể tương tác một cách thích hợp trong ứng dụng của bạn. Có mười hai landmark mà bạn có thể tìm thấy:

  • mắt trái và phải
  • tai trái và phải
  • vành tai trái và phải
  • sống mũi
  • má trái và phải
  • khoé miệng trái và phải
  • sống miệng

Các landmark sẵn có phụ thuộc vào góc của khuôn mặt được phát hiện. Ví dụ, một người nào đó quay mặt sang một bên sẽ chỉ có một con mắt là nhìn thấy được, có nghĩa là mắt kia sẽ không thể phát hiện được. Bảng dưới đây phác hoạ những landmark nào sẽ được phát hiện dựa trên góc Euler Y (hướng trái hoặc phải) của khuôn mặt.

Euler Y Landmark Hiện hữu
< -36° mắt trái, miệng trái, tai trái, sống mũi, má trái
-36° đến -12° miệng bên trái, sống mũi, phía dưới miệng, mắt phải, mắt trái, má trái, vành tai trái
-12° đến 12° mắt phải, mắt trái, sống mũi, má trái, má phải, miệng trái, miệng phải, phía dưới miệng
12° đến 36° bên phải miệng, sống mũi, phía dưới miệng, mắt trái, mắt phải, má phải, vành tai phải
> 36° mắt phải, bên phải miệng, tai phải, sống mũi, má phải

Các landmark cũng cực kỳ dễ sử dụng trong ứng dụng của bạn vì bạn đã bao gồm chúng trong quá trình phát hiện khuôn mặt. Bạn chỉ cần gọi getLandmarks() trên một đối tượng Face để lấy về một List chứa các đối tượng Landmark mà bạn có thể làm việc với chúng.

Trong hướng dẫn này, bạn sẽ vẽ một vòng tròn nhỏ trên mỗi landmark đã phát hiện bằng cách gọi một phương thức mới, drawFaceLandmarks(Canvas canvas, double scale), từ onDraw(canvas canvas) thay cho drawFaceBox(Canvas canvas, double scale). Phương thức này lấy vị trí của mỗi landmark, điều chỉnh nó phù hợp độ co giản của bitmap, và sau đó hiển thị vòng tròn landmark.

Sau khi gọi phương thức này, bạn sẽ nhìn thấy các vòng tròn nhỏ màu xanh lá cây ở trên những khuôn mặt được phát hiện như trong ví dụ dưới đây.

Circles placed over detected facial landmarksCircles placed over detected facial landmarksCircles placed over detected facial landmarks

4. Dữ liệu Khuôn mặt Bổ sung

Mặc dù vị trí của một khuôn mặt và các landmark của nó là rất hữu ích, nhưng bạn còn có thể tìm ra thêm thông tin về từng khuôn mặt được phát hiện trong ứng dụng của bạn thông qua một số phương thức được tích hợp từ đối tượng Face. Các phương thức getIsSmilingProbability(), getIsLeftEyeOpenProbability()getIsRightEyeOpenProbability() cố gắng xác định xem đôi mắt đang mở hay nhắm hay một người nào đó có đang cười bằng cách trả về một float từ dãy 0.0 cho đến 1.0. Càng gần với 1.0, thì người đó càng có khả năng đang mỉm cười hoặc có mắt trái hoặc mắt phải đang mở.

Bạn cũng có thể tìm ra góc của khuôn mặt trên các trục Y và Z của một hình ảnh bằng cách kiểm tra các giá trị Euler của nó. Tuy nhiên, giá trị Z Euler sẽ luôn luôn được báo cáo, bạn phải sử dụng chế độ chính xác khi phát hiện khuôn mặt để nhận được giá trị X. Bạn có thể thấy ví dụ về cách lấy các giá trị này trong đoạn code sau đây.

Phần Tóm tắt

Trong hướng dẫn này, bạn đã được tìm hiểu về một trong những thành phần chính của thư viện Vision của Play Services, Face Detection. Bây giờ thì bạn đã biết cách phát hiện các khuôn mặt trong một hình ảnh tĩnh, cách thu thập thông tin và tìm ra các landmark quan trọng cho mỗi khuôn mặt.

Sử dụng những gì bạn đã học được, bạn sẽ có thể thêm một số tính năng tuyệt vời vào các ứng dụng của riêng bạn để thêm những điều thú vị vào ảnh tĩnh, theo dõi khuôn mặt trong một video, hoặc bất cứ điều gì khác mà bạn có thể tưởng tượng ra.

Advertisement
Did you find this post useful?
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.