Ca avance bien 👍

Co-authored-by: Laureηt <laurent@fainsin.bzh>
Co-authored-by: pejour <pejour@users.noreply.github.com>
This commit is contained in:
gdamms 2023-02-01 11:51:01 +01:00
parent 5cbb0d31ac
commit 4384319a03
3 changed files with 164 additions and 147 deletions

View file

@ -20,81 +20,116 @@ title: Bureau d'étude de PI3D
---
## Exemple Level sets 2D
## Plan du BE
<div class="h-100 flex items-center text-2xl">
- Définitions
- L'idée générale
- Hyposthèses
- L'algorithme
- Résultats
</div>
<!--
Notre objectif dans ce BE c'était donc d'implémenter ce procédé.
Et pour ce faire on avait besoin de faire les étapes suivantes:
- Définitions
1. Level sets
2. MVS
- L'idée générale
- Hyposthèses
1. Discrétisation de l'espace
2. Binarisation du levelset
- L'algorithme
1. Initialisation du volume
2. Mise à jour du volume
- Résultats
-->
---
## Définition
### Level sets
<img src="/figs/lvl7_2D.gif" class="m-auto"/>
$\mathcal{V} = \{ \textbf{Q} = (X, Y) \in \mathbb{R}^2, u(\textbf{Q}) > s \}, \quad s\in [0,1], \quad u \colon \mathbb{R}^2 \to [0, 1]$
<img src="/figs/lvl7_2D.gif" class="m-auto mt-5"/>
<!--
level set ≃ un seuillage. \
Ici on représente le seuillage d'une fonction par un contour rouge, avec le resultat binarisé à droite.
Ça fait un peu penser aux contours actifs, et on peut considérer les levels sets comme une généralisation des contours actifs.
-->
---
## Définition du Level sets (2D)
<style>
span.katex {
position: absolute;
bottom: 5%;
left: 8%;
}
</style>
<img src="/figs/wikipedia_top.png" class="m-auto -mt-12"/>
<img src="/figs/wikipedia_bottom.png" class="m-auto -mt-12"/>
$\mathcal{V}_t = \{ \textbf{Q} = (X, Y) \in \mathbb{R}^2, u(\textbf{Q}) > t \}, \quad t\in [0,1], \quad u \colon \mathbb{R}^2 \to [0, 1]$
<a href="https://en.wikipedia.org/wiki/Level-set_method" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Wikipedia</a>
<!--
Définition mathématique et continue des levels sets:
Volume = Ensemble des points de l'espace tel que, l'image de ces points par une fonction valide une condition
- V_t -> volume (2D ici, gris en bas) que l'on souhaite obtenir/approximer
- V -> volume (2D ici, noir à droite)
- Q -> point 2D de l'espace
- u -> fonction indicatrice (que l'on souhaite apprendre) qui indique "l'intériorité" d'un point Q dans V_t
- t -> seuil qui détermine la valeur à partir de laquelle on est dans V_t
Pour un levelset 2D, on peut représenter u en 3D, t par un plan, et notre volume V_t par tout ce qui se situe au dessus du plan t.
- u -> fonction indicatrice (que l'on souhaite apprendre) qui indique "l'intériorité" d'un point Q dans V
- s -> seuil qui détermine la valeur à partir de laquelle on est dans V
-->
---
## Exemple Level sets 3D
### Exemple Level sets 3D
<img src="/figs/lvl7_3D.gif" class="m-auto -mt-1 h-125"/>
<div class="flex items-center">
<img src="/figs/lvl7_3D.gif" class="h-110"/>
<figure>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/MarchingCubes.svg/350px-MarchingCubes.svg.png" class="h-50">
<figcaption class="text-center">Marching cubes</figcaption>
</figure>
</div>
<!--
La définition précédente se généralise très bien aux espace de dimension supérieurs, voici un exemple 3D.
Juste on vous parle de la 2D psk c'est plus simple.
Par exemple ici on peut pas représenter u, car il nous faudrait une représentation 4D.
Par contre on peut vous montrer le résultat de V_t pour différent t.
En ce qui concerne le rendu de la surface 3D, on utilise l'ago de marching cubes.
-->
---
## Évolution de $u_t$
## Définition
### Multi-view Stereo
<img src="/figs/lvl7_2D_1.png" class="m-auto h-110"/>
<img src="https://people.inf.ethz.ch/~moswald/publications/resources/Oswald-DA-2007.png" class="m-auto h-105"/>
<a href="https://people.inf.ethz.ch/~moswald/publications/resources/Oswald-DA-2007.pdf" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Concurrent Stereo Reconstruction, Martin R. Oswald, 2007</a>
<!--
MVS -> reconstruction 3D à partir des positions des caméras et de leur image.
-->
---
## L'idée générale
### Évolution de $u$
<img src="/figs/lvl7_2D_1.png" class="m-auto h-100"/>
<a href="https://hal.inria.fr/inria-00073673/document" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Variational principles, surface evolution, PDEs, level set methods, and the stereo problem - Olivier Faugeras, Renaud Keriven, 1998</a>
<!--
Faugeras et Keriven ont écrit ce "livre" pour poser pleins de preuves mathématiques sur des problèmes variationnels... dont les levels sets.
Et donc dans le leur "livre" ils montrent plusieurs exemples de levels sets.
Ils montrent un procédé pour mettre à jour u_t (le contour bleu) pour que celui-ci converge vers un volume capturé (le contour rouge) par des caméras (dont les poses sont connues).
Ils montrent un procédé pour mettre à jour u (le contour bleu) pour que celui-ci converge vers un volume capturé (le contour rouge) par des caméras (dont les poses sont connues).
-->
---
## Évolution de $u_t$
## L'idée générale
### Évolution de $u$
<img src="/figs/lvl7_2D_2.png" class="m-auto h-110"/>
<img src="/figs/lvl7_2D_3.png" class="m-auto h-100"/>
<a href="https://hal.inria.fr/inria-00073673/document" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Variational principles, surface evolution, PDEs, level set methods, and the stereo problem - Olivier Faugeras, Renaud Keriven, 1998</a>
@ -104,35 +139,10 @@ changement de topologie du level set
---
## Évolution de $u_t$
## Hypothèses
### Discrétisation de l'espace
<img src="/figs/lvl7_2D_3.png" class="m-auto h-110"/>
<a href="https://hal.inria.fr/inria-00073673/document" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Variational principles, surface evolution, PDEs, level set methods, and the stereo problem - Olivier Faugeras, Renaud Keriven, 1998</a>
---
## Plan du BE
<div class="h-100 flex items-center text-2xl">
- Discrétisation de l'espace
- Initialisation du volume
- Mise à jour du volume
- Résultats
</div>
<!--
Notre objectif dans ce BE c'était donc d'implémenter ce procédé.
Et pour ce faire on avait besoin de faire les étapes suivantes:
-->
---
## Discrétisation de l'espace <br> Simplification du problème
<img src="https://upload.wikimedia.org/wikipedia/commons/b/bc/Voxels.svg" class="m-auto mr-50 -mt-13 h-110">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/bc/Voxels.svg" class="m-auto mr-50 -mt-13 h-100">
<style>
span.katex {
@ -141,8 +151,9 @@ span.katex {
}
</style>
$\mathbb{R}^3 \to \mathbb{V} \newline \implies \mathcal{V} = \{ \textbf{v} = (x, y, z) \in \mathbb{V}, u(\textbf{v}) > 0 \}, \quad u \colon \mathbb{V} \to \{0, 1\}$
### Binarisation du levelset
$\mathbb{R}^3 \to \mathbb{V} \newline \implies \mathcal{V} = \{ \textbf{v} = (x, y, z) \in \mathbb{V}, u(\textbf{v}) > 0 \}, \quad u \colon \mathbb{V} \to \{0, 1\}$
<a href="https://en.wikipedia.org/wiki/Voxel" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Wikipedia</a>
@ -155,7 +166,8 @@ Et donc t on va aussi le définir égal à 0.
---
## Initialisation du volume
## L'algorithme
### Initialisation du volume
- Définition des bornes de notre grille de voxels:
- $x \in \llbracket x_{\min}, x_{\max} \rrbracket$
@ -175,6 +187,57 @@ Comme on l'a vu dans les exemple de Faugeras, il nous faut un u_0 initial (le co
---
## L'algorithme
### Principe du Shape from Silhouette
<img src="https://www.researchgate.net/profile/Silvio-Savarese/publication/221625880/figure/fig1/AS:652956261158913@1532688312594/Shape-from-Silhouettes-The-silhouette-and-camera-location-for-each-view-forms-a-cone.png" class="m-auto h-105">
<a href="https://ieeexplore.ieee.org/document/1024034" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Implementation of a Shadow Carving System for Shape Capture, doi: 10.1109/TDPVT.2002.1024034</a>
<!--
On suppose qu'on connait les poses de plusieurs caméras, ainsi que les masques de l'objet qu'elles capturent.
On va prendre tous les voxels de notre grille et les projeter sur chacune de nos caméras.
Si on voxel tombe à l'exterieur du masque d'au moins d'une caméra, on le supprime.
Il en résulte l'enveloppe convexe de l'objet (nuage de points / voxels).
Plus on a de caméra, meilleure sera la définition de l'enveloppe.
-->
---
### Shape from Silhouette 3D
<div class="flex items-center">
<img src="/figs/example3D.gif" class="m-auto h-110">
<iframe frameborder="0" allowfullscreen mozallowfullscreen="true" webkitallowfullscreen="true" allow="autoplay; fullscreen; xr-spatial-tracking" xr-spatial-tracking execution-while-out-of-viewport execution-while-not-rendered web-share width="100%" height="100%" src="https://sketchfab.com/models/4da17838dd5f497faa147db5febd21d9/embed"></iframe>
</div>
<!--
25 poses, torus avec briques, génération blender, masques parfait par render raytracing (cycles).
nuage de voxel. si nuage de points -> conversion en mesh possible grace aux marching cubes.
-->
---
## L'algorithme
### Lancer de rayon (Fast Voxel Intersect)
<div class="grid grid-cols-2 col-auto w-110 m-auto">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141883810914427/fvi2.png" class="m-auto h-55"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141884242931712/fvi4.png" class="m-auto h-55"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141884679147602/fvi6.png" class="m-auto h-55"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141885056622661/fvi8.png" class="m-auto h-55"/>
</div>
---
### Shape from Silhouette 2D
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069974891023056926/image.png" class="m-auto -mt-2 h-110">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069974281175449630/image.png" class="m-auto -mt-1 h-11">
---
## Mise à jour du volume
<img src="/figs/update.png" class="m-auto h-120">
@ -191,91 +254,42 @@ Comme on l'a vu dans les exemple de Faugeras, il nous faut un u_0 initial (le co
---
## Principe du Shape from Silhouette
<img src="https://www.researchgate.net/profile/Silvio-Savarese/publication/221625880/figure/fig1/AS:652956261158913@1532688312594/Shape-from-Silhouettes-The-silhouette-and-camera-location-for-each-view-forms-a-cone.png" class="m-auto mt-2 h-110">
<a href="https://ieeexplore.ieee.org/document/1024034" class="absolute bottom-0 font-extralight mb-1 mr-2 right-0 text-xs">Implementation of a Shadow Carving System for Shape Capture, doi: 10.1109/TDPVT.2002.1024034</a>
<!--
On suppose qu'on connait les poses de plusieurs caméras, ainsi que les masques de l'objet qu'elles capturent.
On va prendre tous les voxels de notre grille et les projeter sur chacune de nos caméras.
Si on voxel tombe à l'exterieur du masque d'au moins d'une caméra, on le supprime.
Il en résulte l'enveloppe convexe de l'objet (nuage de points / voxels).
Plus on a de caméra, meilleure sera la définition de l'enveloppe.
-->
---
## Shape from Silhouette 3D
<img src="/figs/example3D.gif" class="m-auto mt-2 h-110">
<!--
25 poses, torus avec briques, génération blender, masques parfait par render raytracing (cycles).
-->
---
## Résultat Shape from Silhouette 3D
<iframe frameborder="0" allowfullscreen mozallowfullscreen="true" webkitallowfullscreen="true" allow="autoplay; fullscreen; xr-spatial-tracking" xr-spatial-tracking execution-while-out-of-viewport execution-while-not-rendered web-share width="100%" height="100%" src="https://sketchfab.com/models/4da17838dd5f497faa147db5febd21d9/embed"></iframe>
<!--
nuage de voxel. si nuage de points -> conversion en mesh possible grace aux marching cubes.
-->
---
## Shape from Silhouette 2D
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069974891023056926/image.png" class="m-auto -mt-2 h-110">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069974281175449630/image.png" class="m-auto -mt-1 h-11">
---
## Résultat Shape from Silhouette 2D
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069973956263686164/Screenshot_from_2023-01-31_14-30-53.png" class="m-auto h-110">
---
## Lancer <br> de rayon
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141883810914427/fvi2.png" class="m-auto -mt-10 h-125"/>
---
## Lancer <br> de rayon
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141884242931712/fvi4.png" class="m-auto -mt-10 h-125"/>
---
## Lancer <br> de rayon
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141884679147602/fvi6.png" class="m-auto -mt-10 h-125"/>
---
## Lancer <br> de rayon
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1068141885056622661/fvi8.png" class="m-auto -mt-10 h-125"/>
---
## Itération du Level Set
<div class="flex">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069973956787966003/Screenshot_from_2023-01-31_14-33-47.png" class="h-110">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069975888382410784/image.png" class="h-110">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069973956787966003/Screenshot_from_2023-01-31_14-33-47.png" class="h-110">
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1069975888382410784/image.png" class="h-110">
</div>
---
## Résultats (TODO)
## Résultats
### L'environnement
<img src="https://media.tenor.com/_NuHtjgRyvcAAAAC/kekw.gif" class="m-auto h-100">
<!-- TODO -->
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070291885823889408/peanut.png"/>
---
## Résultats
### Les données
<!-- TODO: mettre les cams a guache et les mask et imagesa droite les unes sur les autres -->
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070293528288165930/peanut_cams.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292853282054225/Image0000.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292853495975988/Image0010.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292853764407306/Image0020.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292923322744903/Image0000.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292923549224980/Image0010.png"/>
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070292923754741770/Image0020.png"/>
---
## Résultats
### L'initialisation (Shape from Silhouette)
<img src="https://cdn.discordapp.com/attachments/953586522572066826/1070287482186383450/init.png" class="m-auto h-120">
---
@ -286,5 +300,6 @@ nuage de voxel. si nuage de points -> conversion en mesh possible grace aux marc
- Réalisation du SfS en 2D/3D
- Réalisation du MVS par level sets en 2D avec utilisation du SfS
- Résultat en 3D ?
- Passer en continu au lieu de binaire
</div>

View file

@ -58,7 +58,8 @@ for i in range(nb_cams):
plt.xlim(-7, 7)
plt.ylim(-7, 7)
plt.axis("equal")
plt.savefig("data/peanut/peanut.png", dpi=300,
plt.axis("off")
plt.savefig("data/peanut/peanut_cams.png", dpi=300,
bbox_inches="tight", pad_inches=0, transparent=True)
plt.close()

View file

@ -112,6 +112,7 @@ Z = Z.T
plt.figure()
plt.axis("equal")
plt.axis("off")
plot_voxels(Z, "#fff", 1.0, True)
plot_voxels(voxel, "#00f", 0.5, False)
for i in range(nb_frame):
@ -233,7 +234,7 @@ for p in range(11):
occurences = [[x, values.count(x)] for x in set(values)]
occurences = sorted(occurences, key=lambda x: x[1], reverse=True)
if occurences[0][1] >= len(values) * 0.68:
if occurences[0][1] >= len(values) * 0.7:
voxel_[i, j] = 1
color = "#0f0"
else:
@ -258,13 +259,13 @@ for p in range(11):
voxel = voxel_
plt.savefig(f"evol{p}.png", dpi=300, bbox_inches="tight", pad_inches=0, transparent=True)
plt.savefig(f"evol{p:02}.png", dpi=300, bbox_inches="tight", pad_inches=0, transparent=True)
plt.figure()
plt.axis("equal")
plot_voxels(Z, "#fff", 1.0, True)
plot_voxels(voxel, "#00f", 0.5, False)
plt.savefig(f"shape{p}.png", dpi=300, bbox_inches="tight", pad_inches=0, transparent=True)
plt.savefig(f"shape{p:02}.png", dpi=300, bbox_inches="tight", pad_inches=0, transparent=True)
plt.close("all")
# plt.show()