Graduate

Modify register.py

1 +##################################################
2 +#1. webcam에서 얼굴을 인식합니다.
3 +#2. 얼굴일 확률이 97% 이상이고 영역이 15000 이상인 이미지를 서버에 전송
4 +##################################################
5 +import tkinter as tk
6 +import tkinter.font
7 +import tkinter.messagebox
8 +import threading
9 +import torch
10 +import numpy as np
11 +import cv2
12 +import asyncio
13 +import websockets
14 +import json
15 +import os
16 +import timeit
17 +import base64
18 +import time
19 +
20 +from PIL import Image, ImageTk
21 +from io import BytesIO
22 +import requests
23 +
24 +from models.mtcnn import MTCNN
25 +
26 +device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
27 +print('Running on device: {}'.format(device))
28 +
29 +mtcnn = MTCNN(keep_all=True, post_process=True, device=device)
30 +
31 +uri = 'ws://169.56.95.131:8765'
32 +
33 +class Register(tk.Frame):
34 + def __init__(self, parent, *args, **kwargs):
35 + tk.Frame.__init__(self, parent, *args, **kwargs)
36 +
37 + # URI
38 + self.uri = 'ws://169.56.95.131:8765'
39 +
40 + # Pytorch Model
41 + self.device = device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
42 + self.mtcnn = MTCNN(keep_all=True, device=device)
43 +
44 + # OpenCV
45 + self.cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
46 + self.cam_width = 640
47 + self.cam_height = 480
48 + self.cap.set(3, self.cam_width)
49 + self.cap.set(4, self.cam_height)
50 +
51 + # tkinter GUI
52 + self.width = 740
53 + self.height = 640
54 + self.parent = parent
55 + self.parent.geometry("%dx%d+100+100" % (self.width, self.height))
56 + self.pack()
57 + self.create_widgets()
58 +
59 + # Event loop and Thread
60 + self.event_loop = asyncio.new_event_loop()
61 + self.thread = threading.Thread(target=self.mainthread)
62 + self.thread.start()
63 +
64 + def create_widgets(self):
65 + image = np.zeros([self.cam_height, self.cam_width, 3], dtype=np.uint8)
66 + image = Image.fromarray(image)
67 + image = ImageTk.PhotoImage(image)
68 +
69 + font = tk.font.Font(family="맑은 고딕", size=15)
70 +
71 + self.alert = tk.Label(self, text="출석시스템", font=font)
72 + self.alert.grid(row=0, column=0, columnspan=20)
73 + self.label = tk.Label(self, image=image)
74 + self.label.grid(row=1, column=0, columnspan=20)
75 +
76 + self.log = tk.Text(self)
77 + self.log.grid(row=2, column=0, columnspan=20)
78 +
79 +
80 + self.quit = tk.Button(self, text="나가기", fg="red", command=self.stop)
81 + self.quit.grid(row=5, column=10)
82 +
83 +
84 + def detect_face(self, frame):
85 + results = self.mtcnn.detect(frame)
86 + faces = self.mtcnn(frame, return_prob = False)
87 + image_list = []
88 + face_list = []
89 + if results[1][0] == None:
90 + return [], []
91 + for box, face, prob in zip(results[0], faces, results[1]):
92 + if prob < 0.97:
93 + continue
94 + # for debug
95 + # print('face detected. prob:', prob)
96 + x1, y1, x2, y2 = box
97 + if (x2-x1) * (y2-y1) < 15000:
98 + # 얼굴 해상도가 너무 낮으면 무시
99 + self.alert.config(text= "카메라에 더 가까이 접근해주세요.", fg="red")
100 + self.alert.update()
101 + continue
102 + image = frame
103 + image_list.append(image)
104 + # MTCNN 데이터 저장
105 + face_list.append(face.numpy())
106 + return face_list, image_list
107 +
108 + def mainthread(self):
109 + t = threading.currentThread()
110 + asyncio.set_event_loop(self.event_loop)
111 + while getattr(t, "do_run", True):
112 + ret, frame = self.cap.read()
113 +
114 + # model에 이용하기 위해 convert
115 + converted = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
116 + face_list, image_list = self.detect_face(converted)
117 +
118 + # show image
119 + image = Image.fromarray(converted)
120 + image = ImageTk.PhotoImage(image)
121 + self.label.configure(image=image)
122 + self.label.image = image # kind of double buffering
123 +
124 + # 얼굴이 인식되면 요청
125 + if face_list:
126 + self.event_loop.run_until_complete(self.send_face(face_list, image_list))
127 +
128 +
129 + async def wait(self, n):
130 + await asyncio.sleep(n)
131 +
132 + async def send_face(self, face_list, image_list):
133 + try:
134 + async with websockets.connect(uri) as websocket:
135 + for face, image in zip(face_list, image_list):
136 + #type: np.float32
137 + send = json.dumps({'action': 'verify', 'MTCNN': face.tolist()})
138 + await websocket.send(send)
139 + recv = await websocket.recv()
140 + data = json.loads(recv)
141 + if data['status'] == 'success':
142 + # 성공
143 + self.log.insert(tkinter.CURRENT, data['student_id'] + 'is attend')
144 + self.log.insert(tkinter.CURRENT, '\n')
145 + else:
146 + self.log.insert(tkinter.CURRENT, 'verification failed:' + data['status'])
147 + if data['status'] == 'failed':
148 + send = json.dumps({'action': 'save_image', 'image': image.tolist()})
149 + except Exception as e:
150 + self.log.insert(tkinter.CURRENT, e)
151 + self.log.insert(tkinter.CURRENT, '\n')
152 +
153 + def stop(self):
154 + self.thread.do_run = False
155 + # self.thread.join() # there is a freeze problem
156 + self.event_loop.close()
157 + self.cap.release()
158 + self.parent.destroy()
159 +
160 +
161 +if __name__ == '__main__':
162 + root = tk.Tk()
163 + Register(root)
164 + root.mainloop()
165 +
...@@ -27,15 +27,6 @@ class Register(tk.Frame): ...@@ -27,15 +27,6 @@ class Register(tk.Frame):
27 def __init__(self, parent, *args, **kwargs): 27 def __init__(self, parent, *args, **kwargs):
28 tk.Frame.__init__(self, parent, *args, **kwargs) 28 tk.Frame.__init__(self, parent, *args, **kwargs)
29 29
30 - # tkinter GUI
31 - self.width = 740
32 - self.height = 640
33 -
34 - self.parent = parent
35 - self.parent.geometry("%dx%d+100+100" % (self.width, self.height))
36 - self.pack()
37 - self.create_widgets()
38 -
39 # URI 30 # URI
40 self.uri = 'ws://169.56.95.131:8765' 31 self.uri = 'ws://169.56.95.131:8765'
41 32
...@@ -56,6 +47,14 @@ class Register(tk.Frame): ...@@ -56,6 +47,14 @@ class Register(tk.Frame):
56 self.face_list = [] 47 self.face_list = []
57 self.image_list = [] 48 self.image_list = []
58 49
50 + # tkinter GUI
51 + self.width = 740
52 + self.height = 640
53 + self.parent = parent
54 + self.parent.geometry("%dx%d+100+100" % (self.width, self.height))
55 + self.pack()
56 + self.create_widgets()
57 +
59 # Event loop and Thread 58 # Event loop and Thread
60 # self.event_loop = asyncio.new_event_loop() 59 # self.event_loop = asyncio.new_event_loop()
61 self.thread = threading.Thread(target=self.mainthread) 60 self.thread = threading.Thread(target=self.mainthread)
...@@ -63,7 +62,7 @@ class Register(tk.Frame): ...@@ -63,7 +62,7 @@ class Register(tk.Frame):
63 62
64 63
65 def create_widgets(self): 64 def create_widgets(self):
66 - image = np.zeros([480,640,3], dtype=np.uint8) 65 + image = np.zeros([self.cam_height,self.cam_width,3], dtype=np.uint8)
67 image = Image.fromarray(image) 66 image = Image.fromarray(image)
68 image = ImageTk.PhotoImage(image) 67 image = ImageTk.PhotoImage(image)
69 68
......