English
Mới nhấtAI & Dữ liệuIn 3D & CNCNhúng & IoTPhần mềmVề VHITEK MakerLiên hệQuy tắc bình luận

Đo khoảng cách bàn tay ↔ vật và hướng dẫn lấy vật bằng camera chiều sâu Orbbec Astra Pro

Bởi Ngụy Minh Đức|
Đo khoảng cách bàn tay ↔ vật và hướng dẫn lấy vật bằng camera chiều sâu Orbbec Astra Pro

Trước khi một cánh tay robot gắp được đồ vật, máy cần trả lời được hai câu hỏi: bàn tay đang ở đâu so với vật, và phải di chuyển thế nào để tới được vật. Dự án này làm đúng hai việc đó với một camera chiều sâu Orbbec Astra Pro: phát hiện bàn tay, tìm vật trên bàn, đo khoảng cách giữa hai bên theo thời gian thực, rồi hướng dẫn người dùng đưa tay tới vật theo từng bước. Toàn bộ chạy trên laptop, không cần GPU.

Bài này tổng hợp những phần đã làm xong và đã chạy thật với camera.

Dashboard Astra Studio lúc bàn tay chạm vật: khe hở tay và vật 1,9 cm, bên trái ảnh màu, bên phải ảnh độ sâu
Dashboard lúc bàn tay chạm vật: khe hở 1,9 cm. Trái: ảnh màu có vẽ tay, vật và trục X/Y/Z. Phải: ảnh độ sâu.

1. Phần cứng và hướng tiếp cận

Astra Pro thực chất là hai thiết bị USB trong một vỏ: một webcam màu (UVC) và một cảm biến độ sâu hồng ngoại (đọc qua OpenNI2). Cảm biến độ sâu chạy ổn định 30 FPS, tầm đo khoảng 0,6 m đến 4,7 m. Hệ thống chạy được cả trên Windows và Linux.

Vì cả hai API đều chặn (blocking), chương trình đọc mỗi luồng ở một thread riêng. Pipeline xử lý mỗi khung hình như sau:

  1. Phát hiện 2D: tìm bàn tay trên ảnh màu, tìm vật trên ảnh màu hoặc ảnh độ sâu.

  2. Tra độ sâu: lấy giá trị độ sâu tương ứng, có bù lệch giữa camera màu và camera hồng ngoại.

  3. Dựng 3D: chiếu ngược pixel + độ sâu thành toạ độ 3D (mm).

  4. Đo và hướng dẫn: tính khe hở tay ↔ vật, đổi sang hệ trục gắn với mặt sàn, rồi sinh câu hướng dẫn.

2. Phát hiện bàn tay

Bàn tay được nhận diện bằng MediaPipe Hand Landmarker, cho ra 21 khớp tay. Mỗi khớp được lấy độ sâu riêng, chỉ dùng các pixel thuộc vùng tay, nên điểm đo không bị "rơi" ra nền phía sau.S

Độ sâu của Astra hay bị "thủng" (trả về 0) ở mép vật, trên bề mặt mỏng hoặc bóng, và ở bóng hồng ngoại mà bàn tay hắt xuống sàn. Vì vậy hệ thống không lấy một pixel đơn lẻ mà lấy trung vị của cả một vùng nhỏ, bỏ các pixel 0. Khi chính giữa lòng bàn tay bị thủng, độ sâu được lấy từ các khớp quanh lòng bàn tay thay vì bỏ qua cả bàn tay.

3. Tìm vật: ba chế độ, đổi được ngay lúc đang chạy

Ban đầu dự án chỉ nhận xe đồ chơi (YOLO, lớp car của COCO, không cần train thêm). Sau đó mục tiêu được mở rộng thành vật bất kỳ với ba chế độ:

Chế độ

Cách tìm

FPS thực tế

Biết tên vật?

Plane (mặc định)

Tìm mặt bàn bằng RANSAC trên ảnh độ sâu; thứ gì nhô lên 12–300 mm là vật

20 FPS

Không

YOLOE

Nhận diện mở, khoảng 4.585 loại vật, không cần nhập tên trước

16 FPS

Có ("mouse", "cup"…)

COCO

YOLO26-seg, 80 lớp chuẩn

~13 FPS

Có, 80 lớp

Chế độ Plane nghe đơn giản ("mặt bàn phẳng, cái gì nhô lên là vật") nhưng phải xử lý ba cái bẫy: RANSAC bám nhầm vào tường, chân tường cũng "cao hơn mặt bàn", và cẳng tay cũng nhô lên khỏi bàn. Mỗi bẫy có một ràng buộc hình học riêng và có test riêng.

YOLOE tốn gần 1 giây mỗi lần chạy trên CPU. Để hình không bị giật, detector nặng được đưa ra thread nền: vòng xử lý chính luôn dùng kết quả gần nhất và chạy đều theo tốc độ nhận diện tay. Tên vật do YOLOE trả về hay nhảy giữa nhiều nhãn ("frisbee", "bedpan", "sign"…) cho cùng một vật, nên tên hiển thị được bầu chọn qua nhiều khung hình theo độ tin cậy.

