2 minute read

SuGaR์—์„œ Gaussians์ด ์–ด๋–ป๊ฒŒ Primitives (diamond ๋˜๋Š” square(=quad))๋กœ ๋ณ€ํ˜•๋˜๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.

SuGaR ๋ชจ๋ธ์—์„œ๋Š” Gaussian splats๋ฅผ ๋” ์ •๋ฐ€ํ•œ ๋‹ค๊ฐํ˜•(primitive polygon) ํ˜•ํƒœ๋กœ ๋Œ€์ฒดํ•˜์—ฌ 3D ํ‘œ๋ฉด์„ ๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

Gaussian splats๊ฐ€ ๋‹ค์ด์•„๋ชฌ๋“œ(diamond) ๋˜๋Š” ์‚ฌ๊ฐํ˜•(square) ํ˜•ํƒœ์˜ ๋‹ค๊ฐํ˜•์œผ๋กœ ๋ณ€ํ˜•๋˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ด…์‹œ๋‹ค.

๋‹ค์ด์•„๋ชฌ๋“œ์™€ ์‚ฌ๊ฐํ˜•์˜ ์ฐจ์ด์ 

๋‹ค์ด์•„๋ชฌ๋“œ์™€ ์‚ฌ๊ฐํ˜•์€ ์ •์ ์˜ ๊ฐœ์ˆ˜๋Š” ๊ฐ™์ง€๋งŒ, ์ •์ ์˜ ๋ฐฐ์—ด ๋ฐฉ์‹๊ณผ ๊ทธ์— ๋”ฐ๋ฅธ ๊ตฌ์กฐ๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋‹ค์ด์•„๋ชฌ๋“œ๋Š” ์ค‘์‹ฌ์„ ๊ธฐ์ค€์œผ๋กœ ์œ„์•„๋ž˜, ์ขŒ์šฐ๋กœ ๋ฐฐ์—ด๋œ ์ž…์ฒด์  ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์‚ฌ๊ฐํ˜•์€ ํ‰๋ฉด ์ƒ์—์„œ ๋„ค ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐฐ์—ด๋œ ํ‰๋ฉด์  ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์‚ฌ์šฉ๋œ square๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 3D ๊ทธ๋ž˜ํ”ฝ์Šค์—์„œ โ€œquadโ€๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์‚ฌ๊ฐํ˜•์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. quad๋Š” ๋„ค ๊ฐœ์˜ ์ •์ ์„ ๊ฐ€์ง„ ๋‹ค๊ฐํ˜•์„ ์˜๋ฏธํ•˜๋ฉฐ, ์ด ์ฝ”๋“œ์—์„œ๋Š” Gaussian splats๋ฅผ ๋Œ€์ฒดํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

sugar_model.py์—์„œ diamond์™€ sqaure primitive ์ •์˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ฉ๋‹ˆ๋‹ค.

# Primitive polygon that will be used to replace the gaussians
self.primitive_types = primitive_types
self._diamond_verts = torch.Tensor(
        [[0., -1., 0.], [0., 0, 1.], 
        [0., 1., 0.], [0., 0., -1.]]
        ).to(nerfmodel.device)
self._square_verts = torch.Tensor(
        [[0., -1., 1.], [0., 1., 1.], 
        [0., 1., -1.], [0., -1., -1.]]
        ).to(nerfmodel.device)

if primitive_types == 'diamond':
    self.primitive_verts = self._diamond_verts  # Shape (n_vertices_per_gaussian, 3)
elif primitive_types == 'square':
    self.primitive_verts = self._square_verts  # Shape (n_vertices_per_gaussian, 3)

self.primitive_triangles = torch.Tensor(
    [[0, 2, 1], [0, 3, 2]]
    ).to(nerfmodel.device).long()  # Shape (n_triangles_per_gaussian, 3)
self.primitive_border_edges = torch.Tensor(
    [[0, 1], [1, 2], [2, 3], [3, 0]]
    ).to(nerfmodel.device).long()  # Shape (n_edges_per_gaussian, 2)
self.n_vertices_per_gaussian = len(self.primitive_verts)
self.n_triangles_per_gaussian = len(self.primitive_triangles)
self.n_border_edges_per_gaussian = len(self.primitive_border_edges)
self.triangle_scale = triangle_scale

