-
Notifications
You must be signed in to change notification settings - Fork 4
/
HEDAS_code.py
441 lines (390 loc) · 24.6 KB
/
HEDAS_code.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# Libraries
from tkinter import *
from tkinter import messagebox
import PIL
from PIL import Image,ImageTk
from numpy.lib.function_base import angle
import socket
import serial
import serial.tools.list_ports
from threading import Thread
from time import sleep, time
import numpy as np
import trace
import json
import sys
import os
import cv2
import math
# creates a Tk() object
master = Tk()
#global variables
ready = False
arduino = ""
angles_raw = [0]*19
angles = [0]*23
unity = False
done = True
val = 0
sock = 0
s = 0
button_web = 0
# Variables for calibration
angle_calibration_MCP = [0,45,80]
angle_calibration_PIP = [0,45,90]
angle_calibration_wrist = [-45,0,45]
x_MCP = [[0] * 3 for i1 in range(5)]
x_PIP = [[0] * 3 for i1 in range(5)]
z_MCP = [0]*7
wrist_val = [0] * 3
coeff_MCP = [[0] * 3 for i1 in range(5)]
coeff_PIP = [[0] * 3 for i1 in range(5)]
coeff_wrist = [0] * 3
#webcam variables
color_prox = (255, 255, 0)
color_meta = (0, 255, 0)
color_hand = (0, 0, 255)
alpha = 0.4
thickness = 10
show_cam = False
cap = 0
#----------------------------function/thread for the interface--------------------------#
# 1) Main page: asking for the Port to which the Arduino is connected
def interface():
global master
master.title("H.E.D.A.S (Hand Exoskeleton Data Acquisition System)")
master.state('zoomed')
master.config(bg = 'medium aquamarine')
ports = serial.tools.list_ports.comports(include_links=False) #looking for the acive ports
if (len(ports) != 0): # we found a port
label = Label(master, text ="Choose the port to which the device is connected:", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 150)
for port in ports : # we display the ports' name on buttons
Button(master, text = port.device, command = lambda : Calibration(port.device), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').pack(pady = 20)
else: # else we need to connect the device and relaunch the program
label = Label(master, text = "No port found. Connect a device and relaunch the program", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 300)
# 2) Page where there is a choice between calibrating and using a previous calibration
def Calibration(portDevice):
global master,ready,arduino
arduino = serial.Serial(port=portDevice, baudrate=115200, timeout=.1) # the arduino is connected to Python
ready = True # the read_function can start reading the Arduino data
eraseWidget()
# checking if a file exists
if os.path.isfile(os.path.join(path + os.sep, "sample.json")):
Label(master, text ="Do you want to calibrate or use a previous calibration profile?", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 150)
Button(master, text = "New calibration", command = calibration, font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').pack(pady = 10)
Button(master, text = "Use a user calibration profile", command = NoCal, font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').pack(pady = 50)
else:
Label(master, text ="You didn't calibrate yet... Create a new calibration", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 150)
Button(master, text = "New calibration", command = calibration, font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').pack(pady = 10)
# 3) Calibration process with 5 steps
def calibration():
global master, val, show_cam,cap,thread1, button_web
eraseWidget()
if val == 0:
Label(master, text ="Put your hand flat with the thumb as far as possible from the fingers", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
Label(master, text ="And your hand must be aligned with your arm", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
image1 = Image.open(os.path.join(path + os.sep, "image","open_profile.png"))
image2 = Image.open(os.path.join(path + os.sep, "image","open_face.png"))
test1 = ImageTk.PhotoImage(image1)
label1 = Label(image=test1, bg = 'medium aquamarine')
label1.image = test1
test2 = ImageTk.PhotoImage(image2)
label2 = Label(image=test2, bg = 'medium aquamarine')
label2.image = test2
label1.place(x=225,y = master.winfo_height()/2,anchor = CENTER)
label2.place(x=650,y = master.winfo_height()/2,anchor = CENTER)
if not show_cam:
Button(master, text = "Show the webcam", command = lambda : show(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
Label(master, text ="This will return the video of your webcam (if you have a one).", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+55,anchor = CENTER)
Label(master, text ="The same indicator as in the picture will show on the video", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+95,anchor = CENTER)
Label(master, text ="to help you positioning your fingers.", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+135,anchor = CENTER)
Label(master, text ="Opening the webcam can take a couple of seconds", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+175,anchor = CENTER)
if val == 1:
Label(master, text ="Fold your fingers in the same position as in the picture", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
image1 = Image.open(os.path.join(path + os.sep,"image", "45_finger.png"))
image2 = Image.open(os.path.join(path + os.sep,"image", "45_thumb.png"))
test1 = ImageTk.PhotoImage(image1)
label1 = Label(image=test1, bg = 'medium aquamarine')
label1.image = test1
test2 = ImageTk.PhotoImage(image2)
label2 = Label(image=test2, bg = 'medium aquamarine')
label2.image = test2
label1.place(x=225,y = master.winfo_height()/2,anchor = CENTER)
label2.place(x=650,y = master.winfo_height()/2,anchor = CENTER)
if not show_cam:
Button(master, text = "Show the webcam", command = lambda : show(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
Label(master, text ="This will return the video of your webcam (if you have a one).", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+55,anchor = CENTER)
Label(master, text ="The same indicator as in the picture will show on the video", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+95,anchor = CENTER)
Label(master, text ="to help you positioning your fingers.", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+135,anchor = CENTER)
Label(master, text ="Opening the webcam can take a couple of seconds", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+175,anchor = CENTER)
if val == 2:
Label(master, text = "Fold your fingers in the same position as in the picture", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
image1 = Image.open(os.path.join(path + os.sep,"image", "90_finger.png"))
image2 = Image.open(os.path.join(path + os.sep,"image", "90_thumb.png"))
test1 = ImageTk.PhotoImage(image1)
label1 = Label(image=test1, bg = 'medium aquamarine')
label1.image = test1
test2 = ImageTk.PhotoImage(image2)
label2 = Label(image=test2, bg = 'medium aquamarine')
label2.image = test2
label1.place(x=225,y = master.winfo_height()/2,anchor = CENTER)
label2.place(x=650,y = master.winfo_height()/2,anchor = CENTER)
if not show_cam:
Button(master, text = "Show the webcam", command = lambda : show(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
Label(master, text ="This will return the video of your webcam (if you have a one).", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+55,anchor = CENTER)
Label(master, text ="The same indicator as in the picture will show on the video", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+95,anchor = CENTER)
Label(master, text ="to help you positioning your fingers.", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+135,anchor = CENTER)
Label(master, text ="Opening the webcam can take a couple of seconds", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+175,anchor = CENTER)
if val == 3:
Label(master, text ="Fold your wrist until your hand forms a -45° angle", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
Label(master, text ="with your arm as in the picture", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
image1 = Image.open(os.path.join(path + os.sep,"image", "_45_wrist.png"))
test1 = ImageTk.PhotoImage(image1)
label1 = Label(image=test1, bg = 'medium aquamarine')
label1.image = test1
label1.place(x=400,y = master.winfo_height()/2,anchor = CENTER)
if not show_cam:
Button(master, text = "Show the webcam", command = lambda : show(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
Label(master, text ="This will return the video of your webcam (if you have a one).", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+55,anchor = CENTER)
Label(master, text ="The same indicator as in the picture will show on the video", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+95,anchor = CENTER)
Label(master, text ="to help you positioning your fingers.", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+135,anchor = CENTER)
Label(master, text ="Opening the webcam can take a couple of seconds", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+175,anchor = CENTER)
if val == 4:
Label(master, text ="Fold your wrist the other way until your hand", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
Label(master, text ="forms a 45° angle with your arm as in the picture", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
image1 = Image.open(os.path.join(path + os.sep,"image", "45_wrist.png"))
test1 = ImageTk.PhotoImage(image1)
label1 = Label(image=test1, bg = 'medium aquamarine')
label1.image = test1
label1.place(x=400,y = master.winfo_height()/2,anchor = CENTER)
if not show_cam:
Button(master, text = "Show the webcam", command = lambda : show(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
Label(master, text ="This will return the video of your webcam (if you have a one).", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+55,anchor = CENTER)
Label(master, text ="The same indicator as in the picture will show on the video", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200,y = master.winfo_height()/2+95,anchor = CENTER)
Label(master, text ="to help you positioning your fingers.", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+135,anchor = CENTER)
Label(master, text ="Opening the webcam can take a couple of seconds", font=("Abadi MT Condensed Extra Bold", 15), bg = 'medium aquamarine').place(x=1200+25,y = master.winfo_height()/2+175,anchor = CENTER)
# We ask for a name
if val == 5:
if show_cam:
cap.release()
thread1.kill()
Label(master, text="Enter your calibration name", font=("Abadi MT Condensed Extra Bold", 40), bg = 'medium aquamarine').pack(pady = 300)
entry1 = Entry(master, font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine')
entry1.place(x= master.winfo_width()/2, y = master.winfo_height()/2,anchor = CENTER)
Button(master, text = "Submit!", command = lambda : getName(entry1.get()), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x= master.winfo_width()/2, y = master.winfo_height()/2+100,anchor = CENTER)
if val<5:
Button(master, text = "Done!", command = lambda : get_calibration(), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').place(x=725, y=700)
# 3.1) Function that collects the data necessary to estimate the angle from the potentiometer values
def get_calibration():
global angles_raw, val,coeff_MCP,coeff_PIP,coeff_wrist,wrist_val
eraseWidget()
if val==0:
wrist_val[1] = angles_raw[18]
for i in range(0,7):
z_MCP[i] = angles_raw[i+10]
if val < 3 :
for j in range(0,5):
x_PIP[j][val] = angles_raw[j]
x_MCP[j][val] = angles_raw[j+5]
if val == 3:
wrist_val[0] = angles_raw[18]
if val == 4:
wrist_val[2] = angles_raw[18]
val = val + 1
if val == 5:
for t in range(0,5):
coeff_MCP[t] = np.polyfit(x_MCP[t],angle_calibration_MCP,2).tolist()
coeff_PIP[t] = np.polyfit(x_PIP[t],angle_calibration_PIP,2).tolist()
coeff_wrist = np.polyfit(wrist_val,angle_calibration_wrist,2).tolist()
calibration() # it always goes back to the calibration function
# shows the webcam if activated
def show():
global show_cam,cap
show_cam = True
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 720)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 540)
thread1.start()
calibration()
#3.2) ONce the calibration is finished, the program needs to save the data in a JSON file
def getName(name):
global coeff_MCP, coeff_PIP, z_MCP, coeff_wrist
if os.path.isfile(os.path.join(path + os.sep, "sample.json")): # it verifies if a file already exists
with open(os.path.join(path + os.sep, "sample.json")) as json_open: # if there exists one, it opens it
data = json.load(json_open)
data['Usernames'].append({'name': name,'PIP': coeff_PIP,'MPCx': coeff_MCP,'MPCz': z_MCP,'wrist': coeff_wrist})
with open(os.path.join(path + os.sep, "sample.json"),"w") as json_write:
json.dump(data,json_write)
else: # otherwise we create a file in the directory of the program
data = {}
data['Usernames'] = []
data['Usernames'].append({'name': name,'PIP': coeff_PIP,'MPCx': coeff_MCP,'MPCz': z_MCP,'wrist': coeff_wrist})
with open(os.path.join(path + os.sep, "sample.json"), "w") as json_create:
json.dump(data, json_create)
final_page() # Finally, the code arrives to the final page
# 4) It is called if the user choose to use a previous calibration
def NoCal():
eraseWidget()
Label(master, text ="Choose your calibration profile", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 100)
with open(os.path.join(path + os.sep, "sample.json")) as json_open:
data = json.load(json_open)
for user in data['Usernames'] :
Button(master, text = user['name'], command = lambda username = user: get_coeff(username['PIP'],username['MPCx'],username['MPCz'],username['wrist']), font=("Abadi MT Condensed Extra Bold", 30), bg = 'snow').pack(pady = 10)
# Function that replace the coefficient from the JSON
def get_coeff(PIP, MPCx, MPCz,wrist):
global coeff_MCP, coeff_PIP, z_MCP, coeff_wrist
coeff_PIP = PIP
coeff_MCP = MPCx
z_MCP = MPCz
coeff_wrist = wrist
final_page()
# 5) The final page just display a message (and decides if a connection to Unity occurs)
# A function can be added here with a thread to be used for anything
def final_page():
Unity() #comment this line if you don't want a connection to Unity
eraseWidget()
Label(master, text ="You are ready to use the glove", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 150)
Label(master, text ="The angles are avaibles in the array 'angles'", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack(pady = 10)
Label(master, text ="Or try in UNITY", font=("Abadi MT Condensed Extra Bold", 30), bg = 'medium aquamarine').pack()
# If called, it connects to the socket of Unity
def Unity():
global unity,sock,s
#Unity connection
unity = True
host, port = "127.0.0.1", 25001# IP adress (should be same as client) and port number
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
# test part
'''HOST,PORT = '192.168.43.49',65436
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
'''
#----A class that allows a function/thread to be closed if it's an infinity loop---#
class thread_with_trace(Thread):
def __init__(self, *args, **keywords):
Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self.__run_backup = self.run
self.run = self.__run
Thread.start(self)
def __run(self):
sys.settrace(self.globaltrace)
self.__run_backup()
self.run = self.__run_backup
def globaltrace(self, frame, event, arg):
if event == 'call':
return self.localtrace
else:
return None
def localtrace(self, frame, event, arg):
if self.killed:
if event == 'line':
raise SystemExit()
return self.localtrace
def kill(self):
self.killed = True
#---------------function that treats, arranges and send the data----------------#
def read_function():
global ready,angles_raw,angles,unity,sock,s
while True:
if ready == True:
data = arduino.readline()[:-2]
if data and len(data)==19:
angles_raw = [float(x) for x in data.split()]
for i in range (0,5):
# PIP
angles[i] = poly_reg(coeff_PIP[i], angles_raw[i])
# MCPx
angles[i+5]= poly_reg(coeff_MCP[i], angles_raw[i+5])
for i in range (0,7):
# MCPz
angles[i+10] = potToAngle(z_MCP[i])-potToAngle(angles_raw[i+10])
#wirst values
angles[17] = potToAngle(angles_raw[17])-180
angles[18] = poly_reg(coeff_wrist, angles_raw[18])
for i in range (0,4):
# DIP
angles[i+19] = angles[i+1]*0.88
if unity:
#s.sendall(str(angles[7]).encode('utf-8'))
for i in range (0,23):
angles[i] = int(angles[i]*1000)
sock.sendall(json.dumps(angles).encode())
def show_image():
global show_cam,val,cap
while True:
if show_cam:
_, frame = cap.read()
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
overlay = cv2image.copy()
if val == 0:
cv2.line(overlay, (400,450), (400,300), color_hand, 30)
cv2.line(overlay, (400,300), (400,200), color_meta, 30)
if val == 1:
angles1 = math.pi/4
angles2 = math.pi/4
cv2.line(overlay, (400,400), (400,300), color_hand, thickness)
cv2.line(overlay, (400,300), (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), color_meta, thickness)
cv2.line(overlay, (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), (int(400+50*math.cos(angles1)+50*math.sin(angles2+angles1)),int(300-50*math.sin(angles1)-50*math.cos(angles2+angles1))), color_prox, thickness)
angles1 = math.pi/4*3
angles2 = math.pi/4*3
cv2.line(overlay, (400,300), (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), color_meta, thickness)
cv2.line(overlay, (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), (int(400+50*math.cos(angles1)+50*math.sin(angles2+angles1)),int(300-50*math.sin(angles1)-50*math.cos(angles2+angles1))), color_prox, thickness)
if val == 2:
angles1 = math.radians(0)
angles2 = math.radians(-90)
cv2.line(overlay, (400,400), (400,300), color_hand, thickness)
cv2.line(overlay, (400,300), (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), color_meta, thickness)
cv2.line(overlay, (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), (int(400+50*math.cos(angles1)+50*math.cos(angles2+angles1)),int(300-50*math.sin(angles1)-50*math.sin(angles2+angles1))), color_prox, thickness)
angles1 = math.radians(180)
angles2 = math.radians(90)
cv2.line(overlay, (400,400), (400,300), color_hand, thickness)
cv2.line(overlay, (400,300), (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), color_meta, thickness)
cv2.line(overlay, (int(400+50*math.cos(angles1)),int(300-50*math.sin(angles1))), (int(400+50*math.cos(angles1)+50*math.cos(angles2+angles1)),int(300-50*math.sin(angles1)-50*math.sin(angles2+angles1))), color_prox, thickness)
if val == 3:
angles1 = math.radians(45)
cv2.line(overlay, (400,450), (400,300), color_hand, 30)
cv2.line(overlay, (400,300), (int(400+100*math.cos(angles1)),int(300-100*math.sin(angles1))), color_meta, 30)
if val == 4:
angles1 = math.radians(135)
cv2.line(overlay, (400,450), (400,300), color_hand, 30)
cv2.line(overlay, (400,300), (int(400+100*math.cos(angles1)),int(300-100*math.sin(angles1))), color_meta, 30)
cv2.addWeighted(overlay, alpha, cv2image, 1 - alpha,0, cv2image)
img = PIL.Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
label2 = Label(image=imgtk, bg = 'medium aquamarine')
label2.image = imgtk
label2.place(x=1200,y = master.winfo_height()/2,anchor = CENTER)
#----------general functions--------#
# when the close button is pressed on the window
def on_closing():
global cap,show_cam
if messagebox.askokcancel("Quit", "Do you want to quit?"):
if show_cam:
cv2.destroyAllWindows()
thread1.kill()
thread.kill()
master.quit()
# function that erase every widget on the screen
def eraseWidget():
for widgets in master.winfo_children():
widgets.destroy()
# takes the coeff for argument, return the values to a second degree function
def poly_reg(coeff,val):
return coeff[0] * pow(val,2) + coeff[1]*val + coeff[2]
# function that maps the potentiometer value to an angle (the pot goes from 15° to 345°)
def potToAngle(val):
return val * 330 / (1023 + 15)
# Main where the Threads are started
if __name__ == "__main__":
thread = thread_with_trace(target = read_function) # " " read the values, process it and send it with Socket
thread1 = thread_with_trace(target = show_image) # define the thread/function that shows the webcam
thread2 = Thread(target = interface) # " " shows the interface with Tkinter
#starts the threads 0 and 1
thread2.start()
thread.start()
path = os.path.dirname(os.path.abspath(__file__))
master.protocol("WM_DELETE_WINDOW", on_closing)
master.mainloop()