Safemotion Lib
Loading...
Searching...
No Matches
Functions
generate_clip Namespace Reference

Functions

 search_clip_list_v21 (anno_list, image_ids, frame_num)
 
 search_label_list (anno_list, cat_list)
 
 search_clip_list_v22 (anno_list, image_ids, frame_num, action_train_frame=60, pose_train_frame=10)
 
 save_clip_v21 (clip_list, input_anno_list, image_ids, base_anno, save_folder, json_name)
 
 save_clip_v22 (clip_list, input_anno_list, image_ids, base_anno, save_folder, json_name)
 
 generate_clip (json_folder, save_folder)
 

Function Documentation

◆ generate_clip()

generate_clip.generate_clip ( json_folder,
save_folder )
어노테이션 데이터들을 개별 행동 클립으로 분할하는 기능
args:
    json_folder (str): 어노테이션 파일이 저장된 폴더
    save_folder (str): 클립 데이터를 저장할 폴더

Definition at line 336 of file generate_clip.py.

336def generate_clip(json_folder, save_folder):
337 """
338 어노테이션 데이터들을 개별 행동 클립으로 분할하는 기능
339 args:
340 json_folder (str): 어노테이션 파일이 저장된 폴더
341 save_folder (str): 클립 데이터를 저장할 폴더
342 """
343
344 #어노테이션 파일 리스트
345 json_name_list, json_path_list = search_file(json_folder, '.json')
346
347 #데이터 관리자 생성
348 data_manager = AnnotationDataManager()
349
350 #클립 생성 프로세스
351 N= len(json_name_list)
352 for i, (json_name, json_path) in enumerate(zip(json_name_list, json_path_list)):
353 print(f'{i}/{N} {json_path}')
354
355 #데이터 관리자 초기화
356 data_manager.load_annotation(json_path)
357 data_manager.init_annotation()
358
359 #원본 파일 복사, info와 images 키에 대한 정보가 필요함, 데이터를 클립의 데이터로 교체해서 저장하기 위함
360 base_anno = copy.deepcopy(data_manager.dataset)
361
362 #변수 설정
363 labelmap_version = int(base_anno['info']['label_map_version']*10) #어노테이션 버전
364 frames = data_manager.get_number_of_image() #프레임 수
365
366 #추적 아이디 기준으로 구조 변경
367 track_data = data_manager.get_track_anno_data(filter=True)
368
369 #클립 생성
370 for track_id, anno_list in track_data.items():
371 if labelmap_version == 21: #버전 2.1
372 simple_anno_list = cvt_labelmap_v21_pose_and_action(anno_list, cvt_labelmap_v21_action_to_simple_ver2, cvt_labelmap_v21_pose_to_simple_ver2) #학습을 위한 행동 라벨로 변경
373 clip_list = search_clip_list_v21(simple_anno_list, data_manager.image_ids, frames) #변경된 라벨 기준으로 클립 정보 추출
374 save_clip_v21(clip_list, simple_anno_list, data_manager.image_ids, base_anno, save_folder, json_name) #클립 저장, 저장은 원본 행동 라벨 데이터로 저장함
375 elif labelmap_version == 22: #버전 2.2
376 simple_anno_list = cvt_labelmap_v22(anno_list) #학습을 위한 행동 라벨로 변경
377 clip_list = search_clip_list_v22(simple_anno_list, data_manager.image_ids, frames) #변경된 라벨 기준으로 클립 정보 추출
378 save_clip_v22(clip_list, anno_list, data_manager.image_ids, base_anno, save_folder, json_name) #클립 저장, 저장은 원본 행동 라벨 데이터로 저장함
379

◆ save_clip_v21()

