3 minute read

Gaussian Splatting์„ ํ†ตํ•œ surface mesh ๋ฐ”์ธ๋”ฉ ๋ฐฉ๋ฒ•

์ด ๋ฌธ์„œ๋Š” SuGaR ๋ชจ๋ธ์—์„œ Gaussian splats๋ฅผ surface mesh์— ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๊ณผ์ •์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. SuGaR ๋ชจ๋ธ์—์„œ Gaussian splats๋Š” ์ ๋“ค๋กœ ๊ตฌ์„ฑ๋œ 3D ๊ณต๊ฐ„์ƒ์˜ ๊ฐ์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ด ์ ๋“ค์ด ํŠน์ • ํ‘œ๋ฉด์— ๋ฐ”์ธ๋”ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์€ ๋ชจ๋ธ์˜ ํ•™์Šต๊ณผ ๋ Œ๋”๋ง ํ’ˆ์งˆ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.

๋ฐ”์ธ๋”ฉ ๊ณผ์ •

SuGaR ๋ชจ๋ธ์—์„œ๋Š” surface mesh์˜ ๊ฐ triangle(=face)์— ํŠน์ • ๊ฐœ์ˆ˜์˜ Gaussian splats๋ฅผ ํ• ๋‹นํ•˜์—ฌ ํ‘œ๋ฉด์˜ ํ˜•ํƒœ์™€ ํ…์Šค์ฒ˜๋ฅผ ๋ณด๋‹ค ์ •๋ฐ€ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ๊ฐ๊ธฐ ๋‹ค๋ฅธ n_gaussians_per_surface_triangle ๊ฐ’์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ”์ธ๋”ฉ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

์šฉ์–ด ์ •๋ฆฌ

  • triangle: surface mesh๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. ๊ฐ ์‚ผ๊ฐํ˜•์€ ์„ธ ๊ฐœ์˜ ๊ผญ์ง€์ ์„ ๊ฐ€์ง€๋ฉฐ, ์ด ๊ผญ์ง€์ ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ณ€์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • face: SuGaR์—์„œ๋Š” face๊ฐ€ surface mesh์˜ triangle๊ณผ ๋™์ผํ•œ ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. (์ฆ‰, SuGaR์—์„œ๋Š” face = triangle)
    • face์˜ ์ข…๋ฅ˜:
      • triangle (์‚ผ๊ฐํ˜•): ์„ธ ๊ฐœ์˜ ๊ผญ์ง€์ ๊ณผ ์„ธ ๊ฐœ์˜ ๋ณ€์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
      • Qaud (์‚ฌ๊ฐํ˜•): ๋„ค ๊ฐœ์˜ ๊ผญ์ง€์ ๊ณผ ๋„ค ๊ฐœ์˜ ๋ณ€์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
      • Polygon (๋‹ค๊ฐํ˜•): ๋‹ค์„ฏ ๊ฐœ ์ด์ƒ์˜ ๊ผญ์ง€์ ๊ณผ ๋ณ€์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, pentagon(์˜ค๊ฐํ˜•), hexagon(์œก๊ฐํ˜•) ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • Surface Mesh: ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์‚ผ๊ฐํ˜•์œผ๋กœ ๊ตฌ์„ฑ๋œ 3D ๋ชจ๋ธ์˜ ํ‘œ๋ฉด์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

sugar_model.py์—์„œ ๊ฐ triangle๋งˆ๋‹ค Gaussian Splats์€ ๋ฌด๊ฒŒ์ค‘์‹ฌ(barycentric coordinates)์„ ํ™œ์šฉํ•˜์—ฌ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

1. 1๊ฐœ์˜ Gaussian splat per ์‚ผ๊ฐํ˜•

๊ฐ ์‚ผ๊ฐํ˜•์˜ ๋ฌด๊ฒŒ์ค‘์‹ฌ์„ ์‚ฌ์šฉํ•˜์—ฌ Gaussian splat์„ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‹จ์ผ Gaussian splat์ด ์‚ผ๊ฐํ˜•์˜ ์ „์ฒด๋ฅผ ๋Œ€ํ‘œํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

if n_gaussians_per_surface_triangle == 1:
    self.surface_triangle_circle_radius = 1. / 2. / np.sqrt(3.)
    self.surface_triangle_bary_coords = torch.tensor(
        [[1/3, 1/3, 1/3]],
        dtype=torch.float32,
        device=nerfmodel.device,
    )[..., None]

2. 3๊ฐœ์˜ Gaussian splats per ์‚ผ๊ฐํ˜•

