9. Nhận Diện Cử Chỉ Tay trong ROS

9. Nhận Diện Cử Chỉ Tay trong ROS

Hy vọng bạn vẫn nhớ một trong những lý do rất quan trọng mà chúng ta tìm hiểu ROS: "Don't reinvent the wheel", nghĩa là có rất nhiều package (hoặc project) thú vị có sẵn mà bạn có thể ứng dụng ngay hoặc không tốn nhiều công sức để triển khai trong ROS. Trong chương này, bạn sẽ học cách clone (tải) và chạy một package giúp nhận dạng (recognize) các kí hiệu/cử chỉ tay trên các ảnh được publish từ webcam của bạn. Nghĩa là thay vì chỉ hiển thị hình ảnh như trong chương 8, giờ bạn có thể dùng chúng để có những thông tin hữu ích hơn. Lưu ý: Bản Tiếng Anh của bài viết ở đây.

Công nghệ nhận diện cử chỉ tay (Hand Gesture Recognition)

Một hệ thống có thể hiểu cử chỉ tay của con người có vô vàn ứng dụng thực tế. Ví dụ như trong chế tạo rô-bốt, nó có thể giúp chuyển đổi nhận dạng cử chỉ thành tín hiệu điều khiển khiến rô-bốt.

Với sự phát triển gần đây của trí tuệ nhân tạo (AI), việc triển khai hệ thống đó dễ dàng hơn bao giờ hết. Trong chương này, mình muốn giới thiệu với bạn Mediapipe Hands là gói máy học (ML) mã nguồn mở của Google có thể giúp nhận dạng và theo dõi (track) bàn tay người bằng hình ảnh. Về cơ bản, Mediapipe kết hợp hai mô hình (model) học máy: một mô hình palm detection (nhận diện bàn tay) để tìm vị trí của bàn tay và một mô hình mốc (landmark) bàn tay để định vị chính xác 21 tọa độ khớp ngón tay từ vị trí tìm được ở palm detection (xem hình ảnh bên dưới). Nó được train (huấn luyện, đào tạo) với khoảng 30 nghìn dữ liệu thực có gắn nhãn (label) và chạy rất nhanh theo cách thức single-shot. Bạn có thể tìm hiểu thêm thông tin chi tiết về package này tại đây.

hand_landmarks.png

Các keypoint (điểm màu đỏ ở trong hình landmark bên trên) được nhận diện từ Mediapipe cần được chuyển đổi thành những hành động có ý nghĩa. Chẳng hạn như từ hình landmark bàn tay ở trên, hệ thống của chúng ta sẽ cho chúng ta biết trạng thái là "Open" vì tất cả các ngón tay đều đang được duỗi thẳng. Để làm được điều đó, cần phải có một model khác để phân loại (classify) các hành động. May mắn là đã có một chương trình có sẵn trên GitHub. Repository (kho lưu trữ) hand-gesture-recognition-mediapipe này chứa các tập lệnh Python giúp người dùng train và triển khai các model để nhận dạng dấu hiệu bàn tay và cử chỉ ngón tay. Mình đã dùng và biến nó thành một ROS package để bạn có thể sao chép (clone) và chạy ngay.

Cài đặt

Đầu tiên, cài đặt các phần phụ thuộc (dependencies) sau bằng cách sử dụng pip3 (hoặc conda nếu bạn dùng Anaconda):

  • Mediapipe 0.8.1

  • OpenCV 3.4.2 trở lên

  • Tensorflow 2.3.0 trở lên

Dưới đây là ba câu lệnh dùng pip3 (bạn phải chạy riêng từng cái một):

pip3 install mediapipe
pip3 install opencv-python
pip3 install tensorflow

Sau đó, sao chép kho lưu trữ này vào thư mục catkin_ws/src:

cd ~/catkin_ws/src
git clone https://github.com/TrinhNC/ros_hand_gesture_recognition.git

Build package:

cd ~/catkin_ws
catkin build

Chạy Package

Sau khi build thành công, bạn có thể chạy demo. Nhớ source không gian làm việc (catkin workspace) bằng command source ~/catkin_ws/devel/setup.bash. Mở 2 terminal. Trong terminal thứ nhất, chạy image publisher (từ chương 7 và nhớ kết nối webcam với máy ảo nếu bạn đang sử dụng máy ảo):

roslaunch my_cam my_cam.launch

Nếu bạn thắc mắc về roslaunch có thể xem lại ở đây. Trong terminal thứ hai, chạy hand gesture recognition:

roslaunch ros_hand_gesture_recognition hand_sign.launch

Kết quả sẽ như thế này:

ros-mediapipe

Trong GIF ở trên, FPS là viết tắt của Frame Per Second, là số lượng hình ảnh được xử lý mỗi giây, Right là tay phải và các từ sau đó (Turn Right, Forward, v.v.) là các nhãn (label) mà mình đã gán cho các dấu tay. Bạn có thể thay đổi các nhãn này bằng cách làm theo phần bên dưới.

Train mô hình nhận dạng dấu tay

