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

Functions

 display_reid_result (sorted_keep_index, crop_image_path, test_image_list)
 
 get_palette (n)
 
 vis_instance_segmentation (image, masks=None, bboxes=None, colors=None)
 
 vis_pose_coco_skeleton (image, pose_results)
 
 vis_pose_coco_skeleton_one_person (image, keypoints)
 
 draw_single_bbox_and_label (img, bbox, label, box_color, box_thk, txt_color, txt_thk, txt_scale, box_type='xywh')
 
 draw_bboxes_list (image, bboxes, box_color, box_thk, box_type, labels=None)
 
 draw_bboxes_dict (image, bboxes, box_color, box_thk, box_type)
 
 draw_and_save_bboxes (image, save_path, bboxes, box_color, box_thk, box_type='xywh')
 
 draw_and_save_single_bbox (image, save_path, bbox, label, box_color, box_thk, box_type='xywh')
 
 make_video (folder_or_paths, save_path, fps=30, i_size='half')
 

Function Documentation

◆ display_reid_result()

utils_vis.display_reid_result ( sorted_keep_index,
crop_image_path,
test_image_list )

Definition at line 7 of file utils_vis.py.

7def display_reid_result(sorted_keep_index, crop_image_path, test_image_list):
8 columns = 5
9 cnt = 0
10 rows = (len(sorted_keep_index) // columns)+1
11
12 figsize = (30.0, rows*2)
13 plt.figure(figsize=figsize)
14
15 for index in tqdm(sorted_keep_index):
16
17 image_path = os.path.join(crop_image_path, test_image_list[index[0]])
18 image = Image.open(image_path)
19 image_index = cnt+1
20
21 title_txt = f'{test_image_list[index[0]]} | {index[1]:.4f}'
22 plt.subplot(rows, columns, image_index)
23 plt.title(title_txt)
24 plt.xticks([])
25 plt.yticks([])
26 plt.imshow(image)
27
28 cnt+=1
29
30 plt.show()
31

◆ draw_and_save_bboxes()

utils_vis.draw_and_save_bboxes ( image,
save_path,
bboxes,
box_color,
box_thk,
box_type = 'xywh' )
박스를 그리고 박스가 그려진 이미지를 저장하는 기능
args:
    image (str or np.array): 이미지 경로 또는 이미지
    save_path (str): 이미지 저장 경로
    bboxes (np.array or list[np.array] or dict): 박스
    box_color (tuple): 박스 컬러
    box_thk (int): 박스를 그리는 선의 두께
    box_type (str): 박스 구조, 'xyxy', 'xywh' 지원

Definition at line 227 of file utils_vis.py.

227def draw_and_save_bboxes(image, save_path, bboxes, box_color, box_thk, box_type='xywh'):
228 """
229 박스를 그리고 박스가 그려진 이미지를 저장하는 기능
230 args:
231 image (str or np.array): 이미지 경로 또는 이미지
232 save_path (str): 이미지 저장 경로
233 bboxes (np.array or list[np.array] or dict): 박스
234 box_color (tuple): 박스 컬러
235 box_thk (int): 박스를 그리는 선의 두께
236 box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
237 """
238
239 #이미지의 입력이 경로인 경우 로드
240 if isinstance(image, str):
241 image = cv2.imread(image)
242
243 #그리기
244 if isinstance(bboxes, dict):
245 image = draw_bboxes_dict(image, bboxes, box_color, box_thk, box_type)
246 else:
247 image = draw_bboxes_list(image, bboxes, box_color, box_thk, box_type)
248
249 #저장
250 cv2.imwrite(save_path, image)
251

◆ draw_and_save_single_bbox()

utils_vis.draw_and_save_single_bbox ( image,
save_path,
bbox,
label,
box_color,
box_thk,
box_type = 'xywh' )
박스 한개를 그리고 박스가 그려진 이미지를 저장하는 기능
args:
    image (str or np.array): 이미지 경로 또는 이미지
    save_path (str): 이미지 저장 경로
    bbox (np.array): 박스, shape (4 or 5 or 6)
    label (str): 출력 문구
    box_color (tuple): 박스 컬러
    box_thk (int): 박스를 그리는 선의 두께
    box_type (str): 박스 구조, 'xyxy', 'xywh' 지원

Definition at line 252 of file utils_vis.py.

252def draw_and_save_single_bbox(image, save_path, bbox, label, box_color, box_thk, box_type='xywh'):
253 """
254 박스 한개를 그리고 박스가 그려진 이미지를 저장하는 기능
255 args:
256 image (str or np.array): 이미지 경로 또는 이미지
257 save_path (str): 이미지 저장 경로
258 bbox (np.array): 박스, shape (4 or 5 or 6)
259 label (str): 출력 문구
260 box_color (tuple): 박스 컬러
261 box_thk (int): 박스를 그리는 선의 두께
262 box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
263 """
264
265 #이미지의 입력이 경로인 경우 로드
266 if isinstance(image, str):
267 image = cv2.imread(image)
268
269 #박스에 추적 아이디가 포함된 경우
270 if bbox.shape[0] == 6:
271 bbox = bbox[1:]
272
273 #그리기
274 image = draw_single_bbox_and_label(image, bbox, label, box_color, box_thk, (255, 255, 255), 2, 1.5, box_type=box_type)
275
276 #저장
277 cv2.imwrite(save_path, image)
278

◆ draw_bboxes_dict()

utils_vis.draw_bboxes_dict ( image,
bboxes,
box_color,
box_thk,
box_type )
딕셔너리 형태로 입력된 박스를 그리는 기능
키는 추적 아이디, value는 박스
args:
    image (np.array): 이미지
    bboxes (dict[np.array]): 박스
    box_color (tuple): 박스 컬러
    box_thk (int): 박스를 그리는 선의 두께
    box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
return (np.array): 박스가 그려진 이미지

Definition at line 210 of file utils_vis.py.

210def draw_bboxes_dict(image, bboxes, box_color, box_thk, box_type):
211 """
212 딕셔너리 형태로 입력된 박스를 그리는 기능
213 키는 추적 아이디, value는 박스
214 args:
215 image (np.array): 이미지
216 bboxes (dict[np.array]): 박스
217 box_color (tuple): 박스 컬러
218 box_thk (int): 박스를 그리는 선의 두께
219 box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
220 return (np.array): 박스가 그려진 이미지
221 """
222 for track_id, bbox in bboxes.items():
223 label = f'{track_id}'
224 image = draw_single_bbox_and_label(image, bbox, label, box_color, box_thk, (255, 255, 255), 2, 1.5, box_type=box_type)
225 return image
226

◆ draw_bboxes_list()

utils_vis.draw_bboxes_list ( image,
bboxes,
box_color,
box_thk,
box_type,
labels = None )
리스트 또는 np.array 타입의 박스를 이미지에 그리는 기능
args:
    image (np.array): 이미지
    bboxes (list[np.array], np.array): 박스
    box_color (tuple): 박스 컬러
    box_thk (int): 박스를 그리는 선의 두께
    box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
    labels (str): 출력 문구
return (np.array): 박스 및 텍스트가 그려진 이미지

Definition at line 182 of file utils_vis.py.

182def draw_bboxes_list(image, bboxes, box_color, box_thk, box_type, labels=None):
183 """
184 리스트 또는 np.array 타입의 박스를 이미지에 그리는 기능
185 args:
186 image (np.array): 이미지
187 bboxes (list[np.array], np.array): 박스
188 box_color (tuple): 박스 컬러
189 box_thk (int): 박스를 그리는 선의 두께
190 box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
191 labels (str): 출력 문구
192 return (np.array): 박스 및 텍스트가 그려진 이미지
193 """
194
195 #출력 문구가 없을경우 초기화
196 if labels == None:
197 labels = ['']*len(bboxes)
198
199 #박스 그리기
200 for bbox, label in zip(bboxes, labels):
201 #출력 문구를 추적 아이디로 설정하고 박스 셋팅
202 if label == '' and bbox.shape[0] == 6:
203 label = str(int(bbox[0]))
204 bbox = bbox[1:]
205
206 #그리기
207 image = draw_single_bbox_and_label(image, bbox, label, box_color, box_thk, (255, 255, 255), 2, 1.5, box_type=box_type)
208 return image
209

◆ draw_single_bbox_and_label()

utils_vis.draw_single_bbox_and_label ( img,
bbox,
label,
box_color,
box_thk,
txt_color,
txt_thk,
txt_scale,
box_type = 'xywh' )
이미지에 박스 한개와 텍스트를 출력하는 기능
텍스트의 위치는 박스의 상단, 상단에 출력하지 못할것 같다고 판단되면 박스 하단에 출력
args:
    img (np.array): 이미지
    bbox (np.array): 박스, shape (4 or 5)
    label (str): 출력 문구
    box_color (tuple): 박스 컬러
    box_thk (int): 박스를 그리는 선의 두께
    txt_color (tuple): 텍스트의 색상
    txt_thk (int): 텍스트 선의 두께
    txt_scale (float): 텍스트의 크기
    box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
return (np.array): 박스 및 텍스트가 그려진 이미지

Definition at line 145 of file utils_vis.py.

145def draw_single_bbox_and_label(img, bbox, label, box_color, box_thk, txt_color, txt_thk, txt_scale, box_type='xywh'):
146 """
147 이미지에 박스 한개와 텍스트를 출력하는 기능
148 텍스트의 위치는 박스의 상단, 상단에 출력하지 못할것 같다고 판단되면 박스 하단에 출력
149 args:
150 img (np.array): 이미지
151 bbox (np.array): 박스, shape (4 or 5)
152 label (str): 출력 문구
153 box_color (tuple): 박스 컬러
154 box_thk (int): 박스를 그리는 선의 두께
155 txt_color (tuple): 텍스트의 색상
156 txt_thk (int): 텍스트 선의 두께
157 txt_scale (float): 텍스트의 크기
158 box_type (str): 박스 구조, 'xyxy', 'xywh' 지원
159 return (np.array): 박스 및 텍스트가 그려진 이미지
160 """
161
162 #텍스트 출력 위치
163 txt_xy = (int(bbox[0])-30, int(bbox[1]-20))
164 if int(bbox[1]-20) < 40:
165 txt_xy = (int(bbox[0]-30), int(bbox[1]+bbox[3]+25))
166
167 #입력 데이터를 int로 변환후 튜플로 묶기
168 box_color = tuple(map(int, box_color))
169 txt_color = tuple(map(int, txt_color))
170
171 #박스 그리기
172 if box_type == 'xywh':
173 img = cv2.rectangle(img, (int(bbox[0]), int(bbox[1])), (int(bbox[0]+bbox[2]), int(bbox[1]+bbox[3])), box_color, box_thk)
174 elif box_type == 'xyxy':
175 img = cv2.rectangle(img, (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3])), box_color, box_thk)
176
177 #텍스트 출력
178 cv2.putText(img, label, txt_xy, cv2.FONT_HERSHEY_DUPLEX, txt_scale, txt_color, txt_thk, 1)
179
180 return img
181

