Graduate

Modify server.py

...@@ -8,7 +8,7 @@ import websockets ...@@ -8,7 +8,7 @@ import websockets
8 from io import BytesIO 8 from io import BytesIO
9 9
10 import pymysql 10 import pymysql
11 -import datetime 11 +from datetime import datetime
12 12
13 from PIL import Image, ImageDraw 13 from PIL import Image, ImageDraw
14 from IPython import display 14 from IPython import display
...@@ -23,7 +23,7 @@ model = InceptionResnetV1().eval().to(device) ...@@ -23,7 +23,7 @@ model = InceptionResnetV1().eval().to(device)
23 attendance_db = pymysql.connect( 23 attendance_db = pymysql.connect(
24 user='root', 24 user='root',
25 passwd='5978', 25 passwd='5978',
26 - host='localhost', 26 + host='127.0.0.1',
27 db='attendance', 27 db='attendance',
28 charset='utf8' 28 charset='utf8'
29 ) 29 )
...@@ -39,7 +39,7 @@ async def get_embeddings(face_list): ...@@ -39,7 +39,7 @@ async def get_embeddings(face_list):
39 return yhat 39 return yhat
40 40
41 async def get_distance(arr1, arr2): 41 async def get_distance(arr1, arr2):
42 - distance = (arr1 - arr2).norm().item() 42 + distance = np.linalg.norm(arr1 - arr2)
43 return distance 43 return distance
44 44
45 def get_argmin(someone, database): 45 def get_argmin(someone, database):
...@@ -67,10 +67,8 @@ async def unregister(websocket): ...@@ -67,10 +67,8 @@ async def unregister(websocket):
67 print(msg) 67 print(msg)
68 68
69 async def thread(websocket, path): 69 async def thread(websocket, path):
70 - # register(websocket) sends user_event() to websocket
71 await register(websocket) 70 await register(websocket)
72 try: 71 try:
73 - # await websocket.send(state_event())
74 async for message in websocket: 72 async for message in websocket:
75 data = json.loads(message) 73 data = json.loads(message)
76 remote_ip = websocket.remote_address[0] 74 remote_ip = websocket.remote_address[0]
...@@ -89,79 +87,92 @@ async def thread(websocket, path): ...@@ -89,79 +87,92 @@ async def thread(websocket, path):
89 cursor = attendance_db.cursor(pymysql.cursors.DictCursor) 87 cursor = attendance_db.cursor(pymysql.cursors.DictCursor)
90 88
91 # 학생을 찾음 89 # 학생을 찾음
92 - sql = "SELECT student_id FROM student WHERE student_id = %s;" 90 + sql = "SELECT student_id FROM student WHERE student_id = %s;"
93 cursor.execute(sql, (student_id)) 91 cursor.execute(sql, (student_id))
94 92
95 # DB에 학생이 없으면 등록 93 # DB에 학생이 없으면 등록
96 if not cursor.fetchone(): 94 if not cursor.fetchone():
97 - sql = "insert into student(student_id, student_name) values (%s, %s)" 95 + sql = "INSERT INTO student(student_id, student_name) VALUES (%s, %s)"
98 cursor.execute(sql, (student_id, student_name)) 96 cursor.execute(sql, (student_id, student_name))
99 attendance_db.commit() 97 attendance_db.commit()
98 + msg='[{ip}] {id} is registered'.format(ip=remote_ip, id=student_id)
99 + print(msg)
100 100
101 # student_embedding Table에 등록 101 # student_embedding Table에 등록
102 embedding = await get_embeddings(face) 102 embedding = await get_embeddings(face)
103 embedding = embedding.detach().numpy().tobytes() 103 embedding = embedding.detach().numpy().tobytes()
104 - embedding_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 104 + embedding_date = datetime.now().strftime('%Y-%m-%d')
105 - sql = "insert into student_embedding(student_id, embedding_date, embedding) values (%s, %s, %s)" 105 + sql = "insert into student_embedding(student_id, embedding_date, embedding) values (%s, %s, _binary %s)"
106 cursor.execute(sql, (student_id, embedding_date, embedding)) 106 cursor.execute(sql, (student_id, embedding_date, embedding))
107 attendance_db.commit() 107 attendance_db.commit()
108 - await websocket.send('{id} registered'.format(id=student_id)) 108 + send = json.dumps({'status': 'success', 'student_id': student_id})
109 - elif data['action'] == "verify": 109 + await websocket.send(send)
110 +
111 + elif data['action'] == 'verify':
110 # log 112 # log
111 msg='[{ip}] verify face'.format(ip=remote_ip) 113 msg='[{ip}] verify face'.format(ip=remote_ip)
112 print(msg) 114 print(msg)
113 - ###############
114 115
115 # load json 116 # load json
116 face = np.asarray(data['MTCNN'], dtype = np.float32) 117 face = np.asarray(data['MTCNN'], dtype = np.float32)
117 face = face.reshape((1,3,160,160)) 118 face = face.reshape((1,3,160,160))
118 119
119 - # embedding 구하기
120 embedding = await get_embeddings(face) 120 embedding = await get_embeddings(face)
121 embedding = embedding.detach().numpy() 121 embedding = embedding.detach().numpy()
122 - # embedding.numpy()
123 - # [1, 512] numpy()임
124 - # np.frombuffer()로 불러오는 것이 좋을 듯.
125 - # DB에 연결
126 - cursor = attendance_db.cursor(pymysql.cursors.DictCursor)
127 122
128 - # 학생을 찾음 123 + # 가장 비슷한 Embedding을 찾는 SQL
124 + cursor = attendance_db.cursor(pymysql.cursors.DictCursor)
129 sql = "SELECT student_id, embedding FROM student_embedding;" 125 sql = "SELECT student_id, embedding FROM student_embedding;"
130 cursor.execute(sql) 126 cursor.execute(sql)
131 result = cursor.fetchall() 127 result = cursor.fetchall()
132 - verified_id = '0000000000' 128 + verified_id = '0'
133 - distance_min = 1 129 + distance_min = 1.0
134 for row_data in result: 130 for row_data in result:
135 db_embedding = np.frombuffer(row_data['embedding'], dtype=np.float32) 131 db_embedding = np.frombuffer(row_data['embedding'], dtype=np.float32)
136 db_embedding = db_embedding.reshape((1,512)) 132 db_embedding = db_embedding.reshape((1,512))
137 - distance = get_distance(embedding, db_embedding) 133 + distance = await get_distance(embedding, db_embedding)
138 if (distance < distance_min): 134 if (distance < distance_min):
139 verified_id = row_data['student_id'] 135 verified_id = row_data['student_id']
140 distance_min = distance 136 distance_min = distance
141 137
142 # 출석 데이터 전송 138 # 출석 데이터 전송
143 - data = '' 139 + send = ''
140 + print('[debug] distance:', distance_min)
144 if distance_min >= 0.6: 141 if distance_min >= 0.6:
145 # 해당하는 사람 DB에 없음 142 # 해당하는 사람 DB에 없음
146 - print('verification failed: not in DB') 143 + msg='[{ip}] verification failed'.format(ip=remote_ip)
147 - data = json.dumps({'state': 'fail'}) 144 + print(msg)
145 + send = json.dumps({'status': 'fail'})
148 else: 146 else:
149 # 해당하는 사람 DB에 있음 147 # 해당하는 사람 DB에 있음
150 - print('verification success:', verified_id) 148 + # logging
151 - data = json.dumps({'state': 'success', 'id': verified_id}) 149 + msg='[{ip}] verification success {id}'.format(ip=remote_ip, id=verified_id)
152 - await websocket.send(data) 150 + print(msg)
151 +
152 + # TODO: lecture DB에 tuple 삽입해야 아래 코드가 돌아감
153 + # 해당하는 사람이 DB에 있으면 출석 처리
154 + #date = datetime.now().strftime('%Y-%m-%d')
155 + #sql = "INSERT INTO student_attendance(lecture_id, student_id, date) VALUES (%s, %s, %s)"
156 + #cursor.execute(sql, ('0', verified_id, date))
157 +
158 + # client에 전달
159 + send = json.dumps({'status': 'success', 'student_id': verified_id})
160 + await websocket.send(send)
153 elif data['action'] == "save_image": 161 elif data['action'] == "save_image":
154 # 출석이 제대로 이뤄지지 않으면 이미지를 저장하여 162 # 출석이 제대로 이뤄지지 않으면 이미지를 저장하여
155 # 나중에 교강사가 출석을 확인할 수 있도록 한다 163 # 나중에 교강사가 출석을 확인할 수 있도록 한다
156 - arr = np.asarray(data['image'], dtype = np.uint8)
157 - # 이 데이터는 데이터베이스(과목명/일자/undefined)에 저장하는 것이 좋을듯
158 - # image = Image.fromarray(arr)
159 - # image.save('face.jpg')# storage에 데이터 저장
160 - remote_ip = websocket.remote_address[0]
161 msg='[{ip}] save image'.format(ip=remote_ip) 164 msg='[{ip}] save image'.format(ip=remote_ip)
162 print(msg) 165 print(msg)
163 - ### 166 +
164 - await websocket.send('정해갑') 167 + arr = np.asarray(data['image'], dtype = np.uint8)
168 + blob = arr.tobytes()
169 + date = datetime.now().strftime('%Y-%m-%d')
170 +
171 + # TODO: lecture DB에 tuple 삽입해야 아래 코드가 돌아감
172 + #cursor = attendance_db.cursor(pymysql.cursors.DictCursor)
173 + #sql = "INSERT INTO undefined_image(lecture_id, date, image, width, height) VALUES (%s, %s, _binary %s, %s, %s)"
174 + #cursor.execute(sql, ('0', date, blob, arr.shape[0], arr.shape[1]))
175 + #attendance_db.commit()
165 else: 176 else:
166 print("unsupported event: {}", data) 177 print("unsupported event: {}", data)
167 finally: 178 finally:
......