Quay lại Hồ sơ

Nghiên cứu điển hình

Bài viết đi sâu hơn về một số dự án trong hồ sơ: quy trình xử lý (pipeline), toán học, và bản demo.

Thị giác máy tính
Ghép ảnh đa camera thời gian thực
Tháng 6/2022 – Tháng 9/2022
Ước lượng độ sâu
Định vị công nhân tại đường sắt
Tháng 9/2022 – Tháng 3/2023
Ước lượng độ sâu
PseudoLiDAR thời gian thực
Tháng 3/2023 – Tháng 11/2023
Thị giác máy tính
Ước lượng tư thế đầu
Tháng 9/2025 – Hiện tại
Thị giác máy tính

Ghép ảnh đa camera thời gian thực

Giới thiệu

Một bằng chứng khái niệm (proof-of-concept) thực hiện ghép ảnh đa camera thời gian thực, có thể áp dụng cho Hệ thống Hỗ trợ Lái xe Tiên tiến (Advanced Driving Assistance System). Tôi là nhà phát triển duy nhất, đảm nhiệm toàn bộ từ nghiên cứu, triển khai đến kiểm thử.


Tổng quan quy trình xử lý

Quy trình ghép ảnh gồm ba giai đoạn:

  • Nhận luồng đầu vào: thu khung hình từ camera/nguồn video và gộp thành lô (batch) làm đầu vào cho thuật toán ghép ảnh.
  • Ghép ảnh: đăng ký (register) các tham số cache cần thiết để mỗi camera đóng góp vào phép ước lượng, sau đó tổng hợp ảnh toàn cảnh (panorama) từ lô đầu vào và các tham số đã cache đó.
  • Hậu xử lý: ảnh toàn cảnh thu được sẽ được đưa vào các tác vụ phía sau — hiển thị, phát hiện đối tượng, ước lượng độ sâu, v.v.
Tổng quan quy trình ghép ảnh camera
💡 Quy tắc kinh nghiệm: tỷ lệ Intersection-over-Union (IoU) giữa trường nhìn (Field-of-View) của mỗi cặp camera nên đạt tối thiểu 30% để khắc phục méo ống kính và giữ đủ đặc trưng (feature) có thể phát hiện được cho việc ghép ảnh.

Thuật toán ghép ảnh

Tôi đã triển khai hai thuật toán ghép ảnh: một phiên bản đơn giản với quy trình xử lý nhẹ hơn, và một phiên bản nâng cao đánh đổi độ trễ xử lý cao hơn để lấy kết quả mượt mà, tinh chỉnh hơn.

So sánh quy trình thuật toán ghép ảnh đơn giản và nâng cao

Trích xuất đặc trưng

Dùng để trích xuất danh sách đặc trưng (feature) từ mỗi ảnh đầu vào:

Khớp đặc trưng

Dùng để tìm các đặc trưng khớp nhau giữa mỗi cặp ảnh đầu vào, từ đó ước lượng ma trận homography:

Ma trận homography $H$ xác định phép biến đổi giữa hai mặt phẳng, sai khác một hệ số tỷ lệ:

$$s \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \mathbf{H} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} = \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}$$

$H$ là ma trận $3 \times 3$ với 8 bậc tự do, vì nó chỉ được ước lượng sai khác một hệ số tỷ lệ — thường được chuẩn hóa với $h_{33} = 1$.

Ba trường hợp sau đều liên quan đến phép biến đổi giữa hai mặt phẳng:

Mặt phẳng vật thể và mặt phẳng ảnh Mặt phẳng vật thể quan sát từ hai vị trí camera Camera xoay quanh trục chiếu của nó

Trái → phải: mặt phẳng vật thể và mặt phẳng ảnh; mặt phẳng vật thể quan sát từ hai vị trí camera (trường hợp ghép ảnh); camera xoay quanh trục chiếu của nó — tương đương với các điểm nằm trên một mặt phẳng ở vô cực (chế độ chụp toàn cảnh trên điện thoại), trường hợp nền tảng cho việc ghép ảnh.


Demo

Đầu vào — 3 camera (gương trái, phía trước, gương phải)

Đầu vào camera gương trái Đầu vào camera phía trước Đầu vào camera gương phải

