Compare commits

...

21 Commits

Author SHA1 Message Date
47ca224e2a fixed distance to being straight 2021-02-01 13:57:59 +01:00
7dd4af8db2 bigger font 2021-02-01 13:49:50 +01:00
Michal Maciaszek
def7acc30c improved tracking, added red dot 2021-01-24 17:35:10 +01:00
6872124632 updated requirements 2021-01-23 11:01:17 +01:00
Michal Maciaszek
02c34ca299 SMART-61 write text with ninja 2021-01-17 14:18:51 +01:00
Michal Maciaszek
d4de4a8699 SMART-61 write text with ninja 2021-01-17 14:16:01 +01:00
Michal Maciaszek
11a43331ad better lines 2021-01-17 10:19:13 +01:00
ed00996424 SMART-61 poprawiony kciuk w dol 2021-01-16 15:32:40 +01:00
8521680069 SMART-61 rysowanie ruchem palca po canvasie i zapisywanie obrazka na dysk 2021-01-16 15:04:34 +01:00
bdf51e9f16 SMART-62 - split project view into two frames: top with canvas and (for now) fingers state, bottom with back button and video capturing 2021-01-07 22:13:39 +01:00
1fc537a36c SMART-62 first version of project view - capturing video from camera and displaying fingers info 2021-01-07 20:25:38 +01:00
1116f84ca0 SMART-63 refactorize client app - views extracted into separated files 2021-01-07 18:35:51 +01:00
550c8f4458 Zaktualizuj 'README.md' 2021-01-04 17:24:19 +01:00
5d33d9606f Zaktualizuj 'README.md' 2021-01-04 17:24:09 +01:00
040b260a88 SMART-27 Merge pull request 'gestures' (#11) from gestures into master
Reviewed-on: #11
2021-01-04 17:20:27 +01:00
Michal Maciaszek
6aa3dc2cb4 added fingers 2021-01-03 13:33:47 +01:00
Michal Maciaszek
8aec2319d1 recognize finger straight 2020-12-29 21:46:50 +01:00
Michal Maciaszek
1bbade4884 recognize finger straight 2020-12-29 21:42:16 +01:00
Michal Maciaszek
e05e288875 gestures google 2020-12-28 23:43:48 +01:00
6ff054c84b SMART-19 Merge pull request 'develop' (#10) from develop into master
Reviewed-on: #10
2020-12-21 14:25:53 +01:00
86afc9b2f8 SMART-18 Merge pull request 'projects_view' (#9) from projects_view into develop
Reviewed-on: #9
2020-12-21 14:25:18 +01:00
31 changed files with 682 additions and 271 deletions

View File

@ -23,3 +23,12 @@ To run tests:
`pip3 install -r requirements.txt`
`python3 app.py`
### Gestures module
`cd gestures`
`pip install -r requirements.txt`
`python gesture_recognition.py `

View File

@ -1,14 +1,9 @@
import tkinter as tk
import requests
FONT = ("Verdana", 12)
FONT_B = ("Verdana", 12, 'bold')
FONT_LARGE = ("Verdana", 20)
URL = "http://localhost:8000/api/authenticate"
URL_REGISTER = "http://localhost:8000/api/register"
URL_PROFILE = "http://localhost:8000/api/profile"
URL_PROJECTS = "http://localhost:8000/api/projects"
from constants import LOGIN_VIEW_NAME
from views.login_view import LoginView
from views.main_view import MainView
from views.register_view import RegisterView
class SmartPicasso(tk.Tk):
@ -17,7 +12,7 @@ class SmartPicasso(tk.Tk):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
self.title('SmartPicasso')
self.geometry('610x460')
self.geometry('800x600')
container.pack(side="top", fill="both", expand=True)
@ -29,11 +24,11 @@ class SmartPicasso(tk.Tk):
for F in (LoginView, MainView, RegisterView):
frame = F(container, self)
self.frames[F] = frame
self.frames[F.get_view_name()] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LoginView)
self.show_frame(LOGIN_VIEW_NAME)
def show_frame(self, view, token=None):
frame = self.frames[view]
@ -43,264 +38,5 @@ class SmartPicasso(tk.Tk):
frame.token = token
class LoginView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.pack()
button = tk.Button(self, text="Login", font=FONT,
command=lambda: self.login(controller, input1.get(), input2.get()))
button.pack()
button2 = tk.Button(self, text="Register", font=FONT, command=lambda: controller.show_frame(RegisterView))
button2.pack()
def login(self, controller, login, password):
print(login)
print(password)
data = {
"email": str(login),
"password": str(password)
}
resp = requests.post(URL, json=data)
print(resp)
if resp.status_code == 200:
response = resp.json()
token = response['token']
controller.show_frame(MainView, token)
else:
print("bad pass")
bad_pass_label = tk.Label(self, text='Wrong login/password!', font=FONT)
bad_pass_label.pack()
return ()
class MainView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.frames = {}
self.token = ''
for F in (ProfileView, ProjectsView, ProjectsAddView):
frame = F(parent, controller, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Main menu", font=FONT)
label_u.pack(pady=10, padx=10)
button_projects = tk.Button(self, text="Projects", font=FONT,
command=lambda: self.show_frame(ProjectsView))
button_projects.pack()
button_profile = tk.Button(self, text="My profile", font=FONT,
command=lambda: self.show_frame(ProfileView))
button_profile.pack()
def show_frame(self, view):
frame = self.frames[view]
frame.tkraise()
if self.token:
print(self.token)
frame.token = self.token
frame.start()
class RegisterView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Register", font=FONT)
label_u.pack(pady=10, padx=10)
label0 = tk.Label(self, text='Email:', font=FONT)
label0.pack()
input0 = tk.Entry(self)
input0.pack()
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.pack()
label3 = tk.Label(self, text='First name:', font=FONT)
label3.pack()
input3 = tk.Entry(self)
input3.pack()
label4 = tk.Label(self, text='Last name:', font=FONT)
label4.pack()
input4 = tk.Entry(self)
input4.pack()
button1 = tk.Button(self, text="Register", font=FONT,
command=lambda: self.register(controller, input0.get(), input1.get(), input2.get(),
input3.get(), input4.get()))
button1.pack()
button2 = tk.Button(self, text="Cancel", font=FONT, command=lambda: controller.show_frame(LoginView))
button2.pack()
def register(self, controller, email, login, passw, name, lastname):
data = {
"email": str(email),
"password": str(passw),
"profile": {
"username": str(login),
"first_name": str(name),
"last_name": str(lastname)
}
}
print(data)
response = requests.post(URL_REGISTER, json=data)
print(response)
if response.status_code == 201:
response = response.json()
controller.show_frame(LoginView)
else:
print("sth wrong")
bad_pass_label = tk.Label(self, text='Something went wrong!', font=FONT)
bad_pass_label.pack()
return ()
class ProfileView(tk.Frame):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_l1 = tk.Label(self, text="Login:", font=FONT_B)
label_l1.pack(pady=10, padx=10)
self.label_username = tk.Label(self, text='', font=FONT)
self.label_username.pack(pady=10, padx=10)
label_n1 = tk.Label(self, text="Name:", font=FONT_B)
label_n1.pack(pady=10, padx=10)
self.label_first_name = tk.Label(self, text='', font=FONT)
self.label_first_name.pack(pady=10, padx=10)
label_ln1 = tk.Label(self, text="Last name", font=FONT_B)
label_ln1.pack(pady=10, padx=10)
self.label_last_name = tk.Label(self, text='', font=FONT)
self.label_last_name.pack(pady=10, padx=10)
button_profile = tk.Button(self, text="Back", font=FONT,
command=lambda: controller.show_frame(MainView, self.token))
button_profile.pack()
def start(self):
headers = {'Authorization': 'Bearer ' + self.token}
resp = requests.get(URL_PROFILE, headers=headers)
response = resp.json()
print(response)
self.label_username['text'] = response['profile']['username']
self.label_first_name['text'] = response['profile']['first_name']
self.label_last_name['text'] = response['profile']['last_name']
class ProjectsView(tk.Frame):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
self.projects_buttons = []
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
button_add = tk.Button(self, text="Add project", font=FONT,
command=lambda: main_view_controller.show_frame(ProjectsAddView))
button_add.pack()
button_back = tk.Button(self, text="Back", font=FONT,
command=lambda: controller.show_frame(MainView, self.token))
button_back.pack()
label0 = tk.Label(self, text='Projects:', font=FONT)
label0.pack()
def start(self):
for button in self.projects_buttons:
button.destroy()
self.projects_buttons = []
headers = {'Authorization': 'Bearer ' + self.token}
resp = requests.get(URL_PROJECTS, headers=headers)
response = resp.json()
print(response)
for projects in response:
button_proj = tk.Button(self, text=projects['name'], font=FONT)
button_proj.pack()
self.projects_buttons.append(button_proj)
class ProjectsAddView(tk.Frame):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
label0 = tk.Label(self, text='Project name:', font=FONT)
label0.pack()
input0 = tk.Entry(self)
input0.pack()
button_add = tk.Button(self, text="Confirm and add", font=FONT,
command=lambda: self.add_project(main_view_controller, input0.get()))
button_add.pack()
button_back = tk.Button(self, text="Back", font=FONT,
command=lambda: main_view_controller.show_frame(ProjectsView))
button_back.pack()
def start(self):
print("ok")
def add_project(self, controller, project_name):
headers = {'Authorization': 'Bearer ' + self.token}
data = {
"name": str(project_name)
}
print(data)
response = requests.post(URL_PROJECTS, json=data, headers=headers)
print(response)
if response.status_code == 201:
response = response.json()
controller.show_frame(ProjectsView)
else:
print("sth wrong")
bad_pass_label = tk.Label(self, text='Something went wrong!', font=FONT)
bad_pass_label.pack()
return ()
app = SmartPicasso()
app.mainloop()

17
client/constants.py Normal file
View File

@ -0,0 +1,17 @@
FONT = ("Verdana", 12)
FONT_SM = ("Verdana", 10)
FONT_B = ("Verdana", 12, 'bold')
FONT_LARGE = ("Verdana", 20)
URL_LOGIN = "http://localhost:8000/api/authenticate"
URL_REGISTER = "http://localhost:8000/api/register"
URL_PROFILE = "http://localhost:8000/api/profile"
URL_PROJECTS = "http://localhost:8000/api/projects"
LOGIN_VIEW_NAME = 'login_view'
MAIN_VIEW_NAME = 'main_view'
REGISTER_VIEW_NAME = 'register_view'
PROFILE_VIEW_NAME = 'profile_view'
PROJECT_VIEW_NAME = 'project_view'
PROJECTS_ADD_VIEW_NAME = 'projects_add_view'
PROJECTS_VIEW_NAME = 'projects_view'

View File

@ -0,0 +1,57 @@
import cv2
import mediapipe as mp
import gestures.simple_gestures_lib as sgest
class MyVideoCapture:
def __init__(self):
# Open the video source
self.vid = cv2.VideoCapture(0)
self.vid.set(3, 300)
self.vid.set(4, 150)
self.mp_drawing = mp.solutions.drawing_utils
self.mp_hands = mp.solutions.hands
self.hands = self.mp_hands.Hands(
min_detection_confidence=0.7, min_tracking_confidence=0.7)
if not self.vid.isOpened():
raise ValueError("Unable to open video source", 0)
# Get video source width and height
self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
def get_frame(self):
if self.vid.isOpened():
success, image = self.vid.read()
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
image.flags.writeable = False
results = self.hands.process(image)
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
self.mp_drawing.draw_landmarks(
image, hand_landmarks, self.mp_hands.HAND_CONNECTIONS)
# if cv2.waitKey(33) == ord('s'):
# fingers = {'index': (), 'middle': (), 'ring': (), 'pinky': ()}
fingers = {}
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
fingers['index'] = sgest.check_index_finger(hand_landmarks)
fingers['start_stop'] = sgest.get_start_stop(hand_landmarks)
fingers['ninja'] = sgest.search_for_ninja_turtle(hand_landmarks)
fingers['middle'] = sgest.check_middle_finger(hand_landmarks)
# fingers['ring'] = sgest.check_ring_finger(hand_landmarks)
# fingers['pinky'] = sgest.check_pinky_finger(hand_landmarks)
else:
fingers = None
return fingers, image, success
# Release the video source when the object is destroyed
def release(self):
print('My video capture delete')
if self.vid.isOpened():
self.vid.release()
self.hands.close()

View File

@ -0,0 +1,92 @@
from math import sqrt
INDEX_FINGER_TOP = 8
INDEX_FINGER_BOTTOM = 5
MIDDLE_FINGER_TOP = 12
MIDDLE_FINGER_BOTTOM = 9
RING_FINGER_TOP = 16
RING_FINGER_BOTTOM = 13
PINKY_FINGER_TOP = 20
PINKY_FINGER_BOTTOM = 17
THUMB_TOP = 4
THUMB_CENTER = 3
THUMB_BOTTOM = 2
def calculate_distance(ax, ay, bx, by):
distance = sqrt(((bx - ax) ** 2 + (by - ay) ** 2))
return distance
def get_start_stop(hand_landmarks):
index_finger = check_index_finger(hand_landmarks)
middle_finger = check_middle_finger(hand_landmarks)
ring_finger = check_ring_finger(hand_landmarks)
pinky_finger = check_pinky_finger(hand_landmarks)
is_thumb_near_index = is_thumb_near_index_finger(hand_landmarks)
if not index_finger['straight'] and middle_finger['straight'] and ring_finger['straight'] and pinky_finger['straight'] and is_thumb_near_index:
return 'start'
else:
thumb_top_y = hand_landmarks.landmark[THUMB_TOP].y
thumb_bottom_y = hand_landmarks.landmark[THUMB_BOTTOM].y
is_thumb_straight = check_finger(hand_landmarks, THUMB_TOP, THUMB_BOTTOM)['straight']
if is_thumb_straight:
if thumb_bottom_y + 0.1 < thumb_top_y:
return 'stop'
else:
return 'nothing'
else:
return 'nothing'
def search_for_ninja_turtle(hand_landmarks):
index_finger = check_index_finger(hand_landmarks)
pinky_finger = check_pinky_finger(hand_landmarks)
middle_finger = check_middle_finger(hand_landmarks)
ring_finger = check_ring_finger(hand_landmarks)
if index_finger['straight'] and pinky_finger['straight'] and not middle_finger['straight'] and not ring_finger['straight']:
#return 'ninja'
return {'ninja': 'ninja', 'x': index_finger['x'], 'y': index_finger['y']}
else:
return 'nothing'
def check_index_finger(hand_landmarks):
return check_finger(hand_landmarks, INDEX_FINGER_TOP, INDEX_FINGER_BOTTOM)
def check_middle_finger(hand_landmarks):
return check_finger(hand_landmarks, MIDDLE_FINGER_TOP, MIDDLE_FINGER_BOTTOM)
def check_ring_finger(hand_landmarks):
return check_finger(hand_landmarks, RING_FINGER_TOP, RING_FINGER_BOTTOM)
def check_pinky_finger(hand_landmarks):
return check_finger(hand_landmarks, PINKY_FINGER_TOP, PINKY_FINGER_BOTTOM)
def check_finger(hand_landmarks, top_idx, bottom_idx):
ax = hand_landmarks.landmark[top_idx].x
ay = hand_landmarks.landmark[top_idx].y
bx = hand_landmarks.landmark[bottom_idx].x
by = hand_landmarks.landmark[bottom_idx].y
distance_top_bottom = calculate_distance(ax, ay, bx, by)
ax = hand_landmarks.landmark[bottom_idx].x
ay = hand_landmarks.landmark[bottom_idx].y
bx = hand_landmarks.landmark[0].x
by = hand_landmarks.landmark[0].y
distance_bottom_start = calculate_distance(ax, ay, bx, by)
if distance_bottom_start < distance_top_bottom + 0.05:
straight = True
else:
straight = False
return {'straight': straight, 'x': hand_landmarks.landmark[top_idx].x, 'y': hand_landmarks.landmark[top_idx].y}
def is_thumb_near_index_finger(hand_landmarks):
thumb_top = hand_landmarks.landmark[THUMB_TOP]
index_finger_top = hand_landmarks.landmark[INDEX_FINGER_TOP]
distance = calculate_distance(thumb_top.x, thumb_top.y, index_finger_top.x, index_finger_top.y)
return distance < 0.1

BIN
client/image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,2 +1,5 @@
tk
requests
cv
mediapipe
Pillow

View File

@ -0,0 +1,4 @@
class AbstractView:
@staticmethod
def get_view_name() -> str:
pass

View File

@ -0,0 +1,58 @@
import requests
import tkinter as tk
from constants import FONT, FONT_LARGE, URL_LOGIN, LOGIN_VIEW_NAME, REGISTER_VIEW_NAME, MAIN_VIEW_NAME
from views.abstract_view import AbstractView
class LoginView(tk.Frame, AbstractView):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.insert(0, 'test@test.pl')
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.insert(0, 'test123')
input2.pack()
button = tk.Button(self, text="Login", font=FONT,
command=lambda: self.login(controller, input1.get(), input2.get()))
button.pack()
button2 = tk.Button(self, text="Register", font=FONT, command=lambda: controller.show_frame(REGISTER_VIEW_NAME))
button2.pack()
@staticmethod
def get_view_name() -> str:
return LOGIN_VIEW_NAME
def login(self, controller, login, password):
print(login)
print(password)
data = {
"email": str(login),
"password": str(password)
}
resp = requests.post(URL_LOGIN, json=data)
print(resp)
if resp.status_code == 200:
response = resp.json()
token = response['token']
controller.show_frame(MAIN_VIEW_NAME, token)
else:
print("bad pass")
bad_pass_label = tk.Label(self, text='Wrong login/password!', font=FONT)
bad_pass_label.pack()
return ()

47
client/views/main_view.py Normal file
View File

@ -0,0 +1,47 @@
import tkinter as tk
from constants import FONT, FONT_LARGE, MAIN_VIEW_NAME, PROJECTS_VIEW_NAME, PROFILE_VIEW_NAME
from views.profile_view import ProfileView
from views.project_view import ProjectView
from views.projects_add_view import ProjectsAddView
from views.projects_view import ProjectsView
from views.abstract_view import AbstractView
class MainView(tk.Frame, AbstractView):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.frames = {}
self.token = ''
for F in (ProfileView, ProjectsView, ProjectsAddView, ProjectView):
frame = F(parent, controller, self)
self.frames[F.get_view_name()] = frame
frame.grid(row=0, column=0, sticky="nsew")
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Main menu", font=FONT)
label_u.pack(pady=10, padx=10)
button_projects = tk.Button(self, text="Projects", font=FONT,
command=lambda: self.show_frame(PROJECTS_VIEW_NAME))
button_projects.pack()
button_profile = tk.Button(self, text="My profile", font=FONT,
command=lambda: self.show_frame(PROFILE_VIEW_NAME))
button_profile.pack()
@staticmethod
def get_view_name() -> str:
return MAIN_VIEW_NAME
def show_frame(self, view):
frame = self.frames[view]
frame.tkraise()
if self.token:
print(self.token)
frame.token = self.token
frame.start()

View File

@ -0,0 +1,43 @@
import requests
import tkinter as tk
from constants import FONT, FONT_B, FONT_LARGE, URL_PROFILE, PROFILE_VIEW_NAME, MAIN_VIEW_NAME
from views.abstract_view import AbstractView
class ProfileView(tk.Frame, AbstractView):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_l1 = tk.Label(self, text="Login:", font=FONT_B)
label_l1.pack(pady=10, padx=10)
self.label_username = tk.Label(self, text='', font=FONT)
self.label_username.pack(pady=10, padx=10)
label_n1 = tk.Label(self, text="Name:", font=FONT_B)
label_n1.pack(pady=10, padx=10)
self.label_first_name = tk.Label(self, text='', font=FONT)
self.label_first_name.pack(pady=10, padx=10)
label_ln1 = tk.Label(self, text="Last name", font=FONT_B)
label_ln1.pack(pady=10, padx=10)
self.label_last_name = tk.Label(self, text='', font=FONT)
self.label_last_name.pack(pady=10, padx=10)
button_profile = tk.Button(self, text="Back", font=FONT,
command=lambda: controller.show_frame(MAIN_VIEW_NAME, self.token))
button_profile.pack()
@staticmethod
def get_view_name() -> str:
return PROFILE_VIEW_NAME
def start(self):
headers = {'Authorization': 'Bearer ' + self.token}
resp = requests.get(URL_PROFILE, headers=headers)
response = resp.json()
print(response)
self.label_username['text'] = response['profile']['username']
self.label_first_name['text'] = response['profile']['first_name']
self.label_last_name['text'] = response['profile']['last_name']

View File

@ -0,0 +1,172 @@
import PIL.Image
import PIL.ImageTk
import tkinter as tk
import os
import cv2
from constants import PROJECT_VIEW_NAME, FONT, PROJECTS_VIEW_NAME
from gestures.gesture_recognition import MyVideoCapture
from views.abstract_view import AbstractView
class ProjectView(tk.Frame, AbstractView):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
self.window = controller
self.main_view_controller = main_view_controller
self.delay = 20
self.canvas_width = 800
self.canvas_height = 415
self.start_draw = False
self.vid = None
self.vid_canvas = None
self.canvas = None
self.back_button = None
self.clear_button = None
self.save_button = None
self.bottom_frame = None
self.top_frame = None
self.first_time = True
self.other_gestures_flag_possible = False
@staticmethod
def get_view_name() -> str:
return PROJECT_VIEW_NAME
def start(self):
self.vid = MyVideoCapture()
self.canvas_width = self.window.winfo_width()
self.canvas_height = self.window.winfo_height() - 185
self.top_frame = tk.Frame(self, relief=tk.RAISED, borderwidth=0)
self.top_frame.pack(fill=tk.BOTH, side=tk.TOP)
self.canvas = tk.Canvas(self.top_frame, width=self.canvas_width, height=self.canvas_height, bg="white")
self.canvas.grid(row=0, column=0)
self.bottom_frame = tk.Frame(self, relief=tk.RAISED, borderwidth=1)
self.bottom_frame.pack(fill=tk.BOTH, side=tk.BOTTOM)
self.bottom_frame.columnconfigure(0, weight=1)
self.bottom_frame.columnconfigure(1, weight=1)
self.bottom_frame.columnconfigure(2, weight=15)
self.back_button = tk.Button(self.bottom_frame, text="Back", font=FONT,
command=lambda: self.back_to_projects_view())
self.back_button.grid(row=0, column=0, sticky=tk.SW, pady=10, padx=5)
self.clear_button = tk.Button(self.bottom_frame, text="Clear", font=FONT,
command=lambda: self.clear_canvas())
self.clear_button.grid(row=0, column=1, sticky=tk.SW, pady=10, padx=5)
self.save_button = tk.Button(self.bottom_frame, text="Save", font=FONT,
command=lambda: self.save())
self.save_button.grid(row=0, column=2, sticky=tk.SW, pady=10, padx=5)
self.vid_canvas = tk.Canvas(self.bottom_frame, width=self.vid.width, height=self.vid.height)
self.vid_canvas.grid(row=0, column=3, sticky=tk.E)
self.update()
def create_window(self):
window = tk.Toplevel()
e1 = tk.Entry(window)
e1.grid(row=0, column=1)
okVar = tk.IntVar()
tk.Button(window,text = 'Write',command=lambda: okVar.set(1)).grid(row=1,
column=1,
sticky=tk.W,
pady=4)
#print(okVar)
self.window.wait_variable(okVar)
self.text_to_write = e1.get()
#print(self.text_to_write)
window.destroy()
#self.window.wait_window(window)
def update(self):
# Get a frame from the video source
if self.vid is not None:
fingers, frame, success = self.vid.get_frame()
if fingers is not None:
index_finger = fingers['index']
middle_finger = fingers['middle']
start_stop = fingers['start_stop']
if fingers['ninja'] != 'nothing' and self.other_gestures_flag_possible == True:
#print('trying')
self.create_window()
cv2.waitKey(10)
self.other_gestures_flag_possible = False
x = index_finger['x']
y = index_finger['y']
x, y = self.scale_points(x, y)
self.canvas.create_text(x,y,fill="darkblue", text= self.text_to_write, tags='text',font=("Purisa", 20))
if start_stop == 'start':
print('start')
self.start_draw = True
self.first_time = True
self.other_gestures_flag_possible = False
elif start_stop == 'stop':
print('stop')
self.start_draw = False
self.first_time = False
self.other_gestures_flag_possible = True
if self.start_draw and index_finger['straight'] and middle_finger['straight']:
x = index_finger['x']
y = index_finger['y']
x, y = self.scale_points(x, y)
if self.first_time == True:
self.previous_x = x
self.previous_y = y
self.first_time = False
#print("first_time")
canvas_id = self.canvas.create_line(x, y, x + 2, y + 2, self.previous_x, self.previous_y, tags='point', width=3, fill = 'red')
self.canvas.after(100, self.canvas.delete, canvas_id)
#self.canvas.create_line(x, y, x+1, y+1, self.previous_x, self.previous_y, tags='point', width=3)
self.previous_x = x
self.previous_y = y
if self.start_draw and index_finger['straight'] and not middle_finger['straight']:
x = index_finger['x']
y = index_finger['y']
x, y = self.scale_points(x, y)
if self.first_time == True:
self.previous_x = x
self.previous_y = y
self.first_time = False
#print("first_time")
self.canvas.create_line(x, y, x+1, y+1, self.previous_x, self.previous_y, tags='point', width=3)
self.previous_x = x
self.previous_y = y
if success:
self.photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(frame))
self.vid_canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)
self.window.after(self.delay, self.update)
def back_to_projects_view(self):
self.main_view_controller.show_frame(PROJECTS_VIEW_NAME)
self.vid.release()
self.destroy_widgets()
def clear_canvas(self):
self.canvas.delete('all')
def save(self):
self.canvas.postscript(file='image.eps')
img = PIL.Image.open('image.eps')
img.save('image.png', 'png')
os.remove('image.eps')
def destroy_widgets(self):
self.vid = None
self.top_frame.destroy()
self.canvas.destroy()
self.bottom_frame.destroy()
self.vid_canvas.destroy()
self.back_button.destroy()
def scale_points(self, x, y):
return x*self.canvas_width, y*self.canvas_height

View File

@ -0,0 +1,50 @@
import requests
import tkinter as tk
from constants import FONT, URL_PROJECTS, PROJECTS_ADD_VIEW_NAME, PROJECTS_VIEW_NAME
from views.abstract_view import AbstractView
class ProjectsAddView(tk.Frame, AbstractView):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
label0 = tk.Label(self, text='Project name:', font=FONT)
label0.pack()
input0 = tk.Entry(self)
input0.pack()
button_add = tk.Button(self, text="Confirm and add", font=FONT,
command=lambda: self.add_project(main_view_controller, input0.get()))
button_add.pack()
button_back = tk.Button(self, text="Back", font=FONT,
command=lambda: main_view_controller.show_frame(PROJECTS_VIEW_NAME))
button_back.pack()
@staticmethod
def get_view_name() -> str:
return PROJECTS_ADD_VIEW_NAME
def start(self):
print("ok")
def add_project(self, controller, project_name):
headers = {'Authorization': 'Bearer ' + self.token}
data = {
"name": str(project_name)
}
print(data)
response = requests.post(URL_PROJECTS, json=data, headers=headers)
print(response)
if response.status_code == 201:
response = response.json()
controller.show_frame(PROJECTS_VIEW_NAME)
else:
print("sth wrong")
bad_pass_label = tk.Label(self, text='Something went wrong!', font=FONT)
bad_pass_label.pack()
return ()

View File

@ -0,0 +1,44 @@
import requests
import tkinter as tk
from constants import FONT, FONT_LARGE, URL_PROJECTS, PROJECTS_VIEW_NAME, PROJECTS_ADD_VIEW_NAME, PROJECT_VIEW_NAME, \
MAIN_VIEW_NAME
from views.abstract_view import AbstractView
class ProjectsView(tk.Frame, AbstractView):
def __init__(self, parent, controller, main_view_controller):
tk.Frame.__init__(self, parent)
self.token = ''
self.projects_buttons = []
self.main_view_controller = main_view_controller
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
button_add = tk.Button(self, text="Add project", font=FONT,
command=lambda: self.main_view_controller.show_frame(PROJECTS_ADD_VIEW_NAME))
button_add.pack()
button_back = tk.Button(self, text="Back", font=FONT,
command=lambda: controller.show_frame(MAIN_VIEW_NAME, self.token))
button_back.pack()
label0 = tk.Label(self, text='Projects:', font=FONT)
label0.pack()
@staticmethod
def get_view_name() -> str:
return PROJECTS_VIEW_NAME
def start(self):
for button in self.projects_buttons:
button.destroy()
self.projects_buttons = []
headers = {'Authorization': 'Bearer ' + self.token}
resp = requests.get(URL_PROJECTS, headers=headers)
response = resp.json()
print(response)
for projects in response:
button_proj = tk.Button(self, text=projects['name'], font=FONT,
command=lambda: self.main_view_controller.show_frame(PROJECT_VIEW_NAME))
button_proj.pack()
self.projects_buttons.append(button_proj)

View File

@ -0,0 +1,79 @@
import requests
import tkinter as tk
from constants import FONT, FONT_LARGE, URL_REGISTER, REGISTER_VIEW_NAME, LOGIN_VIEW_NAME
from views.abstract_view import AbstractView
class RegisterView(tk.Frame, AbstractView):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Register", font=FONT)
label_u.pack(pady=10, padx=10)
label0 = tk.Label(self, text='Email:', font=FONT)
label0.pack()
input0 = tk.Entry(self)
input0.pack()
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.pack()
label3 = tk.Label(self, text='First name:', font=FONT)
label3.pack()
input3 = tk.Entry(self)
input3.pack()
label4 = tk.Label(self, text='Last name:', font=FONT)
label4.pack()
input4 = tk.Entry(self)
input4.pack()
button1 = tk.Button(self, text="Register", font=FONT,
command=lambda: self.register(controller, input0.get(), input1.get(), input2.get(),
input3.get(), input4.get()))
button1.pack()
button2 = tk.Button(self, text="Cancel", font=FONT, command=lambda: controller.show_frame(LOGIN_VIEW_NAME))
button2.pack()
@staticmethod
def get_view_name() -> str:
return REGISTER_VIEW_NAME
def register(self, controller, email, login, passw, name, lastname):
data = {
"email": str(email),
"password": str(passw),
"profile": {
"username": str(login),
"first_name": str(name),
"last_name": str(lastname)
}
}
print(data)
response = requests.post(URL_REGISTER, json=data)
print(response)
if response.status_code == 201:
response = response.json()
controller.show_frame(LOGIN_VIEW_NAME)
else:
print("sth wrong")
bad_pass_label = tk.Label(self, text='Something went wrong!', font=FONT)
bad_pass_label.pack()
return ()

Binary file not shown.