[open3d / reconstruction system (Tensor)] 4. Ray Casting in a Voxel Block Grid

About_work·2024년 9월 14일
0

SLAM

목록 보기
8/12

참고

본문

  • 레이캐스팅은 복셀 블록 그리드 내에서 특정 뷰포인트에서 깊이 및 컬러 이미지를 생성하는 데 사용할 수 있으며, 전체 표면을 추출하지 않아도 됩니다.
  • 이는 frame-to-model trackingdifferentiable volume rendering에 유용
  • Open3D에서는 최적화된 기존 렌더링미분 가능 렌더링에 사용될 수 있는 사용자 정의 렌더링을 위한 기본 지원을 제공
  • 예제는 examples/python/t_reconstruction_system/ray_casting.py에서 확인할 수 있습니다.

기존 렌더링(Conventional rendering)

  • TSDF 통합에서 복원된 복셀 블록 그리드 vbg를 사용하면 입력 깊이 값을 대략적인 범위 추정으로 하여 장면을 효율적으로 렌더링할 수 있습니다.
# examples/python/t_reconstruction_system/ray_casting.py
result = vbg.ray_cast(block_coords=frustum_block_coords,
                      intrinsic=intrinsic,
                      extrinsic=extrinsic,
                      width=depth.columns,
                      height=depth.rows,
                      render_attributes=[
                          'depth', 'normal', 'color', 'index',
                          'interp_ratio'
                      ],
                      depth_scale=config.depth_scale,
                      depth_min=config.depth_min,
                      depth_max=config.depth_max,
                      weight_threshold=1,
                      range_map_down_factor=8)

요약

  • 이 코드의 목적: vbg.ray_cast 함수는 카메라의 내부 및 외부 파라미터를 사용해 복셀 블록 그리드에서 장면을 렌더링합니다.

  • 레이캐스팅: 주어진 카메라 뷰포인트에서 복셀 블록을 투영하여 깊이, 색상, 표면 정보 등을 생성하는 과정입니다.

  • 인자의 역할: 카메라의 파라미터, 이미지 해상도, 렌더링할 속성 등을 지정하여 2D 이미지로 장면을 표현하는 데 사용됩니다.

  • 이 과정은 SLAM 시스템에서 현재 3D 모델의 상태를 카메라 뷰에서 어떻게 보이는지 계산하고 시각화하는 중요한 단계입니다.

  • 위 코드는 복셀 블록 그리드(Voxel Block Grid)에서 레이캐스팅(ray casting)을 수행하여 특정 뷰포인트에서 깊이, 색상, 표면 정보 등을 생성하는 과정입니다.

  • 기존 렌더링(Conventional rendering)이라는 용어는 Open3D에서 제공하는 표준적인 방식으로 복셀 블록 그리드를 시각화하는 방법을 의미합니다.

코드의 전체적인 흐름

  • 코드는 vbg.ray_cast 함수를 사용하여 복셀 블록 그리드(vbg)에서 특정 카메라 뷰(프러스텀)에서 볼 수 있는 장면을 렌더링

1. vbg.ray_cast 함수

result = vbg.ray_cast(block_coords=frustum_block_coords,
                      intrinsic=intrinsic,
                      extrinsic=extrinsic,
                      width=depth.columns,
                      height=depth.rows,
                      render_attributes=[
                          'depth', 'normal', 'color', 'index',
                          'interp_ratio'
                      ],
                      depth_scale=config.depth_scale,
                      depth_min=config.depth_min,
                      depth_max=config.depth_max,
                      weight_threshold=1,
                      range_map_down_factor=8)
  • 이 함수는 복셀 블록 그리드(vbg)를 주어진 카메라 뷰포인트에서 투영하여 렌더링을 수행합니다.