์ด๋ฅผ visualizeํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋ด…์‹œ๋‹ค.

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

# Convert tensors to numpy arrays
_diamond_verts = np.array([[0., -1., 0.], [0., 0, 1.], [0., 1., 0.], [0., 0., -1.]])
_square_verts = np.array([[0., -1., 1.], [0., 1., 1.], [0., 1., -1.], [0., -1., -1.]])

primitive_triangles = np.array([[0, 2, 1], [0, 3, 2]])
primitive_border_edges = np.array([[0, 1], [1, 2], [2, 3], [3, 0]])

# Function to plot vertices
def plot_vertices(vertices, ax, color='b'):
    ax.scatter(vertices[:, 0], vertices[:, 1], vertices[:, 2], color=color, s=100)

# Function to plot edges
def plot_edges(vertices, edges, ax, color='r'):
    for edge in edges:
        edge_verts = vertices[edge]
        ax.plot(edge_verts[:, 0], edge_verts[:, 1], edge_verts[:, 2], color=color)

# Function to plot triangles
def plot_triangles(vertices, triangles, ax, color='g'):
    for tri in triangles:
        tri_verts = vertices[tri]
        poly3d = [[tri_verts[0], tri_verts[1], tri_verts[2]]]
        ax.add_collection3d(Poly3DCollection(poly3d, facecolors=color, linewidths=1, edgecolors='k', alpha=.25))

# Plotting
fig = plt.figure(figsize=(18, 6))

# Plot diamond vertices and edges
ax1 = fig.add_subplot(131, projection='3d')
plot_vertices(_diamond_verts, ax1, color='b')
plot_edges(_diamond_verts, primitive_border_edges, ax1, color='r')
plot_triangles(_diamond_verts, primitive_triangles, ax1, color='g')
ax1.set_title('Diamond')
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')

# Plot square vertices and edges
ax2 = fig.add_subplot(132, projection='3d')
plot_vertices(_square_verts, ax2, color='b')
plot_edges(_square_verts, primitive_border_edges, ax2, color='r')
plot_triangles(_square_verts, primitive_triangles, ax2, color='g')
ax2.set_title('Square')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')

# Separate plot for _diamond_verts and _square_verts visualization
ax3 = fig.add_subplot(133, projection='3d')
plot_vertices(_diamond_verts, ax3, color='b')
plot_vertices(_square_verts, ax3, color='r')
ax3.set_title('Diamond (blue) and Square (red) Vertices')
ax3.set_xlabel('X')
ax3.set_ylabel('Y')
ax3.set_zlabel('Z')

plt.show()

image

์š”์•ฝ

  • ๋‹ค์ด์•„๋ชฌ๋“œ์™€ ์‚ฌ๊ฐํ˜•์˜ ์ •์  ๋ฐฐ์—ด ์ˆœ์„œ:
    • ๋‹ค์ด์•„๋ชฌ๋“œ๋Š” ์ค‘์•™์„ ๊ธฐ์ค€์œผ๋กœ ์œ„์•„๋ž˜, ์ขŒ์šฐ๋กœ ๋ฐฐ์—ด๋ฉ๋‹ˆ๋‹ค.
    • ์‚ฌ๊ฐํ˜•์€ ํ‰๋ฉด ์ƒ์—์„œ ๋„ค ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐฐ์—ด๋ฉ๋‹ˆ๋‹ค.
  • ํ˜•์„ฑ๋œ ๊ตฌ์กฐ:
    • ๋‹ค์ด์•„๋ชฌ๋“œ๋Š” ์ž…์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ์‚ฌ๊ฐํ˜•(quad)์€ ํ‰๋ฉด์ ์ธ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ๋Š” ์ •์ ์˜ ๋ฐฐ์—ด ์ˆœ์„œ์™€ ๊ทธ์— ๋”ฐ๋ฅธ ์‚ผ๊ฐํ˜•์˜ ๋ฐฐ์น˜๊ฐ€ ๋‹ฌ๋ผ์„œ ์„œ๋กœ ๋‹ค๋ฅธ ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Gaussian splats๋ฅผ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋” ์ •๋ฐ€ํ•˜๊ณ  ๋ณต์žกํ•œ 3D ๋ชจ๋ธ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Leave a comment