◆ get_palette()

utils_vis.get_palette ( n)
설정한 수량만큼 컬러 테이블을 생성하는 기능
args:
    n (int): 생성하려는 색상 수량
return (list[tuple]): 컬러 테이블

Definition at line 11 of file utils_vis.py.

11def get_palette(n):
12 """
13 설정한 수량만큼 컬러 테이블을 생성하는 기능
14 args:
15 n (int): 생성하려는 색상 수량
16 return (list[tuple]): 컬러 테이블
17 """
18 state = np.random.get_state()
19 np.random.seed(42) #고정된 컬러 테이블 출력을 위해 셋팅
20 palette = np.random.randint(0, 256, size=(n, 3))
21 np.random.set_state(state) #이후에 랜덤성 관련 함수를 사용할 수도 있기 때문에 원래의 값으로 셋팅
22 colors = [tuple(c) for c in palette]
23 return colors
24

◆ make_video()

utils_vis.make_video ( folder_or_paths,
save_path,
fps = 30,
i_size = 'half' )
이미지를 기반으로 동영상을 생성하는 기능
TODO: utils_video.py의 make_video를 사용하도록 함, 제거 필요
args:
    folder_or_paths (str or list[str]): 동영상을 만들 이미지가 저장된 폴더 또는 이미지 경로 리스트
    save_path (str): 동영상을 저장할 경로
    fps (int): 생성할 동영상의 프레임 속도
    i_size (str): 이미지의 크기를 절반으로 줄여서 저장할지 여부, 'half'입력했을 경우 영상을 절반 크기로 생성함

