Safemotion Lib
Loading...
Searching...
No Matches
action_demo_with_anno.py
Go to the documentation of this file.
2#system path 설정
3import sys
4sys_path = ['/workspace/smlab', '/workspace']
5for path in sys_path:
6 if path not in sys.path:
7 sys.path.append(path)
8
9#import package
10import os
11import cv2
12import smrunner
13from smutils.utils_vis import draw_single_bbox_and_label
14from smutils.utils_vis import vis_pose_coco_skeleton
15from smutils.utils_os import search_file, create_directory
16from smutils.utils_data import load_labelmap
17from smutils.utils_video import make_video
18
19from smdataset.AnnotationDataManager import AnnotationDataManager
20
21import copy
22import numpy as np
23import shutil
24
25#annotation data 변환 함수
26def make_pose_result(anno_data):
27 pose_result = []
28 for anno in anno_data:
29 tmp_data = {}
30
31 box = copy.deepcopy(anno['bbox'])
32
33 tmp_data['bbox'] = np.array(box)
34 tmp_data['keypoints'] = np.array(anno['keypoints'])
35 tmp_data['track_id'] = anno['track_id']
36 pose_result.append(tmp_data)
37
38 return pose_result
39
40#시각화 파라미터
41action_vis_param = dict(
42 box_color = (0, 255, 0),
43 box_thk = 3,
44 txt_color = (255, 255, 255),
45 txt_thk=3,
46 txt_scale=1.5,
47 box_type='xyxy'
48)
49
50vis_param = dict(
51 box_color = (0, 255, 0),
52 box_thk = 3,
53 txt_color = (255, 255, 255),
54 txt_thk=3,
55 txt_scale=1.5,
56 box_type='xyxy'
57)
58
59#경로 설정
60action_cfg_path = '/workspace/InnoTest/models/posec3d_action.py'
61posture_cfg_path = '/workspace/InnoTest/models/posec3d_pose.py'
62image_base = '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/images' #이미지가 저장된 폴더
63save_root = '/media/safemotion/HDD5/pjm_test/inno2023_result_select_half' #결과 동영상 저장 폴더
64
65#어노테이션 파일이 저장된 폴더 리스트
66anno_folder_list = [
67 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_1',
68 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_kkomo_1',
69 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_kkumjalam_1',
70 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_kkumjalam_hard_1',
71 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_kkomo_2',
72 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_kid_kkumjalam_hard_1'
73 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_2nd_3',
74 '/media/safemotion/HDD2/SM_Dataset/action_2022/action_cctv_img/annotations_action_v22_2nd_4',
75]
76
77#레이블맵 변환 테이블
78cvt_lower_map = [0, 1, 2, 0, 4, 5, 6, 7, 8, 9, 0, 11]
79cvt_upper_map = [0, 0, 0, 3, 4, 0]
80cvt_pose_map = [0, 0, 0, 0, 4, 4, 6, 7]
81cvt_hand_map = [0, 0, 0, 3]
82
83#저장 폴더 생성
84create_directory(save_root)
85
86# 모델 빌드
87device = 'cuda:0'
88action_model = smrunner.build_model(action_cfg_path).to(device)
89posture_model = smrunner.build_model(posture_cfg_path).to(device)
90action_model.eval()
91posture_model.eval()
92
93#레이블 맵 로드
94labelmap = dict()
95labelmap['action_upper'] = load_labelmap('/workspace/smlab/smaction/datasets/safemotion_v22_upper_action.txt')
96labelmap['action_lower'] = load_labelmap('/workspace/smlab/smaction/datasets/safemotion_v22_lower_action.txt')
97labelmap['pose'] = load_labelmap('/workspace/smlab/smaction/datasets/safemotion_v22_pose.txt')
98labelmap['hand'] = load_labelmap('/workspace/smlab/smaction/datasets/safemotion_v22_hand.txt')
99
100#어노테이션 파일 경로 셋팅
101json_path_list = []
102for anno_folder in anno_folder_list:
103 name_list, path_list = search_file(anno_folder, '.json')
104 json_path_list.extend(path_list)
105NUM = len(json_path_list)
106
107#샘플링 파라미터 설정
108#TODO: cfg로 옮겨서 runner의 파라미터로 설정할 필요가 있음 또는 pipline에 설정
109video_fps = 30
110action_k = video_fps*2
111action_sample = 20
112pose_k = video_fps//2
113pose_sample = 6
114
115#데이터 로더
116data_manager = AnnotationDataManager()
117
118#데모
119for iter_n, json_path in enumerate(json_path_list):
120
121 #저장경로 설정
122 json_name = json_path.split('/')[-1]
123 save_folder = os.path.join(save_root, json_name.split('.')[0]) #임시 저장 경로
124 save_video_path = os.path.join(save_root, json_name.replace('.json', '.mp4')) #동영상 저장 경로
125 create_directory(save_folder) #폴더 생성
126
127 #데이터 매니저 초기화
128 data_manager.load_annotation(json_path, image_base=image_base)
129 data_manager.init_annotation()
130
131 #초기화
132 track_data = {} #추적 객체 저장 변수, 추적아이디별 박스, 스켈레톤 정보 저장
133 frame_id = 0 #프레임 아이디, 0부터 1씩 증가
134 while True:
135 #진행도 출력
136 print(f'[{iter_n+1}/{NUM}] {json_name} : {frame_id}', end='\r')
137
138 #해당 프레임에 존재하는 어노테이션 데이터 읽기
139 anno_data = data_manager.get_anno_data_in_image(filter=True)
140
141 #이미지 로드
142 image = data_manager.read_image()
143
144 #가시화 이미지 생성
145 vis_img = image.copy()
146 vis_img = cv2.cvtColor(vis_img, cv2.COLOR_RGB2BGR)
147
148 # 모델 inference(검출, 추적, 포즈) 결과와 동일한 포맷으로 만들기
149 pose_result = make_pose_result(anno_data)
150
151 #추적 아이디별로 포즈 데이터 저장
152 for pose in pose_result:
153 track_id = int(pose['track_id'])
154 if track_id not in track_data:
155 track_data[track_id] = []
156 pose['frame_id'] = frame_id
157 track_data[track_id].append(pose)
158
159 #스켈레톤 시각화
160 vis_img = vis_pose_coco_skeleton(vis_img, pose_result)
161
162 delete_list = []
163 txt_pos_y = 50
164 for track_id, pose_q in track_data.items():
165 #박스 시각화
166 bbox = pose_q[-1]['bbox']
167
168 last_frame = pose_q[-1]['frame_id']
169 if last_frame == frame_id:
170 label = f'{track_id:3d}'
171 vis_img = draw_single_bbox_and_label(vis_img, bbox, label, **vis_param)
172
173
174 #최근 1초동안 검출 안되면 제거
175 if frame_id - last_frame > action_k*0.5:
176 delete_list.append(track_id)
177 continue
178
179 #최근 15프레임동안 검출 안되면 넘김
180 #포스처 때문에 넣은 조건, 하나의 모델로 변경되면 조건 변경 필요함
181 if frame_id - last_frame > 15:
182 continue
183
184 #액션 모델 inference
185 action_result = action_model.run_recognizer(pose_q, action_k, action_sample, device=device)
186
187 #결과가 None면 유효성 체크에서 탈락한 것임
188 if action_result is None:
189 continue
190
191 posture_result = posture_model.run_recognizer(pose_q[-pose_k:], pose_k, pose_sample, False, device=device)
192 # #첫 프레임과 마지막 프레임 간격이 설정한 구간을 넘기면 맨 앞쪽 포즈 제거
193 # #상황에 따라 루프로 제거해야 할 수도 있음
194 if last_frame - pose_q[0]['frame_id'] >= action_k:
195 del pose_q[0]
196
197
198 #추론된 결과 변환
199 pose_label = cvt_pose_map[posture_result['pred_pose']]
200 upper_label = cvt_upper_map[action_result['pred_action_upper']]
201 lower_label = cvt_lower_map[action_result['pred_action_lower']]
202 hand_label = cvt_hand_map[posture_result['pred_hand']]
203
204 #행동 라벨 및 박스 시각화
205 label = f"{track_id:3d}: {labelmap['pose'][pose_label]}"
206
207 if hand_label != 0:
208 label += f"/{labelmap['hand'][hand_label]}"
209 if upper_label != 0:
210 label += f"/{labelmap['action_upper'][upper_label]}"
211 if lower_label != 0:
212 label += f"/{labelmap['action_lower'][lower_label]}"
213
214 cv2.putText(vis_img, label, (10, txt_pos_y), cv2.FONT_HERSHEY_DUPLEX, 1.5, (0, 0, 0), 10, 1)
215 cv2.putText(vis_img, label, (10, txt_pos_y), cv2.FONT_HERSHEY_DUPLEX, 1.5, (0, 255, 255), 2, 1)
216 txt_pos_y += 45
217
218 vis_img = draw_single_bbox_and_label(vis_img, bbox, f'{track_id:3d}', **action_vis_param)
219
220 #긴시간 미검출된 추적 아이디 제거
221 for track_id in delete_list:
222 del track_data[track_id]
223
224 #마지막 프레임일경우 종료
225 if data_manager.get_number_of_image() <= (data_manager.image_idx+1):
226 break
227
228 #다음프레임으로 이동
229 data_manager.move_image_right()
230
231 #프레임 아이디 증가
232 frame_id+=1
233
234 #시각화 이미지 저장
235 name = f'{frame_id:06d}.jpg'
236 save_path = os.path.join(save_folder, name)
237 cv2.imwrite(save_path, vis_img)
238
239 #시각화 이미지 비디오로 저장
240 make_video(save_folder, save_video_path, fps=video_fps, half=True) #동영상 생성
241 shutil.rmtree(save_folder) #임시 폴더 삭제
242
243
244