generate_clip.save_clip_v21 ( clip_list,
input_anno_list,
image_ids,
base_anno,
save_folder,
json_name )
한사람에 대해 행동별로 생성된 클립을 저장하는 기능
v21 어노테이션 버전에 대해서만 동작함 
args:
    clip_list (list[dict]): 카테고리별 클래스의 클립정보(한명에 대한 정보), 클립의 시작, 끝, 클래스 저장되어 있음
    input_anno_list (list[dict]): 한사람에 대한 어노테이션 데이터
    image_ids (list[str]): 이미지 아이디 리스트
    base_anno : 어노테이션 데이터 원본, 파일을 읽었을때의 초기 상태
    save_folder (str): 클립 데이터를 저장할 폴더
    json_name (str): 원본 클립의 이름

Definition at line 229 of file generate_clip.py.

229def save_clip_v21(clip_list, input_anno_list, image_ids, base_anno, save_folder, json_name):
230 """
231 한사람에 대해 행동별로 생성된 클립을 저장하는 기능
232 v21 어노테이션 버전에 대해서만 동작함
233 args:
234 clip_list (list[dict]): 카테고리별 클래스의 클립정보(한명에 대한 정보), 클립의 시작, 끝, 클래스 저장되어 있음
235 input_anno_list (list[dict]): 한사람에 대한 어노테이션 데이터
236 image_ids (list[str]): 이미지 아이디 리스트
237 base_anno : 어노테이션 데이터 원본, 파일을 읽었을때의 초기 상태
238 save_folder (str): 클립 데이터를 저장할 폴더
239 json_name (str): 원본 클립의 이름
240 """
241
242 #이미지 인덱스와 입력 어노테이션 데이터의 인덱스를 매칭시켜줌
243 idx_link = {}
244 for i, anno in enumerate(input_anno_list):
245 image_idx = image_ids.index(anno['image_id'])
246 idx_link[image_idx] = i
247
248 #클립 데이터 저장
249 for clip in clip_list:
250 start = clip['start']
251 end = clip['end']
252 label = clip['label']
253 seq = clip['seq']
254
255 #하나의 클립에 대한 정보만 저장
256 anno_list = []
257 for image_idx in range(start, end+1):
258 #이미지 인덱스에 해당하는 어노테이션 데이터를 가져오기, 어노테이션 데이터가 없을 경우 None으로 셋팅
259 anno = input_anno_list[idx_link[image_idx]] if image_idx in idx_link else None
260
261 #어노테이션 데이터가 존재할 경우만 클립 정보 저장
262 if anno is not None:
263 anno_list.append(anno)
264
265 #클립 데이터 생성, 원본어노테이션 파일에 클립 시작, 끝, 데이터 셋팅
266 base_anno['annotations'] = anno_list
267 base_anno['info']['start'] = start
268 base_anno['info']['end'] = end
269
270 #클립 데이터 저장
271 track_id = anno_list[0]['track_id'] #추적 아이디
272 new_name = json_name.replace('.json', f'T{track_id:02d}L{label:02d}S{seq:02d}.json') #클립 이름 설정
273 save_path = os.path.join(save_folder, f'{label:02d}', new_name) #저장 경로
274 save_json(base_anno, save_path) #저장
275 print(' saved : ', save_path)
276

◆ save_clip_v22()

generate_clip.save_clip_v22 ( clip_list,
input_anno_list,
image_ids,
base_anno,
save_folder,
json_name )
한사람에 대해 행동별로 생성된 클립을 저장하는 기능
args:
    clip_list (dict): 카테고리별 클래스의 클립정보(한명에 대한 정보)
        구조
            {
                '카테고리 명': {클래스 번호: [ {클립정보(start, end, lable, seq)} ]}
            }
        구조 예시 : 
            {'action_upper': {0: [{'start': 20, 'end': 60, 'label':0, 'seq':0}]},
            'action_lower': {0: []},
            'pose': {1: []},
            'hand': {0: [], 1: []},
            'foot': {0: []}}
    input_anno_list (list[dict]): 한사람에 대한 어노테이션 데이터
    image_ids (list[str]): 이미지 아이디 리스트
    base_anno : 어노테이션 데이터 원본, 파일을 읽었을때의 초기 상태
    save_folder (str): 클립 데이터를 저장할 폴더
    json_name (str): 원본 클립의 이름

