# 1 - Imports and defining functions


```python
import numpy as np

from pyFM.mesh import TriMesh
from pyFM.functional import FunctionalMapping

import meshplot as mp

def plot_mesh(myMesh,cmap=None):
    mp.plot(myMesh.vertlist, myMesh.facelist,c=cmap)
    
def double_plot(myMesh1,myMesh2,cmap1=None,cmap2=None):
    d = mp.subplot(myMesh1.vertlist, myMesh1.facelist, c=cmap1, s=[2, 2, 0])
    mp.subplot(myMesh2.vertlist, myMesh2.facelist, c=cmap2, s=[2, 2, 1], data=d)

def visu(vertices):
    min_coord,max_coord = np.min(vertices,axis=0,keepdims=True),np.max(vertices,axis=0,keepdims=True)
    cmap = (vertices-min_coord)/(max_coord-min_coord)
    return cmap
```

## 2- Loading Data


```python
mesh1 = TriMesh('data/cat-00.off')
mesh2 = TriMesh('data/lion-00.off')
print(f'Mesh 1 : {mesh1.n_vertices:4d} vertices, {mesh1.n_faces:5d} faces\n'
      f'Mesh 2 : {mesh2.n_vertices:4d} vertices, {mesh2.n_faces:5d} faces')

double_plot(mesh1,mesh2)
```

# 3 - Computing the functional map

**Computing descriptors**


```python
process_params = {
    'n_ev': (35,35),  # Number of eigenvalues on source and Target
    'landmarks': np.loadtxt('data/landmarks.txt',dtype=int)[:5],  # loading 5 landmarks
    'subsample_step': 5,  # In order not to use too many descriptors
    'descr_type': 'WKS',  # WKS or HKS
}

model = FunctionalMapping(mesh1,mesh2)
model.preprocess(**process_params,verbose=True);
```

**Fitting the model**

$\newcommand{\RR}{\mathbb{R}}$
$\newcommand{\uargmin}[1]{\underset{#1}{\text{argmin}}\;}$
$\newcommand{\uargmax}[1]{\underset{#1}{\text{argmax}}\;}$
$\def\*#1{\mathbf{#1}}$

Optimization problem is
\begin{equation}
\uargmin{\*C\in\RR^{k_2\times k_1}} \mu_{descr}\|\*C\*A - \*B\|^2 + \mu_{lap}\|\*C\Delta_1 - \Delta_2\*C\|^2 + \mu_{\text{descr comm}}\sum_i \|\*C\Gamma_1^i - \Gamma_2^i\*C\|^2 + \mu_{\text{orient}}\sum_i \|\*C\Lambda_1^i - \Lambda_2^i\*C\|^2
\end{equation}

with $\Gamma_1^i$ and $\Gamma_2^i$ [multipliative operators](http://www.lix.polytechnique.fr/~maks/papers/fundescEG17.pdf) associated to the $i$-th descriptors, $\Lambda_1^i$ and $\Lambda_2^i$ [orientation preserving operators](https://arxiv.org/abs/1806.04455) associated to the $i$-th descriptors


```python
fit_params = {
    'descr_mu': 1e0,
    'lap_mu': 1e-2,
    'descr_comm_mu': 1e-1,
    'orient_mu': 0
}



model.fit(**fit_params, verbose=True)
```

**Visualizing the associated point to point map**


```python
p2p = model.p2p
cmap1 = visu(mesh1.vertlist); cmap2 = cmap1[p2p]
double_plot(mesh1,mesh2,cmap1,cmap2)
```

# 4 - Refining the Functional Map
```model.FM``` returns the current state of functional map. One can change which one is returned by using ```model.change_FM_type(FM_type)```, as one can see below. 

**ICP**


```python
model.icp_refine(verbose=True)
p2p = model.p2p
cmap1 = visu(mesh1.vertlist); cmap2 = cmap1[p2p]
double_plot(mesh1,mesh2,cmap1,cmap2)
```

**Zoomout**


```python
model.change_FM_type('classic') # We refine the first computed map, not the icp-refined one

model.zoomout_refine(nit=15, step = 1, verbose=True)
print(model.FM.shape)
p2p = model.p2p
cmap1 = visu(mesh1.vertlist); cmap2 = cmap1[p2p]
double_plot(mesh1,mesh2,cmap1,cmap2)
```

# Evaluating Results


```python
import pyFM.eval
```


```python
# Compute geodesic distance matrix on the cat mesh
A_geod = mesh1.get_geodesic(verbose=True)
```


```python
# Load an approximate ground truth map
gt_p2p = np.loadtxt('data/lion2cat',dtype=int)

model.change_FM_type('classic')
acc_base = pyFM.eval.accuracy(model.p2p, gt_p2p, A_geod, sqrt_area=np.sqrt(mesh1.area))

model.change_FM_type('icp')
acc_icp = pyFM.eval.accuracy(model.p2p, gt_p2p, A_geod, sqrt_area=np.sqrt(mesh1.area))

model.change_FM_type('zoomout')
acc_zo = pyFM.eval.accuracy(model.p2p, gt_p2p, A_geod, sqrt_area=np.sqrt(mesh1.area))

print(f'Accuracy results\n'
      f'\tBasic FM : {1e3*acc_base:.2f}\n'
      f'\tICP refined : {1e3*acc_icp:.2f}\n'
      f'\tZoomOut refined : {1e3*acc_zo:.2f}\n')
```

7320b3cbb4cbbb298289640fb4b258083921ed14
ipynb
Jupyter Notebook
example_notebook.ipynb
Yang-L1/pyFM
bfc9cf58da81441c13dbfe0645872e82b6038521
MIT
2020-09-10T14:27:37.000Z
2022-03-30T02:39:18.000Z
example_notebook.ipynb
Yang-L1/pyFM
bfc9cf58da81441c13dbfe0645872e82b6038521
MIT
2020-12-01T07:30:24.000Z
2020-12-03T08:19:57.000Z
example_notebook.ipynb
Yang-L1/pyFM
bfc9cf58da81441c13dbfe0645872e82b6038521
MIT
2021-02-15T10:56:23.000Z
2021-12-27T07:31:15.000Z
Qwen/Qwen-72B
1. YES
2. YES