Hôm trước, mình có nhận được một câu hỏi tưởng chừng đơn giản nhưng lại rất hóc búa từ một bạn đọc:
Anh ơi, tại sao Facebook Messenger và Snapchat có thể làm các filter ngầu lòi, có thể gắn râu, gắn tai thỏ, đội mũ cho người dùng qua camera vậy.
Đằng sau một tính năng vui vui, đơn giản như vậy lại là một nền tảng các công nghệ cực kì phức tạp từ facial recognition cho đến image processing, hoàn toàn… không dễ một xíu nào.
Vì thế, trong bài này, chúng ta cùng tìm hiểu cơ chế hoạt động của chúng, sau đó làm một ứng dụng tương tự mang tên … gắn râu Sơn Tùng nhé.
Series này gồm 3 phần:
- Cơ chế hoạt động của các filter Snapchat và Facebook Messenger
- Làm quen với các thư viện và API cần sử dụng
- Gắn râu bằng cách kết hợp Face Detection + Image Processing và… Toán Học
Đây là ảnh gốc Sơn Tùng trước khi được gắn râu:
Còn đây là ảnh Sơn Tùng sau khi đã gắn râu nhờ ứng dụng:
Thú vị chưa nào? Chúng ta cùng bắt đầu nhé!
Họ đã làm điều đó… như thế nào?
Trong lập trình, khi muốn giải quyết một vấn đề, chúng ta phải biết cách tách nó thành những vấn đề nhỏ hơn, sau đó giải quyết từng vấn đề một.
Do vậy, trước khi cắm đầu vào code, mình sẽ giải thích cơ chế hoạt động của các filter trên Snapchat, Messenger trước nhé.
Đầu tiên, các bạn phải hiểu cách máy tính lưu trữ file ảnh và video. Một video bao gồm nhiều frame (khoảng 24 frame hoặc 30 frame cho mỗi giây).

- Khi các bạn dùng filter của Snapchat, Messenger, chúng sẽ đọc từng frame từ camera. Sau đó sử dụng thuật toán để tìm ra khuôn mặt (face detection) của bạn trong frame đó.
- Đến khi đã tìm được mặt của bạn, hệ thống tiếp tục dùng thuật toán để tìm những đặc điểm trên khuôn mặt của bạn như mắt, mũi, miệng (face landmark detection).
- Sau khi đã xác định được mắt, mũi, miệng, trán … hệ thống sẽ gắn thêm ảnh vào các frame này.
- Các frame này sẽ được hiển thị lại thành video trên camera. Tốc độ xử lý phải vô cùng nhanh (24-30 frame/s). Kết quả là các bạn sẽ thấy mặt mình được gắn hoa, gắn mũi chó, đeo kính.
Ứng dụng mà chúng ta sẽ làm
Như mình đã nói, để thực hiện việc gắn râu, gắn hoa,… thông qua camera, tốc độ xử lý phải vô cùng nhanh (24-30 frame/s).
Thông thường, các ứng dụng này sẽ có một bộ thư viện nhận diện, chứa các thuật toán nhận diện khuôn mặt chạy offline ngay trên di động.
Tuy nhiên, do … lười, mình sẽ tái sử dụng lại API nhận diện khuôn mặt của Microsoft, thứ mà mình đã sử dụng để xây dựng ứng dụng Nhận Diện Idol.

Hạn chế của API này là phải sử dụng internet, gọi API thông qua HTTP call. Do vậy ứng dụng của mình không thể xử lý video ngầu như Messenger, Snapchat mà chỉ có thể xử lý ảnh thường và ảnh GIF.
Ứng dụng Gắn Râu Sơn Tùng sẽ hoạt động như sau:
- Tách ảnh GIF ra thành nhiều ảnh nhỏ hơn
- Dùng Microsoft Cognitive API để xác định khuôn mặt trong ảnh
- Dùng thuật toán tự viết để gắn râu vào ảnh
- Ghép các ảnh đã gắn râu lại thành ảnh GIF hoàn chỉnh
Đồ chơi cần chuẩn bị
Để làm ứng dụng này, ta không cần cài đặt tùm lum gì cho phức tạp, chỉ cần NodeJS là được. Nếu bạn nào đã làm theo series Nhận Diện Idol thì có thể dễ dàng làm theo bài viết này.
1. Trước tiên, chúng ta cần API Key của Microsoft Face API để có thể gọi API đó.
Các bạn làm theo hướng dẫn trong bài này nhé: https://toidicodedao.com/2017/01/17/series-nhan-dien-idol-phan-3-thu-thap-du-lieu/. Nhớ chọn FaceAPI nha!

