Phần I. Giới thiệu 1. Giới thiệu công nghệ Hand Tracking(Theo dõi chuyển động bàn tay) Ngày nay công nghệ thông tin đang ngày càng phát triển mạnh mẽ, trong đó công nghệ thực tế ảo đang được chú trọng và được rất nhiều các nước và các công ty công nghệ hàng đầu quan tâm. Hiện này, hầu hết sự tuơng tác giữa con người với công nghệ thực tế ảo đều thông qua các thiết bị hỗ trợ như găng tay cảm biến, … . Vậy nên để có thể tương tác với công nghệ ảo mà không cần thiết bị hỗ trợ thì cần phải có một công nghệ thay thế. Hand tracking là công nghệ được phát triển để theo dõi chuyển động và mô phỏng lại mô hình của bàn tay trong không gian. Việc này được thực hiện bằng các phân tích các hình ảnh thông qua video. Và sau đó bàn tay được mô phỏng lại bằng mô hình 3D.
Trang 1HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
KHOA KỸ THUẬT ĐIỆN TỬ 1
**************
BÁO CÁO BÀI TẬP LỚN
ĐỀ TÀI: NHẬN DIỆN CỬ CHỈ TAY
HỌC PHẦN: TRUYỀN THÔNG ĐA PHƯƠNG TIỆN
Trang 2Mục lục
LỜI MỞ ĐẦU 1
Phần I Giới thiệu 2
Phần II Chuẩn bị 2
1 Ngôn ngữ lập trình python 2
2 Thư viện openCV 2
3 Thư viện mediapipe 2
4 Máy tính và camera 3
Phần III Cách thức hoạt động 3
1 Phát hiện dấu mốc bàn tay 3D theo thời gian thực 3
2 Xây dựng bộ đếm ngón tay 4
3 Xây dựng chức năng trò chơi kéo búa bao 4
Phần IV Code 5
Phần V Kết quả 8
LỜI CẢM ƠN 9
Trang 3LỜI MỞ ĐẦU
Ngày nay cùng với sự phát triển của ngành khoa học kỹ thuật, kỹ thuật điện tử đóng vai trò quan trọng trong mỗi lĩnh vực khoa học kỹ thuật, quản lý, công nghiệp tự động hóa, cung cấp thông tin do đó chúng ta phải nắm bắt và vận dụng một cách có hiệu quả nhằm góp phần vào sự phát triển của nền khoa học kĩ thuật thế giới nói chung
và trong kỹ thuật điện tử nói riêng
Cùng với sự tiến bộ của khoa học công nghệ các thiết bị điện tử đang và sẽ tiếp tục được ứng dụng ngày càng rộng rãi và mang lại hiệu quả cao trong hầu hết các lĩnh vực kinh tế, kỹ thuật cũng như đời sống xã hội Nhờ vào sự tiến bộ của công nghệ xử
lý hình ảnh, ngày càng nhiều các thiết bị có khả năng ghi nhận cử chỉ tay và chuyển đổi thành các tín hiệu có thể xử lý bằng máy tính Vậy nên chúng em đã nghiên cứu và tìm hiểu đề tài “Nhận diện cử chỉ tay”.
Trang 4Phần I Giới thiệu
1 Giới thiệu công nghệ Hand Tracking(Theo dõi chuyển động bàn tay)
Ngày nay công nghệ thông tin đang ngày càng phát triển mạnh mẽ, trong đó công nghệ thực tế ảo đang được chú trọng và được rất nhiều các nước và các công ty công nghệ hàng đầu quan tâm.
Hiện này, hầu hết sự tuơng tác giữa con người với công nghệ thực tế ảo đều thông qua các thiết bị hỗ trợ như găng tay cảm biến, … Vậy nên để có thể tương tác với công nghệ ảo mà không cần thiết bị hỗ trợ thì cần phải có một công nghệ thay thế.
Hand tracking là công nghệ được phát triển để theo dõi chuyển động và mô phỏng lại mô hình của bàn tay trong không gian Việc này được thực hiện bằng các phân tích các hình ảnh thông qua video Và sau đó bàn tay được mô phỏng lại bằng mô hình 3D.
2 Tổng quan về đề tài
Đề tài Nhận dạng cử chỉ bàn tay , chúng em sẽ xây dựng dựa trên 3 công
việc chính:
Xây dựng ứng dụng nhận diện bàn tay và vẽ ra 21 điểm 3D trên bàn tay
Xây dựng chức năng đếm số ngón tay
Xây dựng trò chơi kéo búa bao
Phần II Chuẩn bị
1 Ngôn ngữ lập trình python
Python là ngôn ngữ lập trình đa năng ra đời năm 1991 do Guido van Rossum sáng tạo ra Đây là ngôn ngữ lập trình với những điểm mạnh như dễ đọc, dễ nhớ, dễ học Với cấu trúc rõ ràng, thuận tiện nên thu hút khá nhiều người mong muốn học ngôn ngữ này.
2 Thư viện openCV
OpenCV là tên viết tắt của open source computer vision library – có thể được hiểu là một thư viện nguồn mở cho máy tính Cụ thể hơn OpenCV là kho lưu trữ các mã nguồn mở được dùng để xử lý hình ảnh, phát triển các ứng dụng đồ họa trong thời gian thực.
OpenCV cho phép cải thiện tốc độ của CPU khi thực hiện các hoạt động real time Nó còn cung cấp một số lượng lớn các mã xử lý phục vụ cho quy trình của thị giác máy tính hay các learning machine khác.
3 Thư viện mediapipe
2
Trang 5MediaPipe là tập hợp của một loạt các giải pháp Machine Learning đa nền tảng, có thể can thiệp được và cực kỳ nhẹ Một số ưu điểm có thể kể tới của giải pháp này bao gồm:
Cung cấp một giải pháp inference nhanh chóng: Google khẳng định rằng
bộ công cụ này có thể chạy ổn định trên hầu hết các cấu hình phần cứng thông dụng.
Dễ dàng cài đặt và triển khai: Việc cài đặt cực kỳ dễ dàng và tiện lợi, có thể triển khai trên nhiều nền tảng khác nhau như Mobile (Android/iOS), Desktop/Cloud, Web và IoT devices.
Mã nguồn mở và miễn phí: Toàn bộ source code được công khai trên MediaPipe, người dùng hoàn toàn có thể sử dụng và tùy chỉnh trực tiếp để phù hợp với bài toán của mình
4 Máy tính và camera
Phần III Cách thức hoạt động
1 Phát hiện dấu mốc bàn tay 3D theo thời gian thực
Thư viện Mediapipe cung cấp một giải pháp mạnh mẽ có khả năng dự đoán 21
điểm mốc 3D trong thời gian thực với độ chính xác và tốc độ cao, ngay cả trên các
thiết bị cấp thấp như điện thoại, máy tính xách tay, v.v., điều này làm cho nó nổi bật hơn so với các thiết bị khác giải pháp ra khỏi đó.
Hình ảnh bên dưới cho thấy 21 mốc bàn tay mà giải pháp này phát hiện cùng với các chỉ mục của chúng.
Để có thể phát hiện chính xác được 21 điểm mốc bàn tay này , các nhà phát triển
đã phải đánh dấu thủ công 30K hình ảnh trong thế giới thực với tọa độ 3D bằng cách sử dụng bản đồ độ sâu hình ảnh.
Giải pháp: chúng ta phải khởi tạo lớp hands bằng mp.solutions.hands cú pháp
và sau đó chúng ta sẽ phải gọi hàm mp.solutions.hands.Hands() với các tham số:
static_image_mode - Đây là một giá trị boolean mà nếu được đặt
thành False, giải pháp sẽ coi các hình ảnh đầu vào như một luồng
Trang 6video. Nó sẽ cố gắng phát hiện bàn tay trong các hình ảnh đầu vào đầu tiên và khi phát hiện thành công sẽ bản địa hóa thêm các mốc bàn tay. Nếu được đặt thành True, tính năng phát hiện bàn tay sẽ chạy trên mọi hình ảnh đầu vào lý tưởng để xử lý một loạt hình ảnh tĩnh, có thể không liên quan. Giá trị mặc định của nó là False.
max_num_hands : Đó là số lượng bàn tay tối đa để phát hiện. Giá trị
mặc định của nó là 2.
min_detection_confidence : Đây là độ tin cậy phát hiện tối thiểu ([0.0,
1.0]) cần thiết để coi dự đoán của mô hình phát hiện lòng bàn tay là chính xác. Giá trị mặc định của là tất cả các nó 0.5 có nghĩa phát hiện có
độ tin cậy dự đoán nhỏ hơn 50% sẽ bị bỏ qua theo mặc định.
min_tracking_confidence : Đó là độ tin cậy theo dõi tối thiểu ([0.0,
1.0]) cần thiết để coi các mốc bàn tay được theo dõi của mô hình theo dõi mốc là hợp lệ. Nếu độ tin cậy nhỏ hơn giá trị đối số này thì trình phát hiện lại được gọi trong khung hình / hình ảnh tiếp theo, do đó, việc tăng giá trị của nó sẽ làm tăng độ chắc chắn, nhưng cũng làm tăng độ trễ. Giá trị mặc định của nó là 0.5.
2 Xây dựng bộ đếm ngón tay
Nguyên lí hoạt động:Sau khi có được kết quả của 21 điểm mốc ngón tay và đánh dấu chúng , ta sẽ thực hiện như sau:
So sánh tọa độ y của FINGER_TIP mốc và FINGER_PIP mốc của từng ngón tay. Nếu tọa độ y của FINGER_TIP có giá trị thấp hơn giá trị của FINGER_PIP thì ngón tay đang duỗi thẳng và ngược lại.
Nhưng đối với các ngón tay cái sẽ khác một chút vì chúng ta sẽ phải so sánh tọa độ x của THUMB_TIP mốc và THUMB_MCP mốc và điều kiện sẽ thay đổi tùy thuộc vào việc tay trái hay tay phải Đối với tay phải, bất cứ khi nào ngón tay cái mở, tọa độ x của mốc THUMB_TIP sẽ có giá trị thấp hơn so với mốc THUMB_MCP và ngược lại đối với tay trái.
3 Xây dựng chức năng trò chơi kéo búa bao
4
Trang 7Dựa vào kết quả của phần phát hiện dấu mốc bàn tay , chúng ta sẽ có một mảng lưu trữ giá trị trạng thái của các ngón tay :
Nếu trạng thái của 2 ngón tay bên trái là True(tương đương với cái kéo) ,
và trạng thái của 5 ngón tay bên phải là False(tương đương với cái búa) thì bên phải sẽ thắng và ngược lại
Nếu trạng thái của 5 ngón tay nên trái là True(tương đương với cái lá) ,
và trạng thái của 5 ngón tay bên phải là False( tương đương với cái búa) thì bên phải thắng và ngược lại
Nếu trạng thái của 2 ngón tay bên trái là True (tương đương với cái kéo)
và trạng thái của 5 ngón tay bên phải là True(tương đương với cái lá) thì bên trái thắng và ngược lại
Nếu các trạng thái các ngón tay tương ứng của 2 bên giống nhau thì kết quả sẽ là hòa
Phần IV Code
import cv2
import time
import mediapipe as mp
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=True, max_num_hands= , min_detection_confidence=0.5)
hands_videos = mp_hands.Hands(static_image_mode=False, max_num_hands= ,
min_detection_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
pTime = 0
cap = cv2.VideoCapture(0)
def detectHandsLandmarks(image, hands,draw=True):
output_image = image.copy()
imgRGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = hands.process(imgRGB)# phát hiện dấu hiệu bàn tay
if results.multi_hand_landmarks and draw: #kiểm tra xem có điểm mốc vẽ bàn tay không
for hand_landmarks in results.multi_hand_landmarks: #lặp lại các điểm bàn tay
mp_drawing.draw_landmarks(image=output_image, landmark_list=hand_landmarks,
connections=mp_hands.HAND_CONNECTIONS,
landmark_drawing_spec=mp_drawing.DrawingSpec(color=(255, 255, 255),
thickness= , circle_radius= ),
connection_drawing_spec=mp_drawing.DrawingSpec(color=(0 255, ),
thickness= , circle_radius= ))#vẽ các điểm mốc trên bàn tay
return output_image, results
def countFingers(image,result): # hàm đếm số ngón tay
height, width,_ = image.shape #lấy kích thước ảnh
output_image = image.copy()
count = {'RIGHT': , 'LEFT': } # biến lưu số ngón tay
fingers_tips_ids = [mp_hands.HandLandmark.INDEX_FINGER_TIP,
mp_hands.HandLandmark.MIDDLE_FINGER_TIP,
mp_hands.HandLandmark.RING_FINGER_TIP, mp_hands.HandLandmark.PINKY_TIP] #lưu chỉ số của các mốc ngón tay
fingers_statuses = {'RIGHT_THUMB': False, 'RIGHT_INDEX': False, 'RIGHT_MIDDLE': False,
'RIGHT_RING': False,
'RIGHT_PINKY': False, 'LEFT_THUMB': False, 'LEFT_INDEX': False, 'LEFT_MIDDLE':
Trang 8'LEFT_RING': False, 'LEFT_PINKY': False} #chỗ lưu trạng thái từng ngón tay
for hand_index, hand_info in enumerate(results.multi_handedness):
hand_label = hand_info.classification[0].label # lấy nhãn các bàn tay đc tìm thấy
hand_landmarks = results.multi_hand_landmarks[hand_index]# lấy các điểm mốc
for tip_index in fingers_tips_ids: #lặp các chỉ số của mỗi ngón tay
finger_name = tip_index.name.split("_")[0] # truy xuất nhãn
if (hand_landmarks.landmark[tip_index].y < hand_landmarks.landmark[tip_index - 2].y):
fingers_statuses[hand_label.upper() + "_" + finger_name] = True
count[hand_label.upper()] += 1
#check ngón tay cái
thumb_tip_x = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP].x
thumb_mcp_x = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP - 2].x
if ((hand_label == 'Right' and (thumb_tip_x < thumb_mcp_x)) or (hand_label == 'Left' and (thumb_tip_x >
thumb_mcp_x))):
fingers_statuses[hand_label.upper() + "_THUMB"] = True
count[hand_label.upper()] += 1
return output_image, fingers_statuses, count,width
def displaycounter(frame,width):
cv2.putText(frame, str(sum(count.values())), (width // 2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 8.9, (20, 255, 155), 10, 10)
def keobuala(frame,fingers_statuses,width):# trò chơi kéo búa bao
cv2.putText(frame, 'Player1', (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ), 2)
cv2.putText(frame, 'Player2', (450, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ), 2)
#truong hop keo bua
if(fingers_statuses['LEFT_THUMB']== False and fingers_statuses['LEFT_INDEX']== True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB']==False
and fingers_statuses['RIGHT_INDEX']==False and fingers_statuses['RIGHT_MIDDLE'] == False
and fingers_statuses['RIGHT_RING'] ==False and fingers_statuses['RIGHT_PINKY']==False):
cv2.putText(frame, 'Player2 Win', (width//2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ),
2)
elif(fingers_statuses['LEFT_THUMB']== False and fingers_statuses['LEFT_INDEX']== False
and fingers_statuses['LEFT_MIDDLE'] == False and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB']==False
and fingers_statuses['RIGHT_INDEX']==True and fingers_statuses['RIGHT_MIDDLE'] == True
and fingers_statuses['RIGHT_RING'] ==False and fingers_statuses['RIGHT_PINKY']==False):
cv2.putText(frame, 'Player1 Win', (width//2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ),
2)
#truong hop bua la
elif (fingers_statuses['LEFT_THUMB'] == True and fingers_statuses['LEFT_INDEX'] == True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == True
and fingers_statuses['LEFT_PINKY'] == True and fingers_statuses['RIGHT_THUMB'] == False
and fingers_statuses['RIGHT_INDEX'] == False and fingers_statuses['RIGHT_MIDDLE'] == False and fingers_statuses['RIGHT_RING'] == False and fingers_statuses['RIGHT_PINKY'] == False):
cv2.putText(frame, 'Player1 Win', (width // 2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, 0), 2)
elif (fingers_statuses['LEFT_THUMB'] == False and fingers_statuses['LEFT_INDEX'] == False
and fingers_statuses['LEFT_MIDDLE'] == False and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB'] == True
and fingers_statuses['RIGHT_INDEX'] == True and fingers_statuses['RIGHT_MIDDLE'] == True and fingers_statuses['RIGHT_RING'] == True and fingers_statuses['RIGHT_PINKY'] == True):
cv2.putText(frame, 'Player2 Win', (width // 2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, 0), 2)
#trương hop keo la
elif (fingers_statuses['LEFT_THUMB'] == False and fingers_statuses['LEFT_INDEX'] == True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB'] == True
and fingers_statuses['RIGHT_INDEX'] == True and fingers_statuses['RIGHT_MIDDLE'] == True
6
Trang 9and fingers_statuses['RIGHT_RING'] == True and fingers_statuses['RIGHT_PINKY'] == True):
cv2.putText(frame, 'Player1 Win', (width // 2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, 0), 2)
elif (fingers_statuses['LEFT_THUMB'] == True and fingers_statuses['LEFT_INDEX'] == True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == True
and fingers_statuses['LEFT_PINKY'] == True and fingers_statuses['RIGHT_THUMB'] == False
and fingers_statuses['RIGHT_INDEX'] == True and fingers_statuses['RIGHT_MIDDLE'] == True and fingers_statuses['RIGHT_RING'] == False and fingers_statuses['RIGHT_PINKY'] == False):
cv2.putText(frame, 'Player2 Win', (width // 2 - 150, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, 0), 2)
#truong hop hoa
elif (fingers_statuses['LEFT_THUMB'] == True and fingers_statuses['LEFT_INDEX'] == True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == True
and fingers_statuses['LEFT_PINKY'] == True and fingers_statuses['RIGHT_THUMB'] == True
and fingers_statuses['RIGHT_INDEX'] == True and fingers_statuses['RIGHT_MIDDLE'] == True and fingers_statuses['RIGHT_RING'] == True and fingers_statuses['RIGHT_PINKY'] == True):
cv2.putText(frame, 'HOA', (width // 2 - 100, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ), 2) elif (fingers_statuses['LEFT_THUMB'] == False and fingers_statuses['LEFT_INDEX'] == False
and fingers_statuses['LEFT_MIDDLE'] == False and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB'] == False
and fingers_statuses['RIGHT_INDEX'] == False and fingers_statuses['RIGHT_MIDDLE'] == False and fingers_statuses['RIGHT_RING'] == False and fingers_statuses['RIGHT_PINKY'] == False):
cv2.putText(frame, 'HOA', (width // 2 - 100, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ), 2) elif (fingers_statuses['LEFT_THUMB'] == False and fingers_statuses['LEFT_INDEX'] == True
and fingers_statuses['LEFT_MIDDLE'] == True and fingers_statuses['LEFT_RING'] == False
and fingers_statuses['LEFT_PINKY'] == False and fingers_statuses['RIGHT_THUMB'] == False
and fingers_statuses['RIGHT_INDEX'] == True and fingers_statuses['RIGHT_MIDDLE'] == True and fingers_statuses['RIGHT_RING'] == False and fingers_statuses['RIGHT_PINKY'] == False):
cv2.putText(frame, 'HOA', (width // 2 - 100, 240), cv2 FONT_HERSHEY_SIMPLEX, 1.5, (0 255, ), 2)
while True:
success, img = cap.read()
imggray = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
frame, results = detectHandsLandmarks(img, hands_videos)
if results.multi_hand_landmarks:
frame, fingers_statuses, count,width = countFingers(frame, results)
#displaycounter(frame,width)
keobuala(frame,fingers_statuses,width)
print(fingers_statuses)
cv2.putText(frame, f'FPS: {int(fps)}', (10, 30), cv2.FONT_HERSHEY_PLAIN,2, (0 255, ), 1)
cv2.imshow('Image', frame)
if cv2.waitKey(10) & 0x FF == ord('q'):
break
cap.release()
cv2.destroyWindow()
Trang 10Phần V Kết quả
1.Demo đếm số ngón tay
2.Demo trò chơi kéo búa lá
8