Package hiện tại chỉ có thể phân loại được 6 dấu tay (6 lớp/classes) và mình đã gắn nhãn: Stop (Dừng), Go (Đi), Forward (Tiến), Backward (Lùi), Turn Right (Rẽ phải) and Turn Left (Rẽ trái) (xem hình ảnh bên dưới). Chúng sẽ được chuyển đổi thành tín hiệu điều khiển để di chuyển rô-bốt trong các chương sau. Nếu bạn muốn thay đổi hoặc thêm cử chỉ hoặc bạn phát hiện ra rằng trained model của mình chạy chưa tốt lắm thì bạn hoàn toàn có thể tự thu thập dữ liệu (collect data) và train lại.

ros-hand-gesture-recognition

Có hai jupyter notebook trong thư mục src/notebooks:

  • keypoint_classification_EN.ipynb: tập lệnh đào tạo mô hình để nhận dạng ký hiệu tay.

  • point_history_classification.ipynb: tập lệnh đào tạo mô hình để nhận dạng cử chỉ ngón tay (có nghĩa là mô hình sau khi đào tạo có thể phát hiện chuyển động của ngón tay của bạn chứ không chỉ là một dấu hiệu tĩnh như trong mô hình bên trên).

Ở trong ROS package hiện tại mình chỉ sử dụng mô hình keypoint classification vì ứng dụng của mình chỉ cần đến thế nhưng bạn có thể dễ dàng thay đổi nó để phù hợp với ứng dụng của bạn.

Trong ví dụ dưới đây, mình sẽ chỉ cho bạn cách thêm một dấu tay nữa. Giả sử chúng ta muốn thêm ký hiệu này✌️và đặt tên là "Hi". Lưu ý: Phần này không liên quan gì tới ROS package tạo ở phần trước nên bạn nhớ tắt chúng đi.

Trước hết, cài những thư viện dưới đây nếu bạn chưa có:

pip3 install -U tf-nightly
pip3 install -U scikit-learn
pip3 install -U matplotlib

hi_mediapipe

Mở keypoint_classifier_label.csv trong thư mục src/model/keypoint_classifier. Ở đây có tất cả các nhãn (hiện có 6 lớp) và bạn cần thêm 'Hi' vào dòng cuối cùng như sau:

Stop
Go
Forward
Backward
Turn Right
Turn Left
Hi

Tiếp theo, bạn cần ghi (record) dữ liệu và thêm (append) vào tệp keypoint.csv trong thư mục src/model/keypoint_classifier. Nếu bạn mở tệp này, bạn sẽ thấy nó chứa 6410 dòng. Số đầu tiên trong mỗi dòng là class ID (số hiệu của lớp) tương ứng với danh sách trên, ví dụ: "Go" có ID 0, "Stop" có ID 1, "Forward" có ID 2, v.v. Sau đó là 42 số hoặc 21 cặp số biểu thị tọa độ của từng keypoint (tức các đốt ngón tay) đối với điểm gốc là cổ tay. Một điều cần lưu ý là ID trong hình bên dưới là ID của keypoint (từ 0 tới 20) khác với class ID (từ 0 tới 6).

keypoint_mediapipe

Để ghi lại dữ liệu, hãy chạy tập lệnh app.py:

python3 app.py

Nhấn k trên bàn phím và bạn sẽ thấy dòng MODE: Logging Key Point xuất hiện. Sau đó, sử dụng tay phải của bạn để hiển thị dấu✌️. Nhấn và giữ số 6 (class ID của "Hi") bằng tay trái của bạn. Thao tác này sẽ liên tục thêm dữ liệu mới vào tệp keypoint.csv cho đến khi bạn nhả khóa. Bạn cũng có thể thử nhấn và nhả số 6 ngay lập tức và sẽ thấy trong file keypoint.csv có thêm một dòng mới ở cuối bắt đầu bằng số 6 và một danh sách các số tọa tiếp theo sau. Ngoài ra, trong quá trình ghi, nhớ di chuyển tay phải của bạn đến các vị trí khác nhau để làm cho dữ liệu đa dạng hơn.

ros-mediapipe-record-dataset

Sau khi ghi khoảng 10-15 giây, dữ liệu sẽ sẵn sàng và bạn có thể dừng chương trình (bằng phím tắt Ctrl + C trong terminal). Mở notebook keypoint_classification_EN.ipynb. Chỉnh sửa dataset, model_save_pathtflite_save_path để khớp với đường dẫn của bạn. Thay đổi NUM_OF_CLASSES thành 7 thay vì 6: NUM_CLASSES = 7. Sau đó chạy notebook từ đầu đến cuối bằng cách ấn nút Run hoặc chạy từng dòng bằng phím tắt Shift + Enter. Quá trình training được thực hiện trong ô [13] và mất khoảng 2-3 phút. Sau đó, bạn có thể khởi chạy my_cam.launchhand_sign.launch lại như trong Demo bên trên để xem kết quả.

Did you find this article valuable?

Support Trinh Nguyen by becoming a sponsor. Any amount is appreciated!