Definition at line 279 of file utils_vis.py.

279def make_video(folder_or_paths, save_path, fps=30, i_size='half'):
280 """
281 이미지를 기반으로 동영상을 생성하는 기능
282 TODO: utils_video.py의 make_video를 사용하도록 함, 제거 필요
283 args:
284 folder_or_paths (str or list[str]): 동영상을 만들 이미지가 저장된 폴더 또는 이미지 경로 리스트
285 save_path (str): 동영상을 저장할 경로
286 fps (int): 생성할 동영상의 프레임 속도
287 i_size (str): 이미지의 크기를 절반으로 줄여서 저장할지 여부, 'half'입력했을 경우 영상을 절반 크기로 생성함
288 """
289
290 print('Warning: Please use make_video in utils_video.py.')
291
292 #이미지 파일경로 설정
293 if isinstance(folder_or_paths, str):
294 _, path_list = utils.search_file(folder_or_paths, '.jpg')
295 else:
296 path_list = folder_or_paths
297
298 #첫 이미지 읽어서 이미지 크기 알아내기
299 img = cv2.imread(path_list[0])
300 h, w, _ = img.shape
301
302 fourcc = cv2.VideoWriter_fourcc(*'mp4v')
303
304 #이미지 크기 설정
305 if i_size == 'half':
306 h = int(h/2)
307 w = int(w/2)
308
309 #비디오 작성자 생성
310 video_writer = cv2.VideoWriter(save_path, fourcc, fps, (w, h))
311
312 #동영상 만들기
313 N = len(path_list)
314 for i in tqdm(range(N)):
315 path = path_list[i]
316 img = cv2.imread(path) #이미지 읽기
317
318 if i_size == 'half': #이미지 사이즈 조절
319 img = cv2.resize(img, dsize=(w, h), interpolation=cv2.INTER_AREA)
320
321 video_writer.write(img)
322
323 print()
324
325 video_writer.release()
326
327