2. 인자별 설명

  • block_coords=frustum_block_coords:

    • frustum_block_coords
      • 현재 카메라 뷰(프러스텀) 내에 포함된 복셀 블록의 좌표
      • 이 좌표들은 이전에 계산된 것이며, 레이캐스팅을 통해 렌더링할 복셀 블록을 결정
  • width=depth.columns, height=depth.rows:

    • 생성될 이미지의 크기를 지정합니다.
    • depth.columnsdepth.rows는 깊이 이미지의 가로 및 세로 크기이며, 이를 통해 생성되는 렌더링 이미지의 해상도를 결정
  • render_attributes=[...]:

    • 어떤 속성을 렌더링할지 지정하는 리스트입니다.
    • 'depth': 각 픽셀에 대해 깊이 정보를 생성합니다.
    • 'normal': 표면의 법선 벡터를 계산하여 표면의 방향을 나타냄
    • 'color': 각 픽셀의 색상을 생성합니다.
    • 'index': 복셀의 인덱스 정보를 가져옵니다.
    • 'interp_ratio': 삼선형 보간을 위한 비율 값을 제공
  • depth_scale=config.depth_scale:

    • 깊이 값을 정규화할 때 사용하는 스케일 값입니다.
    • 깊이 이미지는 일반적으로 정수로 표현되기 때문에 이를 실수로 변환하여 정밀한 깊이 정보를 얻기 위해 사용합니다.
  • depth_min=config.depth_min, depth_max=config.depth_max:

    • 깊이 값의 최소 및 최대 범위를 지정합니다.
    • 이 값들은 너무 가까운 물체나 너무 먼 물체를 제외하여 렌더링의 효율성과 정확성을 높입니다.
  • weight_threshold=1:

    • TSDF 통합 시 계산된 가중치의 최소값을 설정
    • 이 값을 통해 노이즈가 많은 복셀을 필터링하고, 유효한 정보만 렌더링하는 데 사용
    • 중요!
  • range_map_down_factor=8:

    • 깊이 맵의 해상도를 줄이기 위한 다운샘플링 비율입니다.
    • 해상도를 줄여 렌더링 속도를 높이거나 메모리 사용을 최적화할 수 있습니다.

3. 결과와 반환값

  • result: 이 함수는 렌더링된 결과를 딕셔너리 형태로 반환합니다. 이 딕셔너리에는 'depth', 'normal', 'color'와 같은 렌더링된 속성들이 포함되어 있습니다.
    • 'depth': 렌더링된 깊이 맵.
    • 'normal': 표면의 법선 벡터 맵.
    • 'color': 컬러 이미지.
    • 'index', 'interp_ratio': 렌더링 중에 계산된 기타 정보.

이 결과를 바로 얻고 시각화할 수 있습니다:

# examples/python/t_reconstruction_system/ray_casting.py
fig, axs = plt.subplots(2, 2)
# 깊이 색상화
colorized_depth = o3d.t.geometry.Image(result['depth']).colorize_depth(
    config.depth_scale, config.depth_min, config.depth_max)
axs[0, 0].imshow(colorized_depth.as_tensor().cpu().numpy())
axs[0, 0].set_title('depth')

axs[0, 1].imshow(result['normal'].cpu().numpy())
axs[0, 1].set_title('normal')

axs[1, 0].imshow(result['color'].cpu().numpy())
axs[1, 0].set_title('color via kernel')

사용자 정의 렌더링(Customized rendering)

요약

  1. 복셀 색상 정보 가져오기: 복셀 블록 그리드에서 각 복셀의 색상 데이터를 추출합니다.
  2. 인덱스와 보간 비율 적용: 각 픽셀에 대응하는 복셀 인덱스와 보간 비율을 사용하여 색상을 계산합니다.
  3. 삼선형 보간: 8개의 인접한 복셀의 색상 값을 보간하여 최종 색상을 계산합니다.
  4. 시각화: 계산된 색상을 이미지로 시각화하여 사용자 정의 렌더링을 수행합니다.
  • 이 과정을 통해 복셀 블록 그리드 내의 데이터를 사용해 다양한 방식으로 이미지를 렌더링할 수 있으며, 딥러닝 프레임워크(PyTorch 등)와 함께 사용할 수 있습니다.
# examples/python/t_reconstruction_system/ray_casting.py
vbg_color = vbg.attribute('color').reshape((-1, 3))
nb_indices = result['index'].reshape((-1))
nb_interp_ratio = result['interp_ratio'].reshape((-1, 1))
nb_colors = vbg_color[nb_indices] * nb_interp_ratio
sum_colors = nb_colors.reshape((depth.rows, depth.columns, 8, 3)).sum(
    (2)) / 255.0
