Toggle navigation
Toggle navigation
This project
Loading...
Sign in
2020-2-capstone-design2
/
2014104149
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Graduate
2020-11-18 18:13:02 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
b541e824b14d8151b9db4bc4b383665371673000
b541e824
1 parent
6c346c24
Haar cascade with margin
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
66 additions
and
45 deletions
client/client.cnf
client/client.py
register/register.cnf
register/register.py
server/server.cnf
server/server.py
client/client.cnf
View file @
b541e82
[server]
uri=ws://localhost:3000
[client]
image_size=160
margin=44
\ No newline at end of file
...
...
client/client.py
View file @
b541e82
##################################################
#1. webcam에서 얼굴을 인식합니다.
#2. 얼굴일
확률이 97% 이상이고
영역이 15000 이상인 이미지를 서버에 전송
#2. 얼굴일 영역이 15000 이상인 이미지를 서버에 전송
##################################################
import
tkinter
as
tk
import
tkinter.font
...
...
@@ -39,7 +39,9 @@ class Client(tk.Frame):
self
.
cap
.
set
(
4
,
self
.
cam_height
)
# Preprocessing
self
.
image_size
=
(
160
,
160
)
self
.
margin
=
int
(
config
[
'client'
][
'margin'
])
image_size
=
int
(
config
[
'client'
][
'image_size'
])
self
.
image_size
=
(
image_size
,
image_size
)
# cam에서 MTCNN 적용하는 영역
self
.
detecting_square
=
(
500
,
300
)
...
...
@@ -96,7 +98,8 @@ class Client(tk.Frame):
minSize
=
self
.
image_size
)
for
(
x
,
y
,
w
,
h
)
in
faces
:
image
=
frame
[
y
:
y
+
h
,
x
:
x
+
w
]
margin
=
int
(
self
.
margin
/
2
)
image
=
frame
[
y
-
margin
:
y
+
h
+
margin
,
x
-
margin
:
x
+
w
+
margin
]
return
image
,
True
return
[],
False
...
...
@@ -126,10 +129,13 @@ class Client(tk.Frame):
self
.
label
.
image
=
image
# kind of double buffering
@asyncio.coroutine
def
set_rectangle
(
self
):
def
set_rectangle
_success
(
self
):
self
.
rectangle_color
=
(
255
,
0
,
0
)
yield
from
asyncio
.
sleep
(
2
)
self
.
rectangle_color
=
(
0
,
0
,
255
)
def
set_rectangle_fail
(
self
):
self
.
rectangle_color
=
(
0
,
0
,
255
)
async
def
send_face
(
self
,
image
):
try
:
...
...
@@ -137,24 +143,30 @@ class Client(tk.Frame):
img
=
base64
.
b64encode
(
cv2
.
imencode
(
'.jpg'
,
image
)[
1
])
.
decode
()
send
=
json
.
dumps
({
'action'
:
'verify'
,
'image'
:
img
})
await
websocket
.
send
(
send
)
recv
=
await
websocket
.
recv
(
)
recv
=
await
asyncio
.
wait_for
(
websocket
.
recv
(),
timeout
=
1000
)
data
=
json
.
loads
(
recv
)
if
data
[
'action'
]
==
'success'
:
self
.
logging
(
'succeed'
)
if
data
[
'status'
]
==
'attend'
:
student_id
=
data
[
'student_id'
]
student_name
=
data
[
'student_name'
]
self
.
logging
(
student_id
+
' '
+
student_name
+
' is attend'
)
# change rectangle color
asyncio
.
ensure_future
(
self
.
set_rectangle
())
elif
data
[
'action'
]
==
'fail'
:
asyncio
.
ensure_future
(
self
.
set_rectangle_success
())
elif
data
[
'status'
]
==
'already'
:
# self.logging('already attend')
# change rectangle color
asyncio
.
ensure_future
(
self
.
set_rectangle_success
())
elif
data
[
'status'
]
==
'fail'
:
self
.
logging
(
'failed'
)
self
.
set_rectangle_fail
()
except
Exception
as
e
:
self
.
logging
(
e
)
def
stop
(
self
):
self
.
thread
.
do_run
=
False
self
.
thread
.
join
()
self
.
event_loop
.
close
()
#
self.thread.join()
#
self.event_loop.close()
self
.
cap
.
release
()
self
.
parent
.
destroy
()
if
__name__
==
'__main__'
:
root
=
tk
.
Tk
()
...
...
register/register.cnf
View file @
b541e82
[server]
uri=ws://localhost:3000
[register]
taking_time=0.2
image_size=160
margin=44
\ No newline at end of file
...
...
register/register.py
View file @
b541e82
...
...
@@ -26,7 +26,6 @@ class Register(tk.Frame):
# URI
self
.
uri
=
config
[
'server'
][
'uri'
]
# Cascade Model
self
.
cascade
=
cv2
.
CascadeClassifier
(
"haarcascade_frontalface_default.xml"
)
...
...
@@ -36,9 +35,12 @@ class Register(tk.Frame):
self
.
cam_height
=
480
self
.
cap
.
set
(
3
,
self
.
cam_width
)
self
.
cap
.
set
(
4
,
self
.
cam_height
)
self
.
image_size
=
(
160
,
160
)
image_size
=
int
(
config
[
'register'
][
'image_size'
])
self
.
image_size
=
(
image_size
,
image_size
)
self
.
margin
=
int
(
config
[
'register'
][
'margin'
])
# Application Function
self
.
taking_time
=
float
(
config
[
'register'
][
'taking_time'
])
self
.
detecting_square
=
(
400
,
400
)
self
.
detected
=
False
self
.
face
=
[]
...
...
@@ -120,7 +122,8 @@ class Register(tk.Frame):
minSize
=
self
.
image_size
)
for
(
x
,
y
,
w
,
h
)
in
faces
:
image
=
frame
[
y
:
y
+
h
,
x
:
x
+
w
]
margin
=
int
(
self
.
margin
/
2
)
image
=
frame
[
y
-
margin
:
y
+
h
+
margin
,
x
-
margin
:
x
+
w
+
margin
]
return
image
,
True
return
[],
False
...
...
@@ -157,12 +160,12 @@ class Register(tk.Frame):
# 얼굴이 인식되면 멤버함수에 넣음
if
detected
:
self
.
face
=
face
#
2
초 후에 사진이 찍힘
#
0.5
초 후에 사진이 찍힘
if
detected_time
is
None
:
detected_time
=
time
.
time
()
else
:
self
.
alert
.
config
(
text
=
"얼굴이 인식되었습니다.
%
f초 후 사진을 촬영합니다"
%
(
2
-
(
time
.
time
()
-
detected_time
)),
fg
=
"red"
)
if
time
.
time
()
-
detected_time
>=
2
:
self
.
alert
.
config
(
text
=
"얼굴이 인식되었습니다.
%
f초 후 사진을 촬영합니다"
%
(
self
.
taking_time
-
(
time
.
time
()
-
detected_time
)),
fg
=
"red"
)
if
time
.
time
()
-
detected_time
>=
self
.
taking_time
:
self
.
thread
.
do_run
=
False
self
.
detected
=
True
self
.
alert
.
config
(
text
=
"얼굴을 등록해주세요. 올바르게 촬영되지 않았을 경우 다시촬영을 눌러주세요."
,
fg
=
"blue"
)
...
...
@@ -180,9 +183,9 @@ class Register(tk.Frame):
async
with
websockets
.
connect
(
self
.
uri
)
as
websocket
:
img
=
base64
.
b64encode
(
cv2
.
imencode
(
'.jpg'
,
self
.
face
)[
1
])
.
decode
()
send
=
json
.
dumps
({
'action'
:
'register'
,
'student_id'
:
self
.
studentID
.
get
(),
'student_name'
:
self
.
studentName
.
get
(),
'
tensor
'
:
img
})
'student_id'
:
self
.
studentID
.
get
(),
'student_name'
:
self
.
studentName
.
get
(),
'
image
'
:
img
})
await
websocket
.
send
(
send
)
recv
=
await
websocket
.
recv
()
data
=
json
.
loads
(
recv
)
...
...
server/server.cnf
View file @
b541e82
[verification_server]
host=localhost
port=3000
model=model/20200816-080621
model=model
s
/20200816-080621
threshold=0.75
image_size=160
\ No newline at end of file
...
...
server/server.py
View file @
b541e82
...
...
@@ -11,7 +11,6 @@ import configparser
import
logging
from
datetime
import
datetime
lock
=
asyncio
.
Lock
()
clients
=
set
()
config
=
configparser
.
ConfigParser
()
...
...
@@ -27,23 +26,21 @@ image_size = int(config['verification_server']['image_size'])
threshold
=
float
(
config
[
'verification_server'
][
'threshold'
])
print
(
'connect to DB'
)
db
=
pymysql
.
connect
(
attendance_
db
=
pymysql
.
connect
(
read_default_file
=
"./DB.cnf"
)
async
def
register
(
websocket
):
async
with
lock
:
clients
.
add
(
websocket
)
#remote_ip = websocket.remote_address[0]
#msg='[{ip}] connected'.format(ip=remote_ip)
#print(msg)
clients
.
add
(
websocket
)
remote_ip
=
websocket
.
remote_address
[
0
]
msg
=
'[{ip}] connected'
.
format
(
ip
=
remote_ip
)
print
(
msg
)
async
def
unregister
(
websocket
):
async
with
lock
:
clients
.
remove
(
websocket
)
#remote_ip = websocket.remote_address[0]
#msg='[{ip}] disconnected'.format(ip=remote_ip)
#print(msg)
clients
.
remove
(
websocket
)
remote_ip
=
websocket
.
remote_address
[
0
]
msg
=
'[{ip}] disconnected'
.
format
(
ip
=
remote_ip
)
print
(
msg
)
def
resize
(
image
):
resized
=
cv2
.
resize
(
image
,
(
image_size
,
image_size
),
interpolation
=
cv2
.
INTER_CUBIC
)
...
...
@@ -63,22 +60,20 @@ def get_distance(arr1, arr2):
async
def
thread
(
websocket
,
path
):
await
register
(
websocket
)
cursor
=
db
.
cursor
(
pymysql
.
cursors
.
DictCursor
)
cursor
=
attendance_db
.
cursor
(
pymysql
.
cursors
.
DictCursor
)
remote_ip
=
websocket
.
remote_address
[
0
]
try
:
async
for
message
in
websocket
:
data
=
json
.
loads
(
message
)
remote_ip
=
websocket
.
remote_address
[
0
]
msg
=
'[{ip}] connected'
.
format
(
ip
=
remote_ip
)
print
(
msg
)
if
data
[
'action'
]
==
'register'
:
# log
msg
=
'[{ip}] register face'
.
format
(
ip
=
remote_ip
)
print
(
msg
)
student_id
=
data
[
'student_id'
]
student_name
=
data
[
'student_name'
]
# 학생을 찾음
sql
=
"SELECT student_id FROM student WHERE student_id =
%
s;"
rows_count
=
cursor
.
execute
(
sql
,
(
student_id
))
# DB에 학생이 없으면 등록
if
rows_count
==
0
:
sql
=
"INSERT INTO student(student_id, student_name) VALUES (
%
s,
%
s)"
...
...
@@ -132,7 +127,8 @@ async def thread(websocket, path):
for
row_data
in
result
:
db_embedding
=
np
.
frombuffer
(
row_data
[
'embedding'
],
dtype
=
np
.
float32
)
db_embedding
=
db_embedding
.
reshape
((
1
,
512
))
distance
=
await
get_distance
(
embedding
,
db_embedding
)
distance
=
get_distance
(
embedding
,
db_embedding
)
print
(
distance
)
if
(
distance
<
threshold
):
verified_id
=
row_data
[
'student_id'
]
break
...
...
@@ -143,19 +139,22 @@ async def thread(websocket, path):
# 인증 성공
# 오늘 이미 출석 됐는지 확인
sql
=
"SELECT DATE(timestamp) FROM student_attendance WHERE (lecture_id=
%
s) AND (student_id=
%
s) AND (DATE(timestamp) = CURDATE());"
rows_count
=
cursor
.
execute
(
sql
,
(
'0'
,
verified_id
))
cursor
.
execute
(
sql
,
(
'0'
,
verified_id
))
# 출석 기록이 없는 경우에만
if
rows_
count
==
0
:
if
cursor
.
row
count
==
0
:
# 테이블 맨 뒤에 datetime attribute가 있음. 서버 시간 가져오게 default로 설정해둠.
sql
=
"INSERT INTO student_attendance(lecture_id, student_id, status) VALUES (
%
s,
%
s,
%
s)"
# TODO: attend / late 처리
cursor
.
execute
(
sql
,
(
'0'
,
verified_id
,
'attend'
))
attendance_db
.
commit
()
sql
=
"SELECT student_name FROM student WHERE student_id =
%
s"
cursor
.
execute
(
sql
,
(
verified_id
))
row_data
=
cursor
.
fetchone
()
verified_name
=
row_data
[
'student_name'
]
# log 작성
msg
=
'[{ip}] verification success {id}'
.
format
(
ip
=
remote_ip
,
id
=
verified_id
)
print
(
msg
)
send
=
json
.
dumps
({
'status'
:
'
success'
,
'student_id'
:
verified_id
})
send
=
json
.
dumps
({
'status'
:
'
attend'
,
'student_id'
:
verified_id
,
'student_name'
:
verified_name
})
else
:
msg
=
'[{ip}] verification failed: {id} is already verified'
.
format
(
ip
=
remote_ip
,
id
=
verified_id
)
print
(
msg
)
...
...
Please
register
or
login
to post a comment