Definition at line 277 of file generate_clip.py.

277def save_clip_v22(clip_list, input_anno_list, image_ids, base_anno, save_folder, json_name):
278 """
279 한사람에 대해 행동별로 생성된 클립을 저장하는 기능
280 args:
281 clip_list (dict): 카테고리별 클래스의 클립정보(한명에 대한 정보)
282 구조
283 {
284 '카테고리 명': {클래스 번호: [ {클립정보(start, end, lable, seq)} ]}
285 }
286 구조 예시 :
287 {'action_upper': {0: [{'start': 20, 'end': 60, 'label':0, 'seq':0}]},
288 'action_lower': {0: []},
289 'pose': {1: []},
290 'hand': {0: [], 1: []},
291 'foot': {0: []}}
292 input_anno_list (list[dict]): 한사람에 대한 어노테이션 데이터
293 image_ids (list[str]): 이미지 아이디 리스트
294 base_anno : 어노테이션 데이터 원본, 파일을 읽었을때의 초기 상태
295 save_folder (str): 클립 데이터를 저장할 폴더
296 json_name (str): 원본 클립의 이름
297 """
298
299 #이미지 인덱스와 입력 어노테이션 데이터의 인덱스를 매칭시켜줌
300 idx_link = {}
301 for i, anno in enumerate(input_anno_list):
302 image_idx = image_ids.index(anno['image_id'])
303 idx_link[image_idx] = i
304
305 #클립 데이터 저장
306 for cat, label_clip_info in clip_list.items(): #cat(str):카테고리, label_clip_info(dict):클래스에 대한 클립 리스트
307 for label, clip_list in label_clip_info.items(): #label(int):클래스, clip_list(list[dict]):클립 리스트
308 for clip in clip_list:
309 start = clip['start']
310 end = clip['end']
311 label = clip['label']
312 seq = clip['seq']
313
314 #하나의 클립에 대한 정보만 저장
315 anno_list = []
316 for image_idx in range(start, end+1):
317 #이미지 인덱스에 해당하는 어노테이션 데이터를 가져오기, 어노테이션 데이터가 없을 경우 None으로 셋팅
318 anno = input_anno_list[idx_link[image_idx]] if image_idx in idx_link else None
319
320 #어노테이션 데이터가 존재할 경우만 클립 정보 저장
321 if anno is not None:
322 anno_list.append(anno)
323
324 #클립 데이터 생성, 원본어노테이션 파일에 클립 시작, 끝, 데이터 셋팅
325 base_anno['annotations'] = anno_list
326 base_anno['info']['start'] = start
327 base_anno['info']['end'] = end
328
329 #클립 데이터 저장
330 track_id = anno_list[0]['track_id'] #추적 아이디
331 new_name = json_name.replace('.json', f'T{track_id:02d}L{label:02d}S{seq:02d}.json') #클립 이름 설정
332 save_path = os.path.join(save_folder, cat, f'{label:02d}', new_name) #저장 경로
333 save_json(base_anno, save_path) #저장
334 print(' saved : ', save_path)
335

◆ search_clip_list_v21()

generate_clip.search_clip_list_v21 ( anno_list,
image_ids,
frame_num )
어노테이션 데이터(한명에 해당하는 데이터)에서 행동별로 클립을 생성하는 기능
v21 어노테이션 버전에 대해서만 동작함.
args:
    anno_list (list[dict]): 어노테이션 데이터 리스트(한명에 대한 정보), action_id에 action 키가 존재 해야함, 해당 키에 해당 프레임에서의 클래스 정보가 입력되어 있어야함   
    image_ids (list(int)): 어노테이션 데이터의 이미지 아이디 리스트
    frame_num (int): 어노테이션 데이터의 총 프레임 수
return (dict): 카테고리별 클래스의 클립 리스트, 클립은 클립의 시작 프레임 인덱스(start), 끝 프레임 인덱스(end), 카테고리의 클래스 번호(label), 중복방지를 위한 순번(seq)을 포함하고 있음

