-
Notifications
You must be signed in to change notification settings - Fork 0
/
presenter.py
141 lines (114 loc) · 5.58 KB
/
presenter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import os
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector
def start_presenting(slide_directory_name: str) -> None:
# Local Variables
slides = []
cur_slide = 0
allow_slide_change_gesture = True
drawings = []
drawing_continuation = False
# Collecting the slides in the slide directory
# and sorting based on length also to prevent "10.*" coming after "1.*" instead of "2.*"
slides = sorted(os.listdir(slide_directory_name), key=len)
# Saving all slides with thier names and paths
slides = list(
map(os.path.join, [slide_directory_name] * len(slides), slides))
# Keeping only files with a known image extension
slides = [_ for _ in slides if _.split(
'.')[-1] in ['jpeg', 'png', 'jpg', 'svg', 'webp']]
# Starting up presenter's video capture
presenter_video_capture = cv2.VideoCapture(0)
# Setting up hand detector
hand_detector = HandDetector(detectionCon=0.8, maxHands=1)
while True:
# Showing presenter's video
success, cur_video_img = presenter_video_capture.read()
cur_video_img = cv2.flip(cur_video_img, 1)
# Showing current slide
cur_slide_image = cv2.imread(slides[cur_slide])
# Finding hands
hands, cur_video_img = hand_detector.findHands(
cur_video_img)
# Drawing a gesture threshold line
cv2.line(cur_video_img, (0, threshold_height := int(cur_video_img.shape[0] / 2)),
(int(cur_video_img.shape[1]), int(threshold_height)), (0, 0, 255), 5)
# Finding number of fingers up
if hands:
hands = hands[0]
# Finding center of hand for setting gesture threshold
cur_hands_pos_y = hands["center"][1]
# Finding landmarks of the hand
landmarks_list = hands["lmList"]
# Finding index finger and constraining it to half of the slides
index_finger_x = int(np.interp(landmarks_list[8][0], [int(
cur_video_img.shape[1]) // 2 + 100, int(cur_video_img.shape[1]) - 100], [0, int(cur_slide_image.shape[1])]))
index_finger_y = int(np.interp(landmarks_list[8][1], [
150, int(cur_video_img.shape[0])-150], [0, int(cur_slide_image.shape[0])]))
# Finding currently up fingers
fingers = hand_detector.fingersUp(hands)
# Checking for threshold height and hand position
# for getures that need to done above threshold line
if cur_hands_pos_y < threshold_height:
# Adding slide_change gesture
if fingers == [1, 0, 0, 0, 0]:
if cur_slide > 0 and allow_slide_change_gesture:
cur_slide -= 1
allow_slide_change_gesture = False
# Clearing out any drawings
drawings = []
drawing_continuation = False
elif fingers == [0, 0, 0, 0, 1]:
if cur_slide < len(slides) - 1 and allow_slide_change_gesture:
cur_slide += 1
allow_slide_change_gesture = False
# Clearing out any drawings
drawings = []
drawing_continuation = False
else:
allow_slide_change_gesture = True
# Adding clear_drawings gesture
if fingers == [0, 1, 1, 1, 0]:
drawings = []
drawing_continuation = False
# Adding pointer gesture
if fingers == [0, 1, 0, 0, 0]:
cv2.circle(cur_slide_image, (index_finger_x,
index_finger_y), 15, (0, 0, 255), cv2.FILLED)
# Adding drawing gesture
if fingers == [0, 1, 1, 0, 0]:
cv2.circle(cur_slide_image, (index_finger_x,
index_finger_y), 15, (0, 0, 255), cv2.FILLED)
# drawing_continuation defines if we are in the drawing same as previous drawing or a new drawing
# this is important so that different across the slide don't get joined without the choice of user
if drawing_continuation:
drawings[-1].append((index_finger_x, index_finger_y))
else:
drawings.append([(index_finger_x, index_finger_y)])
drawing_continuation = True
else:
drawing_continuation = False
# Adding all the current drawings to the current slide image
for drawing in drawings:
for i in range(1, len(drawing)):
cv2.line(cur_slide_image,
drawing[i-1], drawing[i], (0, 0, 255), 10)
# Placing presenter's video on top of slide
presentation_slide_height, presentation_slide_width, _ = cur_slide_image.shape
presenter_video_cur_img = cv2.resize(cur_video_img, (200, 113))
cur_slide_image[presentation_slide_height - 113:presentation_slide_height,
presentation_slide_width - 200: presentation_slide_width] = presenter_video_cur_img
# Showing the cur_slide_image
cv2.imshow("Presentation", cur_slide_image)
# Setting a key to stop video capture
key = cv2.waitKey(1)
if key == ord("q") or not success:
break
# Destroying all windows
cv2.destroyAllWindows()
def main():
Slide_directory_name = input("Enter slide directory path : ")
start_presenting(Slide_directory_name)
if __name__ == "__main__":
main()