Touchless HMI using MediaPipe Hands
Gesture Recognition · Virtual Mouse · Air Keyboard
Built with VS Code + Flask + OpenCV on Windows 11
Hệ thống nhận diện cử chỉ tay qua webcam, điều khiển giao diện ảo không cần chạm. MediaPipe Hands phát hiện 21 điểm mốc trên bàn tay theo thời gian thực.
Phát hiện bàn tay mở (開掌控制), hiển thị 21 điểm mốc. Bàn phím ảo bên phải cho phép nhập liệu không tiếp xúc. Góc giám sát: 16°.
Cấu trúc project: app.py, face_detect.py, index.html, style.css, app.js. Terminal hiển thị Flask server đang chạy tại 127.0.0.1:5500.
Tích hợp các công nghệ hiện đại xây dựng giao diện điều khiển không tiếp xúc hoàn chỉnh.
Ngôn ngữ lõi xử lý backend, tích hợp OpenCV capture webcam frame và truyền sang MediaPipe phân tích thời gian thực.
Server web nhẹ, streaming video qua /video_feed endpoint. Xử lý routing và API giao tiếp giữa frontend và backend Python.
Google MediaPipe Tasks API (2026). Phát hiện 21 landmarks bàn tay với độ chính xác cao, hỗ trợ nhiều bàn tay đồng thời.
Xử lý video stream từ webcam, vẽ landmarks lên frame, xử lý hình ảnh real-time và stream MJPEG qua Flask server.
Frontend responsive: index.html cấu trúc, style.css giao diện tối, app.js nhận gesture data cập nhật bàn phím ảo và con trỏ ảo.
IDE trên Windows 11 với extension Python, Flask debug, live reload. Terminal tích hợp chạy Flask và debug traceback.
Touchless HMI cung cấp 6 chế độ điều khiển cử chỉ chính, tất cả chạy real-time qua webcam.
Ngón trỏ di chuyển điều khiển con trỏ toàn màn hình. Pinch (ngón cái + ngón trỏ chụm) = click. Smooth tracking với EMA filter.
Bàn phím ảo điều khiển bằng ngón trỏ. Nhập liệu hoàn toàn không tiếp xúc, hỗ trợ số, chữ cái, Space và Enter.
Chế độ "開掌控制" khi phát hiện 5 ngón tay mở. Chuyển trạng thái điều khiển và hiển thị angle monitoring 16°.
Vẫy tay trái/phải để chuyển slide trình chiếu. Nhận diện vận tốc và hướng chuyển động theo trục X.
Vẽ chữ ký trong không trung, hệ thống lưu trajectory và đối chiếu xác thực danh tính (biometric authentication).
Xoay lòng bàn tay điều chỉnh tham số hệ thống (âm lượng, độ sáng). Nhận diện góc xoay realtime qua wrist landmark.
3 layer: Hardware (webcam) → Backend (Python/Flask/MediaPipe) → Frontend (HTML/CSS/JS). Data flow theo mô hình MJPEG streaming.
📁 PROJECT STRUCTURE — TOUCHLESS_HMI/
Các vấn đề gặp phải trong quá trình phát triển và cách giải quyết từng bước.
Lỗi "response headers were already sent" khi streaming video frame từ Flask. Generator bị interrupt khi frame trống. → Fix: thêm try/except trong gen_frames(), kiểm tra frame is not None trước khi yield.
Landmark bị lag khi ánh sáng yếu hoặc tay di chuyển nhanh. → Fix: điều chỉnh min_detection_confidence=0.7, min_tracking_confidence=0.5. Resize frame về 640x480 trước khi xử lý.
Con trỏ ảo rung khi giữ ngón tay im. Nguyên nhân: MediaPipe landmark có noise nhỏ. → Fix: áp dụng Exponential Moving Average (EMA) smoothing alpha=0.3 trên tọa độ XY.
Ngưỡng phát hiện pinch còn nhạy, dễ trigger nhầm. Đang nghiên cứu thuật toán tính khoảng cách Euclidean giữa tip-4 và tip-8 với ngưỡng động theo kích thước bàn tay.
Port 5500 bị conflict với VS Code Live Server extension. → Fix: đổi Flask app.run(port=5000) hoặc tắt Live Server. Dùng 127.0.0.1 thay localhost tránh IPv6 issues trên Windows 11.
Sử dụng Claude AI để generate cấu trúc project, debug Flask streaming error, tối ưu gesture recognition algorithm, và design giao diện frontend. Gemini hỗ trợ tra cứu MediaPipe API documentation.
YouTube Reference: Touchless HMI with MediaPipe Tutorial
Tuần này là lần đầu tiên tôi xây dựng hệ thống computer vision hoàn chỉnh từ đầu đến cuối — từ capture webcam, xử lý MediaPipe, đến streaming qua Flask và hiển thị trên browser.
Điều ấn tượng nhất là MediaPipe Hands có thể phát hiện 21 điểm mốc trên bàn tay với độ trễ rất thấp ngay cả trên CPU thông thường. Tích hợp vào Flask để stream video real-time ban đầu khó vì tôi không quen với generator pattern trong Python.
Khó khăn lớn nhất là debug phần streaming response — khi headers bị gửi 2 lần sẽ crash server. Sau khi đọc Flask documentation và dùng AI giải thích error traceback, tôi hiểu cần wrap generator trong try/except và kiểm tra frame validity trước khi yield.
Bài học quan trọng: không copy code mà không hiểu flow. Mỗi lần gặp bug tôi trace từng dòng để hiểu thực sự tại sao lỗi xảy ra, thay vì chỉ hỏi AI để fix. Cách này giúp học được nhiều hơn về cả Python lẫn web development.