Definition at line 8 of file generate_clip.py.

8def search_clip_list_v21(anno_list, image_ids, frame_num):
9 """
10 어노테이션 데이터(한명에 해당하는 데이터)에서 행동별로 클립을 생성하는 기능
11 v21 어노테이션 버전에 대해서만 동작함.
12 args:
13 anno_list (list[dict]): 어노테이션 데이터 리스트(한명에 대한 정보), action_id에 action 키가 존재 해야함, 해당 키에 해당 프레임에서의 클래스 정보가 입력되어 있어야함
14 image_ids (list(int)): 어노테이션 데이터의 이미지 아이디 리스트
15 frame_num (int): 어노테이션 데이터의 총 프레임 수
16 return (dict): 카테고리별 클래스의 클립 리스트, 클립은 클립의 시작 프레임 인덱스(start), 끝 프레임 인덱스(end), 카테고리의 클래스 번호(label), 중복방지를 위한 순번(seq)을 포함하고 있음
17 """
18 #액션 클래스 저장
19 action_list = []
20 for anno in anno_list:
21 action_label = anno['action_id']['action'] #행동 클래스
22
23 #행동 클래스가 리스트에 없으면 행동 클래스 저장
24 if action_label not in action_list:
25 action_list.append(action_label)
26
27 #클래스별 클립 생성
28 clip_list = []
29 for label in action_list:
30 #최대 간격 설정
31 max_interval = 15 if label == 0 else 30
32
33 #클립의 이미지 인덱스 저장 변수
34 idx_list = [[]]
35
36 #클립 정보 생성, 클래스에 해당하는 이미지 인덱스 리스트
37 for anno in anno_list:
38 action_label = anno['action_id']['action']
39 image_idx = image_ids.index(anno['image_id'])
40
41 #체크하는 레이블과 다르면 패스
42 if label != action_label:
43 continue
44
45 #클립이 비어있으면 생성
46 if len(idx_list[-1]) == 0:
47 idx_list[-1].append(image_idx)
48
49 #프레임 사이 간격이 max_interval 이하면 이어서 저장, 아니면 새로운 클립 생성
50 if image_idx - idx_list[-1][-1] < max_interval:
51 idx_list[-1].append(image_idx)
52 else:
53 idx_list.append([image_idx])
54
55 #클립 생성
56 for i, idxs in enumerate(idx_list):
57
58 #클립의 시작, 끝 초기화
59 start, end = idxs[0], idxs[-1]
60
61 # #행동 구간이 7프레임 이하이면 패스
62 # if end - start < 7:
63 # continue
64
65 #마진 추가, 클래스가 0(행동 없음)이 아니면 마진 추가함
66 if label != 0:
67 #클립을 최소 90프레임으로 설정함
68 clip_len = end - start #클립 길이
69 margin = max( (90 - clip_len)//2, 30) #마진값 설정
70 start = max(0, start - margin) #마진이 포함된 시작 프레임 설정
71 end = min(frame_num-1, max(start + 60, end + margin)) #마진이 포함된 끝 프레임 설정
72
73 #학습용 클립 길이기반 유효성 검사
74 if end - start < 60:
75 continue
76
77 #클립 생성
78 clip = dict(start=start, end=end, label=label, seq=i)
79 clip_list.append(clip)
80
81 return clip_list
82

◆ search_clip_list_v22()

generate_clip.search_clip_list_v22 ( anno_list,
image_ids,
frame_num,
action_train_frame = 60,
pose_train_frame = 10 )
어노테이션 데이터(한명에 해당하는 데이터)에서 행동별로 클립을 생성하는 기능
args:
    anno_list (list[dict]): 어노테이션 데이터 리스트(한명에 대한 정보), 데이터에는 카테고리별 클래스가 설정된 'action_id'키를 포함하여야함
    image_ids (list(int)): 어노테이션 데이터의 이미지 아이디 리스트
    frame_num (int): 어노테이션 데이터의 총 프레임 수
    action_train_frame (int): 행동 인식의 학습 데이터 생성에 사용되는 프레임 수
    pose_train_frame (int): 포즈 인식의 학습 데이터 생성에 사용되는 프레임 수
return (dict): 카테고리별 클래스의 클립 리스트, 클립은 클립의 시작 프레임 인덱스(start), 끝 프레임 인덱스(end), 카테고리의 클래스 번호(label), 중복방지를 위한 순번(seq)을 포함하고 있음

Definition at line 107 of file generate_clip.py.

107def search_clip_list_v22(anno_list, image_ids, frame_num, action_train_frame=60, pose_train_frame=10):
108 """
109 어노테이션 데이터(한명에 해당하는 데이터)에서 행동별로 클립을 생성하는 기능
110 args:
111 anno_list (list[dict]): 어노테이션 데이터 리스트(한명에 대한 정보), 데이터에는 카테고리별 클래스가 설정된 'action_id'키를 포함하여야함
112 image_ids (list(int)): 어노테이션 데이터의 이미지 아이디 리스트
113 frame_num (int): 어노테이션 데이터의 총 프레임 수
114 action_train_frame (int): 행동 인식의 학습 데이터 생성에 사용되는 프레임 수
115 pose_train_frame (int): 포즈 인식의 학습 데이터 생성에 사용되는 프레임 수
116 return (dict): 카테고리별 클래스의 클립 리스트, 클립은 클립의 시작 프레임 인덱스(start), 끝 프레임 인덱스(end), 카테고리의 클래스 번호(label), 중복방지를 위한 순번(seq)을 포함하고 있음
117 """
118
119 #클립 생성 파라미터 설정
120 cat_info = dict()
121 cat_list=['action_upper', 'action_lower', 'pose', 'hand', 'foot']
122 for cat in cat_list:
123 cat_info[cat] = dict()
124
125 cat_info['action_upper']['info'] = cvt_labelmap_v22_action_upper
126 cat_info['action_lower']['info'] = cvt_labelmap_v22_action_lower
127 cat_info['pose']['info'] = cvt_labelmap_v22_action_pose
128 cat_info['hand']['info'] = cvt_labelmap_v22_action_hand
129 cat_info['foot']['info'] = cvt_labelmap_v22_action_foot
130 cat_info['action_upper']['train_frame'] = action_train_frame
131 cat_info['action_lower']['train_frame'] = action_train_frame
132 cat_info['pose']['train_frame'] = pose_train_frame
133 cat_info['hand']['train_frame'] = pose_train_frame
134 cat_info['foot']['train_frame'] = pose_train_frame
135
136 #어노테이션 데이터에서 카테고리별 클래스 리스트를 탐색, 데이터에 존재하는 모든 클래스를 의미함
137 # label_info 예시
138 # {'action_upper': [0],
139 # 'action_lower': [0],
140 # 'pose': [1],
141 # 'hand': [0, 1],
142 # 'foot': [0]}
143 label_info = search_label_list(anno_list, cat_list)
144
145 #카테고리별 클래스에 해당하는 이미지 인덱스 리스트, 클립을 구성하는 프레임 인덱스
146 # clip_info init 예시
147 # {'action_upper': {0: [[]]},
148 # 'action_lower': {0: [[]]},
149 # 'pose': {1: [[]]},
150 # 'hand': {0: [[]], 1: [[]]},
151 # 'foot': {0: [[]]}}
152 clip_info = dict()
153 for cat in cat_list:
154 clip_info[cat] = dict()
155 label_list = label_info[cat]
156 for label in label_list:
157 clip_info[cat][label] = [[]]
158
159 #카테고리별 클래스에 해당하는 이미지 인덱스 리스트
160 clip_interval = 15 #프레임 간격의 임계치, clip_interval이상이면 다른 클립으로 분리함
161 for anno in anno_list:
162 image_idx = image_ids.index(anno['image_id']) #어노테이션 데이터의 이미지 인덱스
163
164 #카테고리별 클립 정보 설정
165 for cat in cat_list:
166 label = anno['action_id'][cat]
167
168 if len(clip_info[cat][label][-1]) == 0: #클립이 비어있으면 초기화
169 clip_info[cat][label][-1].append(image_idx)
170
171 if image_idx - clip_info[cat][label][-1][-1] < clip_interval: #프레임 간격이 임계치보다 작으면 같은 클립으로 취급함
172 clip_info[cat][label][-1].append(image_idx)
173 else:
174 clip_info[cat][label].append([image_idx]) #프레임 간격이 임계치보다 크면 새로운 클립으로 생성함
175
176 #카테고리별 클래스의 클립 설정
177 # clip_list init 예시
178 # {'action_upper': {0: []},
179 # 'action_lower': {0: []},
180 # 'pose': {1: []},
181 # 'hand': {0: [], 1: []},
182 # 'foot': {0: []}}
183 clip_list = dict()
184 for cat in cat_list:
185 clip_list[cat] = dict()
186 label_list = label_info[cat]
187 for label in label_list:
188 clip_list[cat][label] = []
189
190 #카테고리별 클래스의 클립 생성
191 for cat, cat_clip_info in clip_info.items():
192 for label, clip_frame_list in cat_clip_info.items():
193
194 #클래스의 유효성 체크
195 if label == -1 or label is None:
196 continue
197
198 #클립 정보 생성
199 seq = 0
200 for frame_list in clip_frame_list:
201
202 #클립의 시작, 끝 초기화
203 start, end = frame_list[0], frame_list[-1]
204
205 #클립 길이 유효성 체크(마진 없는 클립 길이)
206 clip_len = end - start +1
207 if clip_len < cat_info[cat]['info'][label][3]:
208 continue
209
210 #마진 추가
211 if cat_info[cat]['info'][label][4]: #사용자 설정 마진
212 #클립을 최소 90프레임으로 설정함
213 margin = max( (90 - clip_len)//2, 30) #마진값 설정
214 start = max(0, start - margin) #마진이 포함된 시작 프레임 설정
215 end = min(frame_num-1, max(start + 60, end + margin)) #마진이 포함된 끝 프레임 설정
216
217 #학습용 클립 길이기반 유효성 검사
218 if (end - start +1) < cat_info[cat]['train_frame']:
219 continue
220
221 #클립 생성
222 clip = dict(start=start, end=end, label=label, seq=seq)
223 clip_list[cat][label].append(clip)
224 seq += 1
225
226 return clip_list
227
228

◆ search_label_list()

generate_clip.search_label_list ( anno_list,
cat_list )
어노테이션 데이터에 존재하는 카테고리별 클래스 리스트 탐색기능
args:
    anno_list (list[dict]): 어노테이션 데이터 리스트, 데이터에는 카테고리별 클래스가 설정된 'action_id'키를 포함하여야함
    cat_list (list[str]): 카테고리 리스트
return (dict): 어노테이션 데이터에 존재하는 각 카테고리별 클래스 리스트

Definition at line 83 of file generate_clip.py.

83def search_label_list(anno_list, cat_list):
84 """
85 어노테이션 데이터에 존재하는 카테고리별 클래스 리스트 탐색기능
86 args:
87 anno_list (list[dict]): 어노테이션 데이터 리스트, 데이터에는 카테고리별 클래스가 설정된 'action_id'키를 포함하여야함
88 cat_list (list[str]): 카테고리 리스트
89 return (dict): 어노테이션 데이터에 존재하는 각 카테고리별 클래스 리스트
90 """
91
92 #카테고리별 클래스 리스트 초기화
93 ret_dict = dict()
94 for cat in cat_list:
95 ret_dict[cat] = []
96
97 #탐색
98 for anno in anno_list:
99 for cat in cat_list:
100 label = anno['action_id'][cat]
101 if label not in ret_dict[cat]:
102 ret_dict[cat].append(label)
103
104 return ret_dict
105
106