Notebook source code:
notebooks/how_to/13_rematching.ipynb
Run it yourself on binder
How to use ReMatching to compute a functional map?#
In [1]:
import gsops.backend as gs
from geomfum.dataset import NotebooksDataset
from geomfum.refine import ZoomOut
from geomfum.shape import TriangleMesh
from geomfum.shape.hierarchical import HierarchicalMesh
In [2]:
dataset = NotebooksDataset()
mesh_a = TriangleMesh.from_file(dataset.get_filename("cat-00"))
mesh_b = TriangleMesh.from_file(dataset.get_filename("lion-00"))
(mesh_a.n_vertices, mesh_a.n_faces), (mesh_b.n_vertices, mesh_b.n_faces)
Out [2]:
((7207, 14410), (5000, 9996))
Create hierarchical meshes.
In [3]:
hmesh_a = HierarchicalMesh.from_registry(mesh_a, min_n_samples=1000)
hmesh_b = HierarchicalMesh.from_registry(mesh_b, min_n_samples=1000)
(
(hmesh_a.low.n_vertices, hmesh_a.low.n_faces),
(hmesh_b.low.n_vertices, hmesh_b.low.n_faces),
)
Out [3]:
((1004, 2004), (1021, 2038))
Set Laplace eigenbasis for each low-resolution mesh.
In [4]:
hmesh_a.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
hmesh_b.low.laplacian.find_spectrum(spectrum_size=10, set_as_basis=True)
hmesh_a.low.basis.use_k = 6
hmesh_b.low.basis.use_k = 5
Extend the basis for the high-resolution meshes.
In [5]:
hmesh_a.extend_basis(set_as_basis=True)
hmesh_b.extend_basis(set_as_basis=True)
(
hmesh_a.high.basis.vecs.shape,
hmesh_b.high.basis.vecs.shape,
)
Out [5]:
((7207, 10), (5000, 10))
Assume we have a valid functional map \(C\) between hmesh_a.low and hmesh_b.low (which for demonstration purposes, we instantiate randomly).
In [6]:
fmap_matrix = gs.random.uniform(
size=(
hmesh_b.low.basis.spectrum_size,
hmesh_a.low.basis.spectrum_size,
)
)
fmap_matrix.shape
Out [6]:
(5, 6)
Now, this functional map can be seamlessly used with the high-resolution meshes. For example, we can upsample it with ZoomOut.
In [7]:
upsampler = ZoomOut(nit=2, step=(2, 1))
upsampled_fmap_matrix = upsampler(
fmap_matrix,
hmesh_a.high.basis,
hmesh_b.high.basis,
)
upsampled_fmap_matrix.shape
Out [7]:
(7, 10)
In [8]:
hmesh_a.high.basis.vecs
Out [8]:
array([[-1.72157991, 1.63091261, -1.05690336, ..., 2.67648666,
-1.04742672, -0.71500848],
[-1.72157991, 1.70083536, -0.86500711, ..., 2.84924518,
-1.43599688, -0.51465914],
[-1.72157991, 1.69559836, -0.84127265, ..., 2.87933207,
-1.4351918 , -0.82635609],
...,
[-1.72157991, 5.0574198 , 6.82858863, ..., -3.77463283,
6.36453632, -0.21060378],
[-1.72157991, 5.06379084, 6.84460851, ..., -3.8108807 ,
6.45896302, -0.21374222],
[-1.72157991, 1.63753198, -1.00536459, ..., 2.71484979,
-1.10020252, -1.01029031]], shape=(7207, 10))
NB: mesh_a and hmesh_a.high are the same object, so it is indiferent which one to use.