◆ vis_instance_segmentation()

utils_vis.vis_instance_segmentation ( image,
masks = None,
bboxes = None,
colors = None )
Instance Segmentation 결과 시각화를 위한 기능
박스 또는 마스크 둘중 하나 이상은 입력되어야함
args:
    image (np.array): 이미지
    masks (list[np.array]): Instance Mask, 각 마스크의 shape은 이미지의 크기와 동일함
    bboxes (np.array): 검출 객체의 박스, 순서는 마스크와 매칭되어야함
    colors (list[tuple]): 컬러 테이블
return (np.array): Instance Segmentation 결과가 시각화된 이미지
    TODO: 이미지를 리턴하지 않아도 됨, 리턴 제거

Definition at line 25 of file utils_vis.py.

25def vis_instance_segmentation(image, masks=None, bboxes=None, colors=None):
26 """
27 Instance Segmentation 결과 시각화를 위한 기능
28 박스 또는 마스크 둘중 하나 이상은 입력되어야함
29 args:
30 image (np.array): 이미지
31 masks (list[np.array]): Instance Mask, 각 마스크의 shape은 이미지의 크기와 동일함
32 bboxes (np.array): 검출 객체의 박스, 순서는 마스크와 매칭되어야함
33 colors (list[tuple]): 컬러 테이블
34 return (np.array): Instance Segmentation 결과가 시각화된 이미지
35 TODO: 이미지를 리턴하지 않아도 됨, 리턴 제거
36 """
37
38 #컬러 테이블 설정
39 if colors is None:
40 if masks is not None:
41 n = masks.shape[0]
42 else:
43 n = bboxes.shape[0]
44 colors = get_palette(n)
45
46 #마스크가 입력되었을 경우
47 if masks is not None:
48 mask_img = np.zeros_like(image) #마스크 이미지 초기화
49
50 #마스크 이미지 생성
51 for mask, color in zip(reversed(masks), colors):
52 mask_img[mask] = color
53
54 #컬러 영상에 오버랩
55 mask = mask_img > 0
56 image[mask] = image[mask]*0.3 + mask_img[mask]*0.7
57
58 #박스가 입력되었을 경우 박스 그리기
59 if bboxes is not None:
60 for bbox, color in zip(reversed(bboxes), colors):
61 image = draw_single_bbox_and_label(image, bbox, f'{bbox[-1]:.3f}', color, 2, color, 2, 0.7, box_type='xyxy')
62
63 return image
64

◆ vis_pose_coco_skeleton()

utils_vis.vis_pose_coco_skeleton ( image,
pose_results )
coco 스켈레톤을 시각화하는 기능
args:
    image (np.array): 이미지
    pose_results (list[dict] or dict): 스켈레톤 정보를 담고 'keypoints'가 포함된 데이터 리스트
return (np.array): coco 스켈레톤이 시각화된 이미지

Definition at line 65 of file utils_vis.py.

65def vis_pose_coco_skeleton(image, pose_results):
66 """
67 coco 스켈레톤을 시각화하는 기능
68 args:
69 image (np.array): 이미지
70 pose_results (list[dict] or dict): 스켈레톤 정보를 담고 'keypoints'가 포함된 데이터 리스트
71 return (np.array): coco 스켈레톤이 시각화된 이미지
72 """
73
74 #하나의 데이터일 경우 리스트로 감싸기
75 if not isinstance(pose_results, list):
76 pose_results = [pose_results]
77
78 #시각화
79 for pose in pose_results:
80 kps = pose['keypoints'] if pose['keypoints'].ndim == 2 else pose['keypoints'][0]
81 # kps[:, :2] += pose['bbox'][:2] #TODO: 크롭 이미지기반의 좌표일 경우 원본이미지 좌표로 이동, 옵션 처리 필요
82 image = vis_pose_coco_skeleton_one_person(image, kps)
83
84 return image
85

◆ vis_pose_coco_skeleton_one_person()

utils_vis.vis_pose_coco_skeleton_one_person ( image,
keypoints )
한명에 대한 coco 스켈레톤을 시각화 하는 기능
args:
    image (np.array): 이미지
    keypoints (np.array): 한명에 대한 스켈레톤 좌표, shape (17, 3)
return (np.array): 스켈레톤이 시각화된 이미지

Definition at line 86 of file utils_vis.py.

86def vis_pose_coco_skeleton_one_person(image, keypoints):
87 """
88 한명에 대한 coco 스켈레톤을 시각화 하는 기능
89 args:
90 image (np.array): 이미지
91 keypoints (np.array): 한명에 대한 스켈레톤 좌표, shape (17, 3)
92 return (np.array): 스켈레톤이 시각화된 이미지
93 """
94 # COCO ordered keypoints:
95 # 0:nose 1:left_eye 2:right_eye 3:left_ear 4:right_ear 5:left_shoulder
96 # 6:right_shoulder 7:left_elbow 8:right_elbow 9:left_wrist 10:right_wrist
97 # 11:left_hip 12:right_hip 13:left_knee 14:right_knee 15:left_ankle 16:right_ankle
98
99 # define connections between keypoints for COCO dataset
100 coco_pairs = [
101 (0, 1), (0, 2), (1, 3), (2, 4), # head
102 (5, 7), (7, 9), # left arm
103 (6, 8), (8, 10), # right arm
104 (5, 6), (5, 11), (6, 12), (11, 12), # body
105 (11, 13), (13, 15), # left leg
106 (12, 14), (14, 16) # right leg
107 ]
108
109 # define colors for different parts of the body
110 colors = {
111 'face': (255, 210, 127), # blue
112 'left_body': (0, 165, 255), # orange
113 'right_body': (0, 255, 0), # green
114 'body': (255, 210, 127) # blue
115 }
116
117 #스켈레톤에 대한 컬러맵
118 keypoint_colors = [colors['face']] * 5 + [colors['left_body'], colors['right_body']] * 6
119
120 #관절에 대한 컬러맵
121 pair_colors = [colors['face']] * 4 + [colors['left_body']] * 2 + [colors['right_body']] * 2 + \
122 [colors['body']] * 4 + [colors['left_body']] * 2 + [colors['right_body']] * 2
123
124
125 #관절 그리기
126 for i, pair in enumerate(coco_pairs):
127 kp1, kp2 = pair
128
129 #관절을 연결하는 두개의 스켈레톤의 스코어가 모두 0.5 이상일경우 그리기
130 if keypoints[kp1, 2] > 0.5 and keypoints[kp2, 2] > 0.5:
131 cv2.line(image, (int(keypoints[kp1, 0]), int(keypoints[kp1, 1])),
132 (int(keypoints[kp2, 0]), int(keypoints[kp2, 1])), pair_colors[i], 2)
133
134 #스켈레톤 그리기
135 for i, keypoint in enumerate(keypoints):
136 x, y, score = keypoint
137
138 #스켈레톤의 스코어가 0.5 이상이면 그리기
139 if score > 0.5:
140 cv2.circle(image, (int(x), int(y)), 5, keypoint_colors[i], thickness=-1, lineType=cv2.FILLED)
141
142 return image
143
144#TODO: 박스 그리는 함수들을 일반화 시킬 필요가 있음