4. Đo khe hở tay ↔ vật: từ mặt da tới bề mặt vật

Phiên bản đầu đo từ tâm lòng bàn tay tới tâm vật. Khi tay đã chạm vật, con số vẫn còn khoảng 86 mm (nửa bề ngang vật cộng độ dày bàn tay). Phiên bản hiện tại đo cặp điểm gần nhau nhất giữa hai bề mặt: 21 khớp tay (dời ra mặt da) và đám mây điểm 3D của vật.

Khe hở thật

Cách cũ (tâm – tâm)

Cách mới (bề mặt – bề mặt)

150 mm

không đo

153 mm

50 mm

không đo

53 mm

0 mm (chạm)

86 mm

8 mm

Với camera thật, các lần đưa tay chạm vật cho ra 0,8–1,9 cm. Khi tay và vật chạm nhau ở cùng độ sâu, ảnh độ sâu không tách được ranh giới, nên khe nhỏ nhất đo được vào khoảng 1 cm chứ không phải 0 tuyệt đối.

Một lỗi đáng nhớ: tay chưa chạm mà báo 0 cm

Khi camera chiếu từ trên xuống, có lúc tay còn lơ lửng cách vật vài cm mà hệ thống đã báo 0,0 cm. Nguyên nhân: ngón tay mảnh nên bị lỗ độ sâu, và vài pixel còn lại trong vùng quanh khớp tay chính là mặt vật nhìn qua khe ngón tay, nên khớp tay bị "đặt" lên mặt vật. Cách sửa dựa trên một nhận xét hình học: bàn tay có độ dày, nên mặt tay mà camera thấy luôn nằm trước mặt vật phía sau nó. Khớp nào đọc ra độ sâu trùng mặt vật thì chắc chắn đang nhìn xuyên qua, không phải tay. Lỗi này được tái hiện bằng dữ liệu tổng hợp và giữ lại thành test để không tái phát.

Khi tay che mất vật

Lúc cần đo nhất (tay sắp chạm vật) cũng là lúc tay hay che khuất vật. Hệ thống giữ lại hình dạng vật lần cuối nhìn thấy, nhưng chỉ khi kiểm chứng được tay đang ở phía trước đúng chỗ vật vừa ở, và chỉ giữ tối đa 5 giây. Nếu bạn cầm vật nhấc đi thì hệ thống không giữ lại một "bóng ma".

5. Khoá mục tiêu: không nhảy loạn giữa các vật

Khi trên bàn có nhiều vật, đã chọn vật nào thì các khung hình sau ưu tiên vật khớp vị trí cũ nhất. Kết quả đo thật: 22 vật trong khung hình, bám đúng một vật suốt 15 giây, không nhảy lần nào.

  • Click để ghim: bấm thẳng vào vật trên ảnh để chọn, vật đã ghim thì không tự đổi.

  • Khoá vùng: ghi nhớ một chỗ cố định trong không gian 3D. Khi đang khoá, detector ngừng chạy nên hết lag hoàn toàn.

  • Đổi mục tiêu: bỏ khoá, hệ thống tự chọn vật gần bàn tay nhất.

6. Hệ trục XYZ gắn với mặt sàn và hướng dẫn lấy vật

Toạ độ của camera không có ý nghĩa với người dùng: camera treo nghiêng thì "Z" không còn là độ cao. Vì vậy hệ thống tự dựng một hệ trục gắn với mặt sàn (tìm mặt sàn bằng RANSAC trên ảnh độ sâu):

  • Gốc (0,0,0): điểm trên sàn nằm thẳng dưới camera.

  • X: về phía trước. Y: sang phải. Z: độ cao so với sàn.

Từ đó có XYZ của bàn tay, XYZ của vật và Delta XYZ = Vật − Tay. Hệ trục cũng tự xử lý trường hợp camera nghiêng: một bức tường không bao giờ bị nhận nhầm là mặt sàn.

Bản đầu đọc cả ba trục thành một câu, kiểu "Đưa tay về phía trước 20 mm, sang trái 110 mm và hạ xuống 210 mm". Thử thực tế thì không ai làm theo được ba con số cùng lúc. Phiên bản hiện tại hướng dẫn từng bước, giống cách người ta với tay lấy đồ:

  1. Đưa tay tới ngay trên vật: chỉ nói hướng lệch nhiều nhất, ví dụ "Sang trái khoảng 13 cm."

  2. Hạ tay xuống: "Hạ tay xuống khoảng 18 cm." Đích là mặt trên của vật, không phải tâm vật.

  3. Chạm vật: khi khe hở còn dưới 3 cm, hệ thống báo "Đã đến vị trí vật."

