frame-to-model tracking
및 differentiable volume rendering
에 유용최적화된 기존 렌더링
과 미분 가능 렌더링
에 사용될 수 있는 사용자 정의 렌더링을 위한 기본 지원을 제공
examples/python/t_reconstruction_system/ray_casting.py
에서 확인할 수 있습니다.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
)에서 특정 카메라 뷰(프러스텀)에서 볼 수 있는 장면을 렌더링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
)를 주어진 카메라 뷰포인트에서 투영하여 렌더링을 수행합니다. block_coords=frustum_block_coords
:
frustum_block_coords
는 width=depth.columns, height=depth.rows
:
depth.columns
와 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
:
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')
# 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 등)에서 원활하게 재작성될 수 있습니다.사용자 정의 렌더링
을 통해 복셀 블록 그리드 내에 저장된 데이터를 사용해 이미지를 생성하는 과정vbg_color = vbg.attribute('color').reshape((-1, 3))
vbg.attribute('color')
: 복셀 블록 그리드(vbg
)에서 각 복셀의 색상 정보를 가져옵니다.nb_indices = result['index'].reshape((-1))
nb_interp_ratio = result['interp_ratio'].reshape((-1, 1))
result['index']
: 이전에 레이캐스팅을 통해 얻은 각 픽셀의 표면 지점과 관련된 복셀 인덱스입니다. 이 인덱스는 어떤 복셀들이 표면에 가까운지를 나타냅니다.result['interp_ratio']
: 각 픽셀의 표면 지점에 대해 8개의 가장 가까운 이웃 복셀에 대한 보간 비율을 제공합니다. 보간 비율은 각 복셀의 색상이 최종 색상에 얼마나 영향을 미칠지를 나타냅니다.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 범위로 만듭니다.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')
: 이미지의 제목을 설정하여 렌더링 방식을 나타냅니다.