Showing
3 changed files
with
52 additions
and
26 deletions
... | @@ -5,6 +5,7 @@ | ... | @@ -5,6 +5,7 @@ |
5 | import tkinter as tk | 5 | import tkinter as tk |
6 | import tkinter.font | 6 | import tkinter.font |
7 | import tkinter.messagebox | 7 | import tkinter.messagebox |
8 | +import tkinter.scrolledtext | ||
8 | import threading | 9 | import threading |
9 | import torch | 10 | import torch |
10 | import numpy as np | 11 | import numpy as np |
... | @@ -48,9 +49,17 @@ class Client(tk.Frame): | ... | @@ -48,9 +49,17 @@ class Client(tk.Frame): |
48 | self.cap.set(3, self.cam_width) | 49 | self.cap.set(3, self.cam_width) |
49 | self.cap.set(4, self.cam_height) | 50 | self.cap.set(4, self.cam_height) |
50 | 51 | ||
52 | + # Application Function | ||
53 | + | ||
54 | + # cam에서 MTCNN 적용하는 영역 | ||
55 | + self.detecting_square = (200, 200) | ||
56 | + | ||
57 | + # 영상 위에 사각형 색상 지정 | ||
58 | + self.rectangle_color = (0, 0, 255) | ||
59 | + | ||
51 | # tkinter GUI | 60 | # tkinter GUI |
52 | self.width = 740 | 61 | self.width = 740 |
53 | - self.height = 640 | 62 | + self.height = 700 |
54 | self.parent = parent | 63 | self.parent = parent |
55 | self.parent.title("출석시스템") | 64 | self.parent.title("출석시스템") |
56 | self.parent.geometry("%dx%d+100+100" % (self.width, self.height)) | 65 | self.parent.geometry("%dx%d+100+100" % (self.width, self.height)) |
... | @@ -74,13 +83,19 @@ class Client(tk.Frame): | ... | @@ -74,13 +83,19 @@ class Client(tk.Frame): |
74 | self.label = tk.Label(self, image=image) | 83 | self.label = tk.Label(self, image=image) |
75 | self.label.grid(row=1, column=0, columnspan=20) | 84 | self.label.grid(row=1, column=0, columnspan=20) |
76 | 85 | ||
77 | - self.log = tk.Text(self) | 86 | + self.log = tk.scrolledtext.ScrolledText(self, wrap = tk.WORD, state=tk.DISABLED, width = 96, height = 10) |
78 | self.log.grid(row=2, column=0, columnspan=20) | 87 | self.log.grid(row=2, column=0, columnspan=20) |
79 | 88 | ||
80 | 89 | ||
81 | self.quit = tk.Button(self, text="나가기", fg="red", command=self.stop) | 90 | self.quit = tk.Button(self, text="나가기", fg="red", command=self.stop) |
82 | - self.quit.grid(row=5, column=10) | 91 | + self.quit.grid(row=3, column=10) |
83 | 92 | ||
93 | + def logging(self, text): | ||
94 | + self.log.config(state=tk.NORMAL) | ||
95 | + self.log.insert(tkinter.CURRENT, text) | ||
96 | + self.log.insert(tkinter.CURRENT, '\n') | ||
97 | + self.log.config(state=tk.DISABLED) | ||
98 | + | ||
84 | 99 | ||
85 | def detect_face(self, frame): | 100 | def detect_face(self, frame): |
86 | results = self.mtcnn.detect(frame) | 101 | results = self.mtcnn.detect(frame) |
... | @@ -97,8 +112,6 @@ class Client(tk.Frame): | ... | @@ -97,8 +112,6 @@ class Client(tk.Frame): |
97 | x1, y1, x2, y2 = box | 112 | x1, y1, x2, y2 = box |
98 | if (x2-x1) * (y2-y1) < 15000: | 113 | if (x2-x1) * (y2-y1) < 15000: |
99 | # 얼굴 해상도가 너무 낮으면 무시 | 114 | # 얼굴 해상도가 너무 낮으면 무시 |
100 | - self.alert.config(text= "카메라에 더 가까이 접근해주세요.", fg="red") | ||
101 | - self.alert.update() | ||
102 | continue | 115 | continue |
103 | image = frame | 116 | image = frame |
104 | image_list.append(image) | 117 | image_list.append(image) |
... | @@ -109,24 +122,35 @@ class Client(tk.Frame): | ... | @@ -109,24 +122,35 @@ class Client(tk.Frame): |
109 | def mainthread(self): | 122 | def mainthread(self): |
110 | t = threading.currentThread() | 123 | t = threading.currentThread() |
111 | asyncio.set_event_loop(self.event_loop) | 124 | asyncio.set_event_loop(self.event_loop) |
125 | + x1 = int(self.cam_width / 2 - self.detecting_square[0] / 2) | ||
126 | + x2 = int(self.cam_width / 2 + self.detecting_square[0] / 2) | ||
127 | + y1 = int(self.cam_height / 2 - self.detecting_square[1] / 2) | ||
128 | + y2 = int(self.cam_height / 2 + self.detecting_square[1] / 2) | ||
112 | while getattr(t, "do_run", True): | 129 | while getattr(t, "do_run", True): |
113 | ret, frame = self.cap.read() | 130 | ret, frame = self.cap.read() |
114 | - | ||
115 | # model에 이용하기 위해 convert | 131 | # model에 이용하기 위해 convert |
116 | converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | 132 | converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
117 | - face_list, image_list = self.detect_face(converted) | 133 | + face_list, image_list = self.detect_face(converted[y1:y2, x1:x2]) |
118 | - | 134 | + |
135 | + # 얼굴이 인식되면 출석요청 | ||
136 | + self.event_loop.run_until_complete(self.send_face(face_list, image_list)) | ||
137 | + | ||
119 | # show image | 138 | # show image |
139 | + frame = cv2.rectangle(frame, (x1, y1), (x2, y2), self.rectangle_color, 3) | ||
140 | + converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | ||
141 | + # 거울상으로 보여준다 | ||
142 | + converted = cv2.flip(converted,1) | ||
120 | image = Image.fromarray(converted) | 143 | image = Image.fromarray(converted) |
121 | image = ImageTk.PhotoImage(image) | 144 | image = ImageTk.PhotoImage(image) |
122 | self.label.configure(image=image) | 145 | self.label.configure(image=image) |
123 | self.label.image = image # kind of double buffering | 146 | self.label.image = image # kind of double buffering |
124 | 147 | ||
125 | - # 얼굴이 인식되면 요청 | 148 | + @asyncio.coroutine |
126 | - if face_list: | 149 | + def set_rectangle(self): |
127 | - self.event_loop.run_until_complete(self.send_face(face_list, image_list)) | 150 | + self.rectangle_color = (255, 0, 0) |
128 | - | 151 | + yield from asyncio.sleep(1) |
129 | - | 152 | + self.rectangle_color = (0, 0, 255) |
153 | + | ||
130 | async def wait(self, n): | 154 | async def wait(self, n): |
131 | await asyncio.sleep(n) | 155 | await asyncio.sleep(n) |
132 | 156 | ||
... | @@ -141,16 +165,16 @@ class Client(tk.Frame): | ... | @@ -141,16 +165,16 @@ class Client(tk.Frame): |
141 | data = json.loads(recv) | 165 | data = json.loads(recv) |
142 | if data['status'] == 'success': | 166 | if data['status'] == 'success': |
143 | # 성공 | 167 | # 성공 |
144 | - self.log.insert(tkinter.CURRENT, data['student_id'] + 'is attend') | 168 | + self.logging('출석확인: ' + data['student_id']) |
145 | - self.log.insert(tkinter.CURRENT, '\n') | 169 | + asyncio.ensure_future(self.set_rectangle()) |
146 | else: | 170 | else: |
147 | - self.log.insert(tkinter.CURRENT, 'verification failed:' + data['status']) | ||
148 | - self.log.insert(tkinter.CURRENT, '\n') | ||
149 | if data['status'] == 'failed': | 171 | if data['status'] == 'failed': |
150 | send = json.dumps({'action': 'save_image', 'image': image.tolist()}) | 172 | send = json.dumps({'action': 'save_image', 'image': image.tolist()}) |
173 | + await websocket.send(send) | ||
174 | + elif data['status'] == 'already': | ||
175 | + asyncio.ensure_future(self.set_rectangle()) | ||
151 | except Exception as e: | 176 | except Exception as e: |
152 | - self.log.insert(tkinter.CURRENT, e) | 177 | + self.logging(e) |
153 | - self.log.insert(tkinter.CURRENT, '\n') | ||
154 | 178 | ||
155 | def stop(self): | 179 | def stop(self): |
156 | self.thread.do_run = False | 180 | self.thread.do_run = False |
... | @@ -164,4 +188,4 @@ if __name__ == '__main__': | ... | @@ -164,4 +188,4 @@ if __name__ == '__main__': |
164 | root = tk.Tk() | 188 | root = tk.Tk() |
165 | Client(root) | 189 | Client(root) |
166 | root.mainloop() | 190 | root.mainloop() |
167 | - | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
191 | + | ... | ... |
... | @@ -164,6 +164,8 @@ class Register(tk.Frame): | ... | @@ -164,6 +164,8 @@ class Register(tk.Frame): |
164 | 164 | ||
165 | # show image | 165 | # show image |
166 | converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | 166 | converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |
167 | + # 유저에게 보여줄 땐 거울상으로 보여준다 | ||
168 | + converted = cv2.flip(converted,1) | ||
167 | image = Image.fromarray(converted) | 169 | image = Image.fromarray(converted) |
168 | image = ImageTk.PhotoImage(image) | 170 | image = ImageTk.PhotoImage(image) |
169 | self.label.configure(image=image) | 171 | self.label.configure(image=image) | ... | ... |
... | @@ -51,18 +51,18 @@ async def register(websocket): | ... | @@ -51,18 +51,18 @@ async def register(websocket): |
51 | global clients | 51 | global clients |
52 | async with lock: | 52 | async with lock: |
53 | clients.add(websocket) | 53 | clients.add(websocket) |
54 | - remote_ip = websocket.remote_address[0] | 54 | + #remote_ip = websocket.remote_address[0] |
55 | - msg='[{ip}] connected'.format(ip=remote_ip) | 55 | + #msg='[{ip}] connected'.format(ip=remote_ip) |
56 | - print(msg) | 56 | + #print(msg) |
57 | 57 | ||
58 | async def unregister(websocket): | 58 | async def unregister(websocket): |
59 | global lock | 59 | global lock |
60 | global clients | 60 | global clients |
61 | async with lock: | 61 | async with lock: |
62 | clients.remove(websocket) | 62 | clients.remove(websocket) |
63 | - remote_ip = websocket.remote_address[0] | 63 | + #remote_ip = websocket.remote_address[0] |
64 | - msg='[{ip}] disconnected'.format(ip=remote_ip) | 64 | + #msg='[{ip}] disconnected'.format(ip=remote_ip) |
65 | - print(msg) | 65 | + #print(msg) |
66 | 66 | ||
67 | async def thread(websocket, path): | 67 | async def thread(websocket, path): |
68 | await register(websocket) | 68 | await register(websocket) | ... | ... |
-
Please register or login to post a comment