2. Cài đặt NodeJS nếu chưa cài: https://nodejs.org/en/download. Bản 8.11 hay 9.11 đều được nha.
3. Chúng ta khởi tạo project NodeJS bằng cách tạo 1 folder mới.
Dùng command line để vào folder đó. Sau đó gõ “npm init“, sau đó “npm install –save-dev request request-promise jimp” để cài các thư viện cần thiết.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
npm init | |
npm install –save-dev request request-promise jimp |
4. Chúng ta tạo file index.js, bắt đầu viết code gọi Microsoft Cognitive API thông qua HTTP để nhận diện khuôn mặt từ url ảnh nhé.
Các bạn nhớ thay key của bạn ở dòng số 4 nha.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const rp = require('request-promise'); | |
async function detectImage(source) { | |
const subscriptionKey = "[thay bằng key của bạn]"; | |
const uri = "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect"; | |
const options = { | |
uri, | |
qs: { | |
returnFaceId: true, | |
returnFaceLandmarks: true, // Nhận diện các điểm trên khuôn mặt | |
}, | |
method: 'POST', | |
headers: { | |
'Ocp-Apim-Subscription-Key': subscriptionKey | |
}, | |
body: { | |
url: source | |
}, | |
json: true | |
}; | |
const result = await rp(options); | |
return result; | |
} | |
(async () => { | |
const imageUrl = 'https://pbs.twimg.com/media/DWr05hUXcAA9s8n.jpg' | |
const result = await detectImage(imageUrl); | |
console.log(JSON.stringify(result, null, 2)); | |
})(); |
5. Chúng ta đưa url sau vào để thử nhận diện: https://pbs.twimg.com/media/DWr05hUXcAA9s8n.jpg.

Các bạn có thể thay bằng ảnh bất kì nhé! Hi vọng hệ thống ko nhận nhầm 2 cái bánh bao phía dưới.
6. Sau khi viết code xong, ta vào command line gõ “node index.js“, nếu thấy kết quả trả về là bạn đã thành công rồi nhé!

Tạm kết
Tới đây bài cũng đã dài rồi. Chúng ta đã tìm hiểu cách thức các filter hoạt động, cũng như setup sẵn sàng đồ chơi cần thiết để bắt đầu viết code.
Ở phần sau, chúng ta sẽ tiếp tục đi sâu vào mảng image processing, xây dựng ứng dụng Gắn Râu JAV Idol, nhầm, Gắn Râu Sơn Tùng nhé!
cảm ơn anh đã viết bài này!
LikeLike
A cứ đưa idol lên là e lại mất tập trung chuyên môn =))
LikeLike
Hi Hoàng, mình đã làm theo các bước, nhưng khi chạy nó có lỗi là “statusCode”:404,”message”:”Resource not found”. Key và link endpoint của mình như bên dưới, bạn kiểm tra lại giúp với được không?
`Endpoint: https://westcentralus.api.cognitive.microsoft.com/vision/v1.0
Key 1: d7c338e9e257499d83323eb97916f5a8
Key 2: 36c00cf64736486b94e7fef6c5dc0d38
Cảm ơn.
LikeLike
À bạn xem kĩ file code nhé.
URL đúng để gọi API là: https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect
LikeLike
Document đầy đủ ở đây nha: https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236
LikeLike
Bây giờ ko rõ face detection bằng Viola–jones còn dc dùng nhiều ko nhỉ? Bây giờ thấy mn toàn nói nhiều về SSD vơi YOLO, mjh lại thấy RCNN dễ thông hơn
LikeLike