Kết quả thuật toán đơn giản

Ảnh ghép từ thuật toán đơn giản

Kết quả thuật toán nâng cao

Ảnh ghép từ thuật toán nâng cao
Ước lượng độ sâu

Định vị công nhân tại đường sắt

Giới thiệu

Một bằng chứng khái niệm nhằm phát hiện và ước lượng vị trí của công nhân tại đường sắt, sử dụng một camera nhiệt (thermal camera) duy nhất (Boson LWIR).


Quy trình

Quy trình xử lý kết hợp hai mô hình học sâu: phát hiện đối tượng (object detection) để tìm công nhân, và ước lượng độ sâu đơn mắt (monocular depth estimation) để ước lượng khoảng cách. Chúng tôi chọn hai mô hình SOTA (state-of-the-art) tốt nhất tại thời điểm đó — YOLOv5 cho phát hiện đối tượng và NeWCRFs cho ước lượng độ sâu — sau đó tinh chỉnh (fine-tune) cả hai trên dữ liệu của riêng chúng tôi, vì trọng số huấn luyện sẵn (pretrained weights) được huấn luyện trên ảnh RGB trong khi camera của chúng tôi là camera nhiệt.

Là nhà phát triển đầu tiên của dự án, nhiệm vụ chính của tôi là thu thập dữ liệu chuẩn (ground truth) về "độ sâu". Với một LIDAR hình ảnh độ phân giải cao góc rộng Ouster OS0 (Ouster OS0 Ultra-Wide High-Resolution Imaging LIDAR), nhiệm vụ này được chia thành ba nhiệm vụ con:

1. Hiệu chỉnh camera (Camera Calibration)

Ước lượng các tham số nội tại (intrinsic parameters) và hệ số méo (distortion coefficients) của camera nhiệt thông qua phương pháp phát hiện bàn cờ (checkerboard) tiêu chuẩn, dựa trên OpenCV và gói image_pipeline/camera_calibration của ROS, kết hợp thêm CLAHE (Contrast Limited Adaptive Histogram Equalization) để làm sắc nét độ tương phản cục bộ. Vì camera nhiệt không thể phân biệt trực quan các ô đen trắng trên bàn cờ, tôi đã đặt bàn cờ trong môi trường nhiệt độ cao (ánh nắng trực tiếp, đèn halogen) — bề mặt màu đen hấp thụ nhiệt nhiều hơn bề mặt màu trắng, khiến hoa văn trở nên rõ ràng đối với cảm biến.

2. Thu thập dữ liệu

Sử dụng ROS để ghi dữ liệu đồng bộ từ nhiều cảm biến: ouster_ros cho LIDAR, flir_boson_usb cho camera nhiệt, và rosbag record để ghi lại cả hai luồng dữ liệu. Việc đồng bộ dựa trên dấu thời gian (timestamp) mà ROS gắn vào lúc ghi.

3. Hiệu chỉnh Camera-LIDAR

Ước lượng ma trận xoay (rotation matrix) và vector tịnh tiến (translation vector) giữa hệ tọa độ của LIDAR và camera:

Sơ đồ quy trình hiệu chỉnh Camera-LIDAR 1 Sơ đồ quy trình hiệu chỉnh Camera-LIDAR 2

Với ma trận xoay $R$ và vector tịnh tiến $t$, đám mây điểm (point cloud) từ LIDAR được chuyển đổi sang hệ tọa độ camera, sau đó chiếu lên mặt phẳng ảnh để tạo thành bản đồ độ sâu (depth map) ở tỷ lệ chuẩn (ground-truth), khớp với ảnh camera:

$$s \begin{bmatrix} u\\ v \end{bmatrix} = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_c\\ Y_c \\ Z_c \end{bmatrix}$$
Bản đồ độ sâu chuẩn (ground-truth) thu được, khớp với ảnh camera nhiệt

Bài học rút ra