axs[1, 1].imshow(sum_colors.cpu().numpy())
axs[1, 1].set_title('color via indexing')
  • 출력이 인덱스를 통해 렌더링되기 때문에, 렌더링 프로세스는 DLPack 메모리 맵을 사용한 PyTorch I/O를 통해 미분 가능한 엔진(PyTorch 등)에서 원활하게 재작성될 수 있습니다.

  • 이 코드는 사용자 정의 렌더링을 통해 복셀 블록 그리드 내에 저장된 데이터를 사용해 이미지를 생성하는 과정
  • 특히, 각 픽셀에 대해 인접한 8개의 복셀의 정보를 가져와 삼선형 보간(trilinear interpolation)을 수행하여 이미지를 렌더링

1. 배경 지식: 삼선형 보간(Trilinear Interpolation)

  • 삼선형 보간은 3D 공간에서 8개의 인접한 복셀 값을 사용하여 특정 위치의 값을 추정하는 방법
  • 여기서는 이미지의 픽셀에 해당하는 3D 공간의 표면 색상을 계산하기 위해 사용됩니다.

2. 코드 분석

1. 복셀의 컬러 정보 가져오기

vbg_color = vbg.attribute('color').reshape((-1, 3))
  • vbg.attribute('color'): 복셀 블록 그리드(vbg)에서 각 복셀의 색상 정보를 가져옵니다.

2. 인덱스와 보간 비율 가져오기

nb_indices = result['index'].reshape((-1))
nb_interp_ratio = result['interp_ratio'].reshape((-1, 1))
  • result['index']: 이전에 레이캐스팅을 통해 얻은 각 픽셀의 표면 지점과 관련된 복셀 인덱스입니다. 이 인덱스는 어떤 복셀들이 표면에 가까운지를 나타냅니다.
  • result['interp_ratio']: 각 픽셀의 표면 지점에 대해 8개의 가장 가까운 이웃 복셀에 대한 보간 비율을 제공합니다. 보간 비율은 각 복셀의 색상이 최종 색상에 얼마나 영향을 미칠지를 나타냅니다.

3. 각 픽셀의 색상 계산

nb_colors = vbg_color[nb_indices] * nb_interp_ratio
sum_colors = nb_colors.reshape((depth.rows, depth.columns, 8, 3)).sum((2)) / 255.0
  • vbg_color[nb_indices]: 앞서 가져온 복셀 인덱스를 사용해 각 픽셀에 대응하는 복셀들의 색상 값을 가져옵니다.
  • * nb_interp_ratio: 보간 비율을 사용해 각 복셀의 색상 값을 가중합니다. 이 단계는 각 복셀의 색상이 얼마나 최종 색상에 영향을 줄지를 결정합니다.
  • sum_colors = nb_colors.reshape((depth.rows, depth.columns, 8, 3)).sum((2)) / 255.0:
    • .reshape((depth.rows, depth.columns, 8, 3)): 1차원 배열을 다시 4차원 배열로 변환합니다. 이 배열은 이미지의 각 픽셀에 대해 8개의 이웃 복셀과 각 복셀의 RGB 채널 값을 나타냅니다.
    • .sum((2)): 8개의 이웃 복셀의 색상 값을 모두 더하여 최종 색상을 계산합니다.
    • / 255.0: 색상 값을 정규화하여 0~1 범위로 만듭니다.

4. 결과 시각화

axs[1, 1].imshow(sum_colors.cpu().numpy())
axs[1, 1].set_title('color via indexing')
  • axs[1, 1].imshow(sum_colors.cpu().numpy()): 보간된 색상 결과를 이미지로 시각화합니다. 이때 sum_colors를 CPU로 이동하고 numpy 배열로 변환하여 이미지에 표시합니다.
  • .set_title('color via indexing'): 이미지의 제목을 설정하여 렌더링 방식을 나타냅니다.

3. 왜 이렇게 하는가?

  • 삼선형 보간: 각 픽셀에 대해 복셀 블록 그리드에서 8개의 인접한 복셀의 색상 값을 보간하여 더 부드러운 색상 표현을 얻기 위함입니다.
  • 사용자 정의 렌더링: Open3D에서 제공하는 기본적인 렌더링 방식을 확장하여, 사용자가 원하는 방식으로 렌더링할 수 있도록 지원합니다. 여기서는 색상 데이터를 사용자 정의 방식으로 추출하고 가공하는 예시를 보여줍니다.
profile
새로운 것이 들어오면 이미 있는 것과 충돌을 시도하라.

0개의 댓글