๊ฐ ์‚ผ๊ฐํ˜•์˜ ์ค‘์‹ฌ๊ณผ ๊ฐ ๋ชจ์„œ๋ฆฌ์— ๊ฐ€๊นŒ์šด ์œ„์น˜์— Gaussian splats๋ฅผ ๋ฐฐ์น˜ํ•˜์—ฌ ์‚ผ๊ฐํ˜•์„ ๋ณด๋‹ค ์ •๋ฐ€ํ•˜๊ฒŒ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

if n_gaussians_per_surface_triangle == 3:
    self.surface_triangle_circle_radius = 1. / 2. / (np.sqrt(3.) + 1.)
    self.surface_triangle_bary_coords = torch.tensor(
        [[1/2, 1/4, 1/4],
        [1/4, 1/2, 1/4],
        [1/4, 1/4, 1/2]],
        dtype=torch.float32,
        device=nerfmodel.device,
    )[..., None]

3. 4๊ฐœ์˜ Gaussian splats per ์‚ผ๊ฐํ˜•

์ค‘์‹ฌ๊ณผ ๊ฐ ๋ชจ์„œ๋ฆฌ์— ๋”ํ•ด, ์‚ผ๊ฐํ˜• ๋‚ด๋ถ€์˜ ๋‹ค๋ฅธ ๋‘ ์ ์—๋„ Gaussian splats๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

if n_gaussians_per_surface_triangle == 4:
    self.surface_triangle_circle_radius = 1 / (4. * np.sqrt(3.))
    self.surface_triangle_bary_coords = torch.tensor(
        [[1/3, 1/3, 1/3],
        [2/3, 1/6, 1/6],
        [1/6, 2/3, 1/6],
        [1/6, 1/6, 2/3]],
        dtype=torch.float32,
        device=nerfmodel.device,
    )[..., None]  # n_gaussians_per_face, 3, 1

4. 6๊ฐœ์˜ Gaussian splats per ์‚ผ๊ฐํ˜•

๋”์šฑ ์ด˜์ด˜ํ•˜๊ฒŒ ์‚ผ๊ฐํ˜• ๋‚ด๋ถ€์— Gaussian splats๋ฅผ ๋ฐฐ์น˜ํ•˜์—ฌ ์‚ผ๊ฐํ˜•์„ ๋”์šฑ ์ •๋ฐ€ํ•˜๊ฒŒ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

if n_gaussians_per_surface_triangle == 6:
    self.surface_triangle_circle_radius = 1 / (4. + 2.*np.sqrt(3.))
    self.surface_triangle_bary_coords = torch.tensor(
        [[2/3, 1/6, 1/6],
        [1/6, 2/3, 1/6],
        [1/6, 1/6, 2/3],
        [1/6, 5/12, 5/12],
        [5/12, 1/6, 5/12],
        [5/12, 5/12, 1/6]],
        dtype=torch.float32,
        device=nerfmodel.device,
    )[..., None]

๊ฒฐ๋ก 

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์„ ํ†ตํ•ด ๋ชจ๋ธ์€ surface mesh์˜ ๋””ํ…Œ์ผ์„ ๋ณด๋‹ค ์ž˜ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Gaussian splats์˜ ์ˆ˜์™€ ๋ฐฐ์น˜ ๋ฐฉ๋ฒ•์„ ์กฐ์ ˆํ•จ์œผ๋กœ์จ ๋ชจ๋ธ์˜ ํ‘œํ˜„๋ ฅ์„ ์œ ์—ฐํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์€ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ชจ๋ธ์˜ ํ•™์Šต๊ณผ ๋ Œ๋”๋ง ํ’ˆ์งˆ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.


sugar_model.py์—์„œ surface_mesh์— binding๋œ ๋ชจ๋“  gaussian๋“ค์˜ densities ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•

if self.binded_to_surface_mesh and (not learn_surface_mesh_opacity):
            all_densities = inverse_sigmoid(0.9999 * torch.ones((n_points, 1), dtype=torch.float, device=points.device))
            self.learn_opacities = False
        else:
            all_densities = inverse_sigmoid(0.1 * torch.ones((n_points, 1), dtype=torch.float, device=points.device))
        self.all_densities = nn.Parameter(all_densities, 
                                     requires_grad=self.learn_opacities).to(nerfmodel.device)
        self.return_one_densities = False

ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช… ๋ฐ ์—ญํ• 

  • self.binded_to_surface_mesh: Gaussian๋“ค์ด surface mesh์— ๋ฐ”์ธ๋”ฉ๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • learn_surface_mesh_opacity: surface mesh์— ์กด์žฌํ•˜๋Š” Gaussian๋“ค์˜ ๋ถˆํˆฌ๋ช…๋„(opacity)๋ฅผ ํ•™์Šตํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆํˆฌ๋ช…๋„๋ฅผ ํ•™์Šตํ•˜์ง€ ์•Š์œผ๋ฉด, ๋ถˆํˆฌ๋ช…๋„ ๊ฐ’์ด ๊ณ ์ •๋œ ์ฑ„๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

