-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathyoona_target.py
More file actions
182 lines (145 loc) · 6.47 KB
/
yoona_target.py
File metadata and controls
182 lines (145 loc) · 6.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import cv2
import numpy as np
import os
import base64
from io import BytesIO
from insightface.app import FaceAnalysis
from PIL import Image
def arcface_recognition(video_path):
app = FaceAnalysis(providers=['CPUExecutionProvider']) # CPU 사용
app.prepare(ctx_id=0, det_size=(640, 640))
video_capture = cv2.VideoCapture(video_path)
identified_faces = []
while video_capture.isOpened():
success, frame = video_capture.read()
if not success:
break
faces = app.get(frame)
for face in faces:
# 얼굴 이미지 추출
box = face.bbox.astype(int)
face_image = frame[box[1]:box[3], box[0]:box[2]]
if face_image.size == 0: # 얼굴 이미지가 빈 경우 건너뛰기
continue
embedding = face.normed_embedding
identified_faces.append((face_image, embedding))
video_capture.release()
return identified_faces
def group_and_save_faces(identified_faces, save_dir='saved_faces', threshold=0.6):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
face_groups = []
for face_image, encoding in identified_faces:
if not face_groups:
face_groups.append([(face_image, encoding)])
else:
matched = False
for face_group in face_groups:
group_encodings = [enc for _, enc in face_group]
avg_encoding = np.mean(group_encodings, axis=0)
# cosine similarity
sim = np.dot(avg_encoding, encoding) / (np.linalg.norm(avg_encoding) * np.linalg.norm(encoding))
if sim > threshold:
face_group.append((face_image, encoding))
matched = True
break
if not matched:
face_groups.append([(face_image, encoding)])
# 얼굴순서 - 내림차순
face_groups.sort(key=lambda x: len(x), reverse=True)
return save_faces(face_groups)
def save_faces(face_groups):
face_base64_arrays = []
for face_group in face_groups:
encoded_faces = []
count = 0 # 각 그룹별로 이미지 개수를 세는 카운터
for face_image, _ in face_group:
# OpenCV는 BGR 형식으로 이미지를 읽기 때문에 RGB로 변환
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
# 이미지를 PIL 이미지 객체로 변환
pil_img = Image.fromarray(face_image)
# 메모리 내에서 이미지를 저장하기 위한 버퍼 생성
buf = BytesIO()
# 이미지를 JPEG 포맷으로 저장
pil_img.save(buf, format="JPEG")
# 버퍼의 바이트 데이터를 Base64 인코딩 문자열로 변환
base64_string = base64.b64encode(buf.getvalue()).decode('utf-8')
# 해당 인물의 인코딩된 이미지를 추가
encoded_faces.append(base64_string)
count += 1
if count == 3: # 각 인물 그룹에서 최대 3개의 이미지만 저장
break
# 모든 인물의 인코딩된 이미지를 배열에 추가
face_base64_arrays.append(encoded_faces)
return face_base64_arrays
# 원본
"""
import base64
from io import BytesIO
import cv2
import face_recognition
import numpy as np
from PIL import Image
def yoona_test(video_path):
face_encodings = [] # 얼굴별 인코딩 저장
face_images = [] # 얼굴별 이미지 저장
identified_faces = [] # 식별된 얼굴별 (객체) 저장
video_capture = cv2.VideoCapture(video_path)
while video_capture.isOpened():
success, frame = video_capture.read()
if not success:
break
face_locations = face_recognition.face_locations(frame) # 현재 프레임에서 얼굴 위치 탐지
current_encodings = face_recognition.face_encodings(frame, face_locations) # 얼굴 위치에 대한 인코딩
for (top, right, bottom, left), encoding in zip(face_locations, current_encodings):
# 얼굴 이미지 추출
face_image = frame[top:bottom, left:right]
face_images.append(face_image)
face_encodings.append(encoding)
# 인식된 얼굴 분류
for idx, encoding in enumerate(face_encodings):
if not identified_faces:
identified_faces.append([(face_images[idx], encoding)])
else:
matched = False
for face_group in identified_faces:
group_encodings = [enc for _, enc in face_group]
avg_encoding = np.mean(group_encodings, axis=0)
dist = np.linalg.norm(avg_encoding - encoding)
if dist < 0.555: # 같은 사람으로 판단하는 임계값
face_group.append((face_images[idx], encoding))
matched = True
break
if not matched:
identified_faces.append([(face_images[idx], encoding)])
# 얼굴 수가 많은 순서로 그룹 정렬
identified_faces.sort(key=lambda x: len(x), reverse=True)
video_capture.release()
print('end1')
# 인식된 얼굴 이미지를 Base64로 인코딩하여 반환
return save_faces(identified_faces)
def save_faces(identified_faces):
face_base64_arrays = []
for face_group in identified_faces:
encoded_faces = []
count = 0 # 각 그룹별로 이미지 개수를 세는 카운터
for face_image, _ in face_group:
# OpenCV는 BGR 형식으로 이미지를 읽기 때문에 RGB로 변환
face_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
# 이미지를 PIL 이미지 객체로 변환
pil_img = Image.fromarray(face_image)
# 메모리 내에서 이미지를 저장하기 위한 버퍼 생성
buf = BytesIO()
# 이미지를 JPEG 포맷으로 저장
pil_img.save(buf, format="JPEG")
# 버퍼의 바이트 데이터를 Base64 인코딩 문자열로 변환
base64_string = base64.b64encode(buf.getvalue()).decode('utf-8')
# 해당 인물의 인코딩된 이미지를 추가
encoded_faces.append(base64_string)
count += 1
if count == 3: # 각 인물 그룹에서 최대 3개의 이미지만 저장
break
# 모든 인물의 인코딩된 이미지를 배열에 추가
face_base64_arrays.append(encoded_faces)
return face_base64_arrays
"""