Khung hướng dẫn lấy vật ở bước 1: câu Sang trái khoảng 13 cm, bản đồ nhìn từ trên với chấm vàng là bàn tay và bảng toạ độ XYZ
Bước 1 — đưa tay tới ngay trên vật. Chấm vàng là bàn tay, hồng tâm là vật.
Khung hướng dẫn lấy vật ở bước 2: chấm vàng đã nằm trong hồng tâm, thanh độ cao cho thấy cần hạ tay xuống khoảng 18 cm
Bước 2 — đã ở trên vật, hạ tay xuống tới nét đứt (mặt trên vật).

Quan trọng hơn câu chữ là phản hồi bằng mắt: một bản đồ nhìn từ trên xuống với vật là hồng tâm và bàn tay là chấm vàng, cộng một thanh độ cao có nét đứt đánh dấu độ cao cần hạ tới. Người dùng chỉ cần kéo chấm vàng vào hồng tâm rồi hạ xuống nét đứt. Hướng dẫn có thể đọc bằng giọng tiếng Việt ngay trên trình duyệt, và chỉ đọc khi hướng cần đi thay đổi.

Khung hướng dẫn lấy vật báo Đã đến vị trí vật khi bàn tay chạm vật, cả ba bước đều hoàn thành
Đã đến vị trí vật: khe hở dưới 3 cm, cả ba bước hoàn thành.

7. Dashboard web "Astra Studio"

Dashboard chạy ngay trên máy (Flask, chỉ lắng nghe 127.0.0.1, hình ảnh camera không ghi xuống đĩa).

  • Hai khung camera: ảnh màu có vẽ tay, vật và ba trục X/Y/Z; ảnh độ sâu có dấu cộng đánh dấu điểm đang lấy khoảng cách.

  • Kết quả đo: khe hở tay ↔ vật, tay cao hơn vật, khoảng cách ngang, khoảng cách tới camera.

  • Hướng dẫn lấy vật: 3 bước, bản đồ nhìn từ trên, thanh độ cao, bảng XYZ Tay / Vật / Delta, giọng nói.

  • Điều khiển: chọn kiểu đặt camera (treo trên / đặt ngang), YOLOE, Khoá vùng, Đổi mục tiêu, click trên ảnh để ghim.

  • Biểu đồ khoảng cách trong 30 giây gần nhất.

  • Công cụ căn chỉnh: chỉnh lệch giữa ảnh màu và ảnh độ sâu bằng thanh trượt ngay khi đang chạy; kiểm chứng số đo bằng thước.

Một worker nền giữ camera và pipeline, web server chỉ đọc kết quả mới nhất. Mở bao nhiêu tab cũng được, camera vẫn chỉ mở một lần. Giao diện tự chuyển sang một cột trên điện thoại.

8. Hiệu năng trên CPU laptop

Khâu

Thời gian / tốc độ

Nhận diện tay (MediaPipe)

~51 ms / khung

Tìm vật — Plane

~10 ms

Tìm mặt sàn cho hệ trục

~16 ms, khoảng 1,5 giây một lần

Toàn hệ thống, chế độ Plane

20 FPS

Toàn hệ thống, chế độ YOLOE

16 FPS

Một bài học rút ra: đừng giảm kích thước ảnh đầu vào để tăng tốc khi vật nhỏ. Xe đồ chơi chỉ rộng khoảng 70 px trong khung 640×480; hạ imgsz xuống 320 thì YOLO không bắt được xe lần nào. Cách hiệu quả hơn là chạy detector vật thưa hơn (vật đứng yên) trong khi tay vẫn được nhận diện ở mọi khung.

9. Kiểm thử

Phần lớn logic được kiểm thử không cần camera, bằng cảnh độ sâu tổng hợp: toán học 3D, bộ lọc nhiễu, tìm vật, khoá mục tiêu, khe hở tay ↔ vật, hệ trục mặt sàn, hướng dẫn từng bước và tầng web của dashboard. Tổng cộng hơn 300 test. Mỗi lỗi tìm ra khi xem video chạy thật đều được tái hiện thành test trước khi sửa.

Tổng kết

Với một camera chiều sâu giá phải chăng và một laptop không GPU, hệ thống đã:

  • phát hiện bàn tay và tìm được vật bất kỳ trên bàn;

  • đo khe hở từ mặt da tới bề mặt vật, về khoảng 1–2 cm khi chạm;

  • dựng hệ trục XYZ gắn với mặt sàn, cho biết toạ độ tay, vật và Delta;

  • hướng dẫn người dùng đưa tay tới vật từng bước, có hình và giọng nói;

  • có dashboard web để theo dõi, ghim mục tiêu và căn chỉnh ngay khi đang chạy.

Đây là nền móng để một cánh tay robot có thể "thấy" bàn tay người và đồ vật trong không gian 3D, rồi tự tính đường đi tới vật.

Bình luận

Chưa có bình luận nào. Nếu bài này sai ở đâu, nói giúp.

Bình luận được duyệt trước khi hiện. Chúng tôi lưu địa chỉ IP và trình duyệt của bạn trong 90 ngày để chống spam, và không lưu email ở dạng đọc được. Chi tiết ở quy tắc bình luận.