Gaussian๋“ค์ด surface_mesh์— binding ๋˜์–ด์žˆ๋Š”์ง€ ์—ฌ๋ถ€์™€ surface_mesh_opacity ํ•™์Šต ์—ฌ๋ถ€์— ๋”ฐ๋ฅธ ๋ชจ๋“  gaussian๋“ค์˜ densities ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•

  • CASE 1: self.binded_to_surface_mesh๊ฐ€ ์ฐธ์ด๊ณ  learn_surface_mesh_opacity๊ฐ€ ๊ฑฐ์ง“์ผ ๋•Œ
    if self.binded_to_surface_mesh and (not learn_surface_mesh_opacity):
      all_densities = inverse_sigmoid(0.9999 * torch.ones((n_points, 1), dtype=torch.float, device=points.device))
      self.learn_opacities = False
    
    • surface mesh์— ๋ฐ”์ธ๋”ฉ๋˜์–ด ์žˆ๊ณ , surface mesh์˜ opacity๋ฅผ ํ•™์Šตํ•˜์ง€ ์•Š๋„๋ก ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ๋ชจ๋“  Gaussian๋“ค์˜ density๊ฐ’์€ 0.9999๋กœ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ์—ญ ์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋˜์–ด ๋งค์šฐ ํฐ ์–‘์˜ ๊ฐ’์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ€๋„๊ฐ€ ๋งค์šฐ ๋†’์€ ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  ๊ฐ€์šฐ์‹œ์•ˆ๋“ค์˜ densities ๊ฐ’์„ ๋งค์šฐ ๋†’์€ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ํ‘œ๋ฉด์ด ๊ฑฐ์˜ ์™„์ „ํ•˜๊ฒŒ ๋ถˆํˆฌ๋ช…ํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
      • ์˜๋ฏธ: Gaussian๋“ค์ด surface mesh์— ๊ณ ์ •๋˜์–ด ์žˆ์œผ๋ฉฐ, Gaussian๋“ค์˜ opacities ๊ฐ’๋“ค์ด ํ•™์Šตํ•  ํ•„์š”๊ฐ€ ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • CASE 2: ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ (Gaussian๋“ค์ด surface mesh์— ๋ฐ”์ธ๋”ฉ๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜, surface mesh์— ์กด์žฌํ•˜๋Š” Gaussian๋“ค์˜ opacity๋ฅผ ํ•™์Šตํ•˜๋Š” ๊ฒฝ์šฐ)
    else:
      all_densities = inverse_sigmoid(0.1 * torch.ones((n_points, 1), dtype=torch.float, device=points.device))
      self.learn_opacities = True
    
    • Gaussian๋“ค์ด surface mesh์— ๋ฐ”์ธ๋”ฉ๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜, surface mesh์— ์กด์žฌํ•˜๋Š” Gaussian๋“ค์˜ ๋ถˆํˆฌ๋ช…๋„(opacity)๋ฅผ ํ•™์Šตํ•˜๋„๋ก ์„ค์ •๋œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ๋ชจ๋“  Gaussian๋“ค์˜ density๊ฐ’์€ 0.1๋กœ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ์—ญ ์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋˜์–ด ์Œ์˜ ๊ฐ’์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ€๋„๊ฐ€ ๋‚ฎ์€ ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰. ๋ชจ๋“  Gaussian๋“ค์˜ densities ๊ฐ’์„ ๋‚ฎ์€ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ Gaussian๋“ค์˜ opacities๋ฅผ ํ•™์Šตํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
      • ์˜๋ฏธ: Gaussian๋“ค์ด surface mesh์— ๊ณ ์ •๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉฐ, Gaussian๋“ค์˜ opacieties ๊ฐ’๋“ค์ด ํ•™์Šต์„ ํ†ตํ•ด ์กฐ์ •๋  ํ•„์š”๊ฐ€ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

image

Leave a comment