2021-07-02 Minion tracking enhancements.
- Minion Tracking
- 이것저것 많이 건드려보았는데 미니언 트랙킹 자체가 변수가 많고 고려해야하는 경우의 수가 많아서 앞으로도 계속 보완해야 할 것 같음.
- 1) Centroid 거리 비교 고도화
- 기존의 방법은 scikit-image를 활용하여 얻은 미니언 웨이브마다의 centroid를 얻은 다음 단순히 centroid 사이의 거리를 바탕으로 교착상태인지 결정
- 미니언 웨이브의 크기와 미니언으로 간주된 챔피언 아이콘이 길게 늘어질 경우 centroid와 웨이브의 가장자리 지점까지의 거리가 멀어 centroid 비교로는 정확도가 떨어짐
-
Centroid의 거리에 각 웨이브의 major axis length의 절반(타원의 반지름으로 이해)만큼을 빼주어서 두 웨이브 사이의 최단 거리를 고려하는 방법으로 보완
def get_minion_lock(red_minion_map, blue_minion_map, dist_threshold=25): # Dilate kernel = np.ones((3,3), np.uint8) red_minion_map_di = cv2.dilate(red_minion_map.astype(np.uint8).copy(), kernel, iterations=1) blue_minion_map_di = cv2.dilate(blue_minion_map.astype(np.uint8).copy(), kernel, iterations=1) # Centroids red_labels = label(red_minion_map_di) red_centroids = [[np.array(prop.centroid), prop.major_axis_length] for prop in regionprops(red_labels)] blue_labels = label(blue_minion_map_di) blue_centroids = [[np.array(prop.centroid), prop.major_axis_length] for prop in regionprops(blue_labels)] lock_pts = [] for r_cen, r_len in red_centroids: for b_cen, b_len in blue_centroids: dist = np.linalg.norm(r_cen - b_cen) - r_len//2 - b_len//2 if dist < dist_threshold: lock_pts.append([int((r_cen[1]+b_cen[1])/2), int((r_cen[0]+b_cen[0])/2)]) return lock_pts
- 2) 라인별 교착 지점 분리
- 기존의 방법은 각 라인(탑, 미드, 정글)의 구분 없이 교착 상태를 따졌기 때문에 interpolation에 한계가 있었다
-
챔피언 아이콘에 의해 웨이브가 완전히 가려진 경우를 커버하기 위하여 우선 각 교착 지점을 라인별로 구분하였다.
def merge_graphs_to_each_line(lock_graph_dfs_itp, minimap_size): # merge graphs to each line (top, mid, bottom) sep_line_map = get_separate_line_map(minimap_size) top_graphs, mid_graphs, bot_graphs = [], [], [] for graph_df in lock_graph_dfs_itp: x, y = graph_df.iloc[0].astype(int) line_idx = sep_line_map[y,x] if line_idx == 1: top_graphs.append(graph_df) elif line_idx == 2: mid_graphs.append(graph_df) elif line_idx == 3: bot_graphs.append(graph_df) top_graphs, mid_graphs, bot_graphs = pd.concat(top_graphs), pd.concat(mid_graphs), pd.concat(bot_graphs) return top_graphs, mid_graphs, bot_graphs
- 3) 누락된 프레임 interpolation
- 챔피언 아이콘에 의해 웨이브가 완전히 가려진 경우, 이전에 챔피언 아이콘을 각 진영의 미니언 웨이브로 간주하는 방법으로 성능을 향상하였다.
- 하지만 한쪽 진영의 챔피언만 라인 상에 존재하여 남은 미니언을 클리어하는 경우에는 상대 미니언과 챔피언 아이콘 모두 존재하지 않기 때문에 직접적으로 해당 교착 지점을 찾는 것이 불가능하였다.
-
따라서 2)에서 각 라인별로 합친 교착 지점의 좌표들을 이용하여 위와 같은 상황으로 인하여 누락된 프레임에 대해서는 이전 프레임의 좌표값을 그대로 사용하는 방식을 사용하였다. (미니언 아이콘이 존재하는 좌표로 수정하는 방법도 고려 중)
def fillna_lock_frame(lock_graph_dfs_itp, minimap_size): top_graphs, mid_graphs, bot_graphs = merge_graphs_to_each_line(lock_graph_dfs_itp, minimap_size) lock_graph_dfs_itp_wo_na = [] for pts_df in [top_graphs, mid_graphs, bot_graphs]: # add NaN frame rows to Dataframe frame_idcs = pts_df.index pts_df_w_na = [] for idx in range(min(frame_idcs), max(frame_idcs)+1): try: pts_df_w_na.append(pts_df.loc[idx]) except: pts_df_w_na.append(pd.Series([np.nan, np.nan], name=idx)) pts_df_w_na = pd.concat(pts_df_w_na, 1).T # Interpolate the NaN frame rows pts_df_itp = pts_df_w_na.fillna(method='ffill') lock_graph_dfs_itp_wo_na.append(pts_df_itp) return lock_graph_dfs_itp_wo_na
-
4) 향상된 결과 시각화
- Champion Tracking
-
기존의 모델은 ‘죽은 챔피언까지 tracking해버리는 문제’ 발생 (아래 예시 참고)
-
해결된 영상
-
해결 방법
- 해당 프레임에 특정 챔피언이 죽은 상태라면 해당 챔피언에 대한 좌표값 제거
-
챔피언이 죽어있는지 여부는 양쪽의 챔피언 아이콘에 회색 빛이 돌고 부활시까지 걸리는 남은 시간이 표시되어 있을 경우를 인식 (아래 예시 참고. 미니맵만 고려하지 않는다는 이슈 존재)
-
Code
for frame in tqdm(frames, desc='Converting to CSV dataset...'): # Get current champion icon current_icons = get_all_icons_in_frame(frame) # Alive check is_alive = structural_similarity(icons[i], current_icons[i], multichannel=True) > 0.7 if is_alive: # Matching # Dead else: csv_row.extend([ID, -1000., -1000., position])
-