Graduate

Make register face client

1 -# 주제
2 -얼굴 인식 전자 출결 시스템
3 -
4 -# 팀원
5 -- 정해갑(컴퓨터공학과, 2014104149)
6 -- 허진호(컴퓨터공학과, 2014104161)
7 -
8 -# 개발환경
9 -- Windows, Linux, Google Colab, Spring, MySQL
10 -
11 -# 활용기술
12 -- pytorch(https://github.com/pytorch/pytorch)
13 -- facenet(https://github.com/davidsandberg/facenet)
14 -- facenet-pytorch(https://github.com/timesler/facenet-pytorch)
15 -- VGGFace2(http://www.robots.ox.ac.uk/~vgg/data/vgg_face2)
16 -- Spring Boot(https://spring.io/projects/spring-boot)
17 -- Spring Data JPA(https://spring.io/projects/spring-data-jpa)
18 -- MySQL(https://www.mysql.com)
19 -- PyMySQL(https://github.com/PyMySQL/PyMySQL)
...\ No newline at end of file ...\ No newline at end of file
File mode changed
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +import torch
2 +import numpy as np
3 +import time
4 +
5 +
6 +class Logger(object):
7 +
8 + def __init__(self, mode, length, calculate_mean=False):
9 + self.mode = mode
10 + self.length = length
11 + self.calculate_mean = calculate_mean
12 + if self.calculate_mean:
13 + self.fn = lambda x, i: x / (i + 1)
14 + else:
15 + self.fn = lambda x, i: x
16 +
17 + def __call__(self, loss, metrics, i):
18 + track_str = '\r{} | {:5d}/{:<5d}| '.format(self.mode, i + 1, self.length)
19 + loss_str = 'loss: {:9.4f} | '.format(self.fn(loss, i))
20 + metric_str = ' | '.join('{}: {:9.4f}'.format(k, self.fn(v, i)) for k, v in metrics.items())
21 + print(track_str + loss_str + metric_str + ' ', end='')
22 + if i + 1 == self.length:
23 + print('')
24 +
25 +
26 +class BatchTimer(object):
27 + """Batch timing class.
28 + Use this class for tracking training and testing time/rate per batch or per sample.
29 +
30 + Keyword Arguments:
31 + rate {bool} -- Whether to report a rate (batches or samples per second) or a time (seconds
32 + per batch or sample). (default: {True})
33 + per_sample {bool} -- Whether to report times or rates per sample or per batch.
34 + (default: {True})
35 + """
36 +
37 + def __init__(self, rate=True, per_sample=True):
38 + self.start = time.time()
39 + self.end = None
40 + self.rate = rate
41 + self.per_sample = per_sample
42 +
43 + def __call__(self, y_pred, y):
44 + self.end = time.time()
45 + elapsed = self.end - self.start
46 + self.start = self.end
47 + self.end = None
48 +
49 + if self.per_sample:
50 + elapsed /= len(y_pred)
51 + if self.rate:
52 + elapsed = 1 / elapsed
53 +
54 + return torch.tensor(elapsed)
55 +
56 +
57 +def accuracy(logits, y):
58 + _, preds = torch.max(logits, 1)
59 + return (preds == y).float().mean()
60 +
61 +
62 +def pass_epoch(
63 + model, loss_fn, loader, optimizer=None, scheduler=None,
64 + batch_metrics={'time': BatchTimer()}, show_running=True,
65 + device='cpu', writer=None
66 +):
67 + """Train or evaluate over a data epoch.
68 +
69 + Arguments:
70 + model {torch.nn.Module} -- Pytorch model.
71 + loss_fn {callable} -- A function to compute (scalar) loss.
72 + loader {torch.utils.data.DataLoader} -- A pytorch data loader.
73 +
74 + Keyword Arguments:
75 + optimizer {torch.optim.Optimizer} -- A pytorch optimizer.
76 + scheduler {torch.optim.lr_scheduler._LRScheduler} -- LR scheduler (default: {None})
77 + batch_metrics {dict} -- Dictionary of metric functions to call on each batch. The default
78 + is a simple timer. A progressive average of these metrics, along with the average
79 + loss, is printed every batch. (default: {{'time': iter_timer()}})
80 + show_running {bool} -- Whether or not to print losses and metrics for the current batch
81 + or rolling averages. (default: {False})
82 + device {str or torch.device} -- Device for pytorch to use. (default: {'cpu'})
83 + writer {torch.utils.tensorboard.SummaryWriter} -- Tensorboard SummaryWriter. (default: {None})
84 +
85 + Returns:
86 + tuple(torch.Tensor, dict) -- A tuple of the average loss and a dictionary of average
87 + metric values across the epoch.
88 + """
89 +
90 + mode = 'Train' if model.training else 'Valid'
91 + logger = Logger(mode, length=len(loader), calculate_mean=show_running)
92 + loss = 0
93 + metrics = {}
94 +
95 + for i_batch, (x, y) in enumerate(loader):
96 + x = x.to(device)
97 + y = y.to(device)
98 + y_pred = model(x)
99 + loss_batch = loss_fn(y_pred, y)
100 +
101 + if model.training:
102 + loss_batch.backward()
103 + optimizer.step()
104 + optimizer.zero_grad()
105 +
106 + metrics_batch = {}
107 + for metric_name, metric_fn in batch_metrics.items():
108 + metrics_batch[metric_name] = metric_fn(y_pred, y).detach().cpu()
109 + metrics[metric_name] = metrics.get(metric_name, 0) + metrics_batch[metric_name]
110 +
111 + if writer is not None and model.training:
112 + if writer.iteration % writer.interval == 0:
113 + writer.add_scalars('loss', {mode: loss_batch.detach().cpu()}, writer.iteration)
114 + for metric_name, metric_batch in metrics_batch.items():
115 + writer.add_scalars(metric_name, {mode: metric_batch}, writer.iteration)
116 + writer.iteration += 1
117 +
118 + loss_batch = loss_batch.detach().cpu()
119 + loss += loss_batch
120 + if show_running:
121 + logger(loss, metrics, i_batch)
122 + else:
123 + logger(loss_batch, metrics_batch, i_batch)
124 +
125 + if model.training and scheduler is not None:
126 + scheduler.step()
127 +
128 + loss = loss / (i_batch + 1)
129 + metrics = {k: v / (i_batch + 1) for k, v in metrics.items()}
130 +
131 + if writer is not None and not model.training:
132 + writer.add_scalars('loss', {mode: loss.detach()}, writer.iteration)
133 + for metric_name, metric in metrics.items():
134 + writer.add_scalars(metric_name, {mode: metric})
135 +
136 + return loss, metrics
137 +
138 +
139 +def collate_pil(x):
140 + out_x, out_y = [], []
141 + for xx, yy in x:
142 + out_x.append(xx)
143 + out_y.append(yy)
144 + return out_x, out_y
1 +##################################################
2 +#1. webcam에서 얼굴을 인식합니다. #
3 +#2. 얼굴일 확률이 95% 이상인 이미지를 이미지 서버로 전송합니다. #
4 +#3. 전처리 된 데이터를 verification 서버에 전송합니다. #
5 +##################################################
6 +import torch
7 +import numpy as np
8 +import cv2
9 +import asyncio
10 +import websockets
11 +import json
12 +import os
13 +import timeit
14 +import base64
15 +
16 +from PIL import Image
17 +from io import BytesIO
18 +import requests
19 +
20 +from models.mtcnn import MTCNN
21 +
22 +device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
23 +print('Running on device: {}'.format(device))
24 +
25 +mtcnn = MTCNN(keep_all=True, device=device)
26 +
27 +uri = 'ws://localhost:8765'
28 +
29 +async def send_face(face_list, image_list):
30 + global uri
31 + async with websockets.connect(uri) as websocket:
32 + for face, image in zip(face_list, image_list):
33 + #type: np.float32
34 + send = json.dumps({'action': 'register', 'student_id':'2014104149', 'student_name':'정해갑', 'MTCNN': face.tolist()})
35 + await websocket.send(send)
36 + recv = await websocket.recv()
37 + data = json.loads(recv)
38 + if data['status'] == 'success':
39 + # 성공
40 + print(data['student_id'], 'is registered')
41 +
42 +def detect_face(frame):
43 + # If required, create a face detection pipeline using MTCNN:
44 + global mtcnn
45 + results = mtcnn.detect(frame)
46 + image_list = []
47 + if results[1][0] == None:
48 + return []
49 + for box, prob in zip(results[0], results[1]):
50 + if prob < 0.95:
51 + continue
52 + print('face detected. prob:', prob)
53 + x1, y1, x2, y2 = box
54 + image = frame[int(y1-10):int(y2+10), int(x1-10):int(x2+10)]
55 + image_list.append(image)
56 + return image_list
57 +
58 +def make_face_list(frame):
59 + global mtcnn
60 + results, prob = mtcnn(frame, return_prob = True)
61 + face_list = []
62 + if prob[0] == None:
63 + return []
64 + for result, prob in zip(results, prob):
65 + if prob < 0.95:
66 + continue
67 + #np.float32
68 + face_list.append(result.numpy())
69 + return face_list
70 +
71 +cap = cv2.VideoCapture(0)
72 +cap.set(3, 720)
73 +cap.set(4, 480)
74 +ret, frame = cap.read()
75 +frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
76 +#img = Image.open('3.jpg')
77 +#frame = np.array(img)
78 +face_list = make_face_list(frame)
79 +image_list = detect_face(frame)
80 +if face_list:
81 + asyncio.get_event_loop().run_until_complete(send_face(face_list, image_list))
...\ No newline at end of file ...\ No newline at end of file