[nuscenes] BEV map 만드는 법

ad_official·2025년 2월 21일

[AD] dataset

목록 보기
4/12

1. static BEV map

1.0. 3가지 방법 비교

항목get_map_mask()render_map_patch()render_layers()
출력 타입NumPy 배열(Figure, List[Axes])(Figure, Axes)
출력 Shape / 캔버스 크기(C, H, W): C = 선택한 layer 수, H×W = canvas_size
예: (2, 1000, 1000)
각 Axes에 (H, W) 형태의 이미지
예: (1000, 1000)
전체 지도 영역을 커버하는 Axes
예: [0, map_edge_x]×[0, map_edge_y]
데이터 타입uint8 (binary)uint8 (RGB)uint8 (RGB)
색상 지정별도 채널로 사용자 정의 필요기본 색상 자동 적용사용자 정의 색상 가능
좌표계패치 중심 상대 좌표계글로벌 맵 좌표계글로벌 맵 좌표계
렌더링 방식프로그래매틱 마스크 생성Matplotlib 기반 래스터화Matplotlib 기반 계층 합성
성능100×100m @500px → 약 15ms100×100m @500px → 약 450ms전체 맵 렌더링 → 약 1200ms
사용 목적 / 주요 활용 사례레이어별 이진 마스크 생성 (ML 모델 입력 등 학습용)patch_box와 patch_angle에 따른 지도 영역 시각화 (결과 리포트용)여러 지도 layer를 전역 지도 위에 오버레이하여 전체 BEV 맵 시각화 (연구/실험용)


1.1. get_map_mask

  • 출력:
    • NumPy 배열
    • shape: (C, H, W)
      • C: 선택한 layer 개수 (예: ['drivable_area', 'walkway'] → 2 채널)
      • H, W: 지정한 canvas_size (예: (1000, 1000))
  • 예시 코드:
# get_map_mask 예시
patch_box = (300, 1700, 100, 100)  # [x_center, y_center, height, width]
patch_angle = 0  # North-up
layer_names = ['drivable_area', 'walkway']
canvas_size = (1000, 1000)

# get_map_mask는 binary mask들을 채널별로 쌓은 numpy 배열을 반환합니다.
map_mask = nusc_map.get_map_mask(patch_box, patch_angle, layer_names, canvas_size)
print("get_map_mask output shape:", map_mask.shape)
# 예: (2, 1000, 1000)


1.2. render_map_patch

  • 출력:
    • (Figure, List[Axes]) 튜플
    • 내부적으로는 get_map_mask를 사용하여 각 layer별 mask (shape: (H, W))를 subplot에 그립니다.
  • 참고:
    • 각 subplot에 표시되는 이미지는 (canvas_size[0], canvas_size[1]) 즉, (1000, 1000) 형태의 2차원 배열(채널별로 하나씩)입니다.
  • 예시 코드:
# render_map_patch 예시
fig_patch, axes_patch = nusc_map.render_map_patch(patch_box, patch_angle, layer_names,
                                                  canvas_size=canvas_size, figsize=(12, 4), n_row=1)
# 내부적으로 각 축(subplot)은 (1000, 1000) 이미지(하나의 mask 채널)를 표시합니다.
print("Each rendered map patch channel shape:", map_mask[0].shape)
# 예: (1000, 1000)
  • render_map_patch() 함수는 지정된 patch 영역에 대해, 각 layer의 mask 이미지를 matplotlib의 서브플롯으로 시각화합니다.

  • fig_patch: 전체 그림(figure) 객체입니다.

    • 타입: matplotlib.figure.Figure
    • 역할: 여러 subplot(axes)을 포함하는 전체 그림 캔버스로, 이 객체를 통해 그림 전체의 저장, 표시 등이 가능합니다.
  • axes_patch: 개별 subplot에 해당하는 축(axes)들의 리스트입니다.

    • 타입: list (각 원소의 타입은 matplotlib.axes.Axes)
    • 역할: 각 subplot에 해당하는 개별 축으로, 여기에는 각 layer별 mask 이미지가 표시됩니다.
      • 보통 Axes 자체는 이미지 데이터가 아니라 전체 Figure의 일부이지만, 해당 Axes의 “bounding box” 영역을 추출하면 그 영역에 그려진 RGB 이미지로 변환할 수 있습니다.
      • 일반적으로 변환한 결과의 shape는 (H, W, 3)이며, 여기서 H와 W는 그 Axes가 렌더링된 픽셀 높이와 너비를 의미합니다.


PNG 이미지로 저장하는 방법

반환된 figure를 PNG 파일로 저장하려면 fig_patch.savefig() 메서드를 사용하면 됩니다.

# 예: PNG 파일로 저장
fig_patch.savefig('map_patch.png', dpi=300, bbox_inches='tight')


Numpy Array로 변환하는 방법

figure 전체를 numpy 배열로 변환하는 두 가지 방법이 있습니다.

방법 1: 캔버스 버퍼 사용하기

# 먼저 canvas에 그리기
fig_patch.canvas.draw()

# 캔버스의 RGB 데이터를 가져오기
import numpy as np
img_array = np.frombuffer(fig_patch.canvas.tostring_rgb(), dtype=np.uint8)
width, height = fig_patch.canvas.get_width_height()
img_array = img_array.reshape((height, width, 3))

방법 2: BytesIO와 PIL 사용하기

import io
from PIL import Image

buf = io.BytesIO()
fig_patch.savefig(buf, format='png', dpi=300, bbox_inches='tight')
buf.seek(0)
img = Image.open(buf)
img_array = np.array(img)



1.3. render_layers

  • 출력:
    • (Figure, Axes) 튜플
    • Axes는 전체 지도 영역(글로벌 캔버스)에 여러 layer(예, 'lane' 등)를 오버레이한 결과를 보여줍니다.
  • 참고:
    • 이 경우 실제 numpy 배열을 직접 반환하지 않고, matplotlib의 시각화 결과(figure와 axis)를 반환합니다.
    • 축의 x, y 범위는 지도 JSON에 저장된 canvas_edge 값에 따라 결정됩니다.
  • 예시 코드:
# render_layers 예시
fig_layers, ax_layers = nusc_map.render_layers(['lane', 'road_segment'], alpha=0.5, figsize=(15, 15))
# 예: ax_layers의 x축, y축 범위는 지도 전체 (예: singapore-onenorth의 경우)
print("render_layers canvas x-range:", ax_layers.get_xlim())
print("render_layers canvas y-range:", ax_layers.get_ylim())



2.

profile
ad_official

0개의 댓글