Bộ dữ liệu và quy trình hiệu chỉnh này đã giúp nhóm trở thành 1 trong 8 giải pháp trên thế giới vượt qua được baseline SOTA được cung cấp, trên bất kỳ chỉ số nào dựa trên point cloud hoặc ảnh, tại cuộc thi ước lượng độ sâu đơn mắt CVPRW 2023. Chúng tôi đã tùy biến PixelFormer (mô hình ước lượng độ sâu SOTA tại thời điểm đó) với các kỹ thuật tăng cường dữ liệu (data augmentation) trong lúc huấn luyện (cắt/xoay ngẫu nhiên, lật trái-phải, CutDepth) và kỹ thuật đệm không (zero-padding) khi suy luận (inference) để giữ nguyên độ phân giải huấn luyện.

Ước lượng độ sâu

PseudoLiDAR thời gian thực

Giới thiệu

Một dự án R&D nhằm thay thế LIDAR bằng camera: một mô hình ước lượng độ sâu tuyệt đối (absolute depth estimation) kết hợp với các tham số hiệu chỉnh camera (camera calibration) tạo ra một đám mây điểm giả (pseudo point cloud) trực tiếp từ các pixel ảnh, được kết xuất (render) theo thời gian thực bằng OpenGL và Open3D.

Phần lý thuyết nền tảng — các tín hiệu cảm nhận độ sâu của con người, ước lượng độ sâu tuyệt đối so với tương đối, phần toán học chuyển đổi từ độ sâu sang tọa độ 3D, và quy trình đề xuất để thay thế LIDAR bằng nhiều camera — được trình bày riêng trong bài viết sau:


Mô hình ước lượng độ sâu nhẹ

Để phục vụ demo thời gian thực, chúng tôi đã xây dựng một mô hình ước lượng độ sâu được tối ưu hóa, hướng tới độ trễ thấp mà không đánh đổi quá nhiều độ chính xác. Lấy cảm hứng từ hiệu suất của họ mô hình YOLO, mô hình sử dụng backbone + neck YOLOv8 được tùy biến làm bộ mã hóa (encoder) đặc trưng 4 tỷ lệ (4-scale), kết nối qua các skip connection tới một bộ giải mã (decoder) kiểu U-Net để tái tạo bản đồ độ sâu.

Kiến trúc mô hình độ sâu encoder-decoder nhẹ dựa trên YOLOv8

Sau khi tinh chỉnh (fine-tune) trên NYUv2 (trong nhà) và KITTI (ngoài trời), mô hình đạt hiệu năng cạnh tranh trên các chỉ số đánh giá độ sâu đã được thiết lập, trong khi kích thước nhỏ hơn nhiều so với các phương pháp SOTA:

Bộ dữ liệu NYUv2

Mô hìnhTham sốFPS (480×640)Abs.Rel↓RMSE↓Sqr.Rel↓δ1↑δ2↑δ3↑
Của chúng tôi (encoder YOLOv8s)10,810,4651050.10330.37170.05780.89650.98140.9958
NeWCRFs270,444,877140.09580.33310.04510.92150.99150.9980
PixelFormer270,895,920160.09050.32420.04350.92890.99060.9977

Bộ dữ liệu KITTI

Mô hìnhTham sốFPS (480×640)Abs.Rel↓RMSE↓Sqr.Rel↓δ1↑δ2↑δ3↑
Của chúng tôi (encoder YOLOv8s)10,810,4651050.04792.38790.17980.97210.99520.9982
NeWCRFs270,444,877140.05092.18710.16080.97620.99630.9987
PixelFormer270,895,920160.05422.37480.18170.97240.99550.9984

Với tốc độ khung hình (FPS) gấp khoảng 7 lần so với NeWCRFs/PixelFormer và chỉ khoảng 4% số lượng tham số của chúng, mô hình đánh đổi một phần nhỏ độ chính xác để đạt được thông lượng (throughput) mà một quy trình PseudoLiDAR thời gian thực cần.

Thị giác máy tính

Ước lượng tư thế đầu

Demo ước lượng tư thế đầu 1 Demo ước lượng tư thế đầu 2

Định nghĩa tư thế đầu

Một tư thế đầu được xác định bởi một điểm xuất phát $p = (u_0, v_0)$ — gốc của hệ tọa độ tư thế đầu — và một ma trận xoay (theo quy ước ZYX) được xây dựng từ góc chúc ngóc (Pitch) $Pi$, góc lệch hướng (Yaw) $Ya$, và góc nghiêng (Roll) $Ro$:

$$R_z(Ro) = \begin{bmatrix} \cos{Ro} & -\sin{Ro} & 0 \\ \sin{Ro} & \cos{Ro} & 0 \\ 0 & 0 & 1 \end{bmatrix}$$
$$R_y(Ya) = \begin{bmatrix} \cos{Ya} & 0 & \sin{Ya} \\ 0 & 1 & 0 \\ -\sin{Ya} & 0 & \cos{Ya} \end{bmatrix}$$
$$R_x(Pi) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos{Pi} & -\sin{Pi} \\ 0 & \sin{Pi} & \cos{Pi} \end{bmatrix}$$

Ma trận xoay tổng hợp của tư thế đầu so với camera là:

$$R = \begin{bmatrix} \cos{Ro}\cos{Ya} & \cos{Ro}\sin{Ya}\sin{Pi} - \sin{Ro}\cos{Pi} & \cos{Ro}\sin{Ya}\cos{Pi} + \sin{Ro}\sin{Pi} \\ \sin{Ro}\cos{Ya} & \sin{Ro}\sin{Ya}\sin{Pi} + \cos{Ro}\cos{Pi} & \sin{Ro}\sin{Ya}\cos{Pi} - \cos{Ro}\sin{Pi} \\ -\sin{Ya} & \cos{Ya}\sin{Pi} & \cos{Ya}\cos{Pi} \end{bmatrix}$$

Mọi điểm $(x, y, z)$ trên tia tư thế đầu (head-pose ray) đều thỏa mãn:

$$\begin{cases} t \geq 0 \\ x = x_0 + t\cos(Ro)\cos(Ya) \\ y = y_0 + t\sin(Ro)\cos(Ya) \\ z = z_0 - t\sin(Ya) \end{cases}$$

Ngược lại, có thể khôi phục Pitch, Yaw, và Roll từ $R$:

$$\tan(Pi) = \frac{R_{2,1}}{R_{2,2}} \qquad \tan(Ya) = -\frac{R_{2,0}}{\sqrt{R_{2,1}^2 + R_{2,2}^2}} \qquad \tan(Ro) = \frac{R_{1,0}}{R_{0,0}}$$

Ý tưởng

Để ước lượng tư thế đầu của con người (ma trận xoay + vector tịnh tiến so với camera) theo thời gian thực, quy trình xử lý áp dụng một phương pháp thị giác máy tính cổ điển:

Sơ đồ quy trình ước lượng tư thế đầu

Bộ lọc Kalman mở rộng (Extended Kalman Filter) "làm mượt" tư thế dự đoán và giảm thiểu các trường hợp lỗi khi mô hình không thể nhìn thấy khuôn mặt — bị che khuất, góc nhìn quá lớn, v.v.


Ước lượng điểm mốc khuôn mặt (Facial Landmark)

Tôi đã xây dựng một mô hình điểm mốc khuôn mặt (facial landmark) 2D với backbone kiểu phân loại (classification), kết thúc bằng một lớp tuyến tính (linear/classifier head) với $(num\_keypoints \times 3)$ đầu ra cho phiên bản có cờ khả kiến (visibility flag), hoặc $(num\_keypoints \times 2)$ cho phiên bản không có cờ khả kiến:

Kiến trúc mô hình điểm mốc khuôn mặt

Ước lượng tư thế đầu qua SolvePnPRansac

Các điểm tĩnh (static points) từ các điểm mốc 2D dự đoán được khớp với các điểm 3D tương ứng từ mẫu khuôn mặt 3D Mediapipe (Mediapipe 3D facemark template), sau đó solvePnPRansac khôi phục ma trận xoay và vector tịnh tiến. "Tĩnh" ở đây nghĩa là các điểm giữ vị trí tương đối cố định so với khuôn mặt ngay cả khi có các biểu cảm — nháy mắt, ngáp, cười, v.v.

Khớp điểm mốc 2D với mẫu khuôn mặt 3D

Bộ ổn định bằng bộ lọc Kalman

Bộ lọc Kalman mở rộng làm mượt chuyển động của tư thế đầu qua các khung hình và lấp đầy khoảng trống khi mô hình điểm mốc khuôn mặt 2D không dự đoán được điểm mốc — phổ biến nhất là do bị che khuất.


Tài liệu tham khảo