<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>http://os-vps418.infomaniak.ch:1250/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lheote</id>
	<title>Wiki du LAMA (UMR 5127) - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="http://os-vps418.infomaniak.ch:1250/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lheote"/>
	<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Sp%C3%A9cial:Contributions/Lheote"/>
	<updated>2026-06-10T10:05:05Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Filage_d%27image_et_trac%C3%A9_de_droites_pour_un_rendu_artistique&amp;diff=16917</id>
		<title>Filage d&#039;image et tracé de droites pour un rendu artistique</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Filage_d%27image_et_trac%C3%A9_de_droites_pour_un_rendu_artistique&amp;diff=16917"/>
		<updated>2026-05-10T21:14:38Z</updated>

		<summary type="html">&lt;p&gt;Lheote : /* Résultats finaux */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Projet réalisé dans le cadre du cours [[VISI201_CMI_:_visite_de_laboratoire]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Étudiants :&#039;&#039;&#039; [http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Utilisateur:Goralczyk Goralczyk Elliot], [http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Utilisateur:Lheote Lhéoté Anaïs]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tuteur :&#039;&#039;&#039; [https://jacquesolivierlachaud.github.io/ Jacques-Olivier Lachaud]&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Un [https://en.wikipedia.org/wiki/String_art filage] d&#039;image est la reproduction d&#039;une image à partir de clous sur une planche et d&#039;un fil noir pour retracer l&#039;image. &lt;br /&gt;
Lors de ce projet, nous avons reproduit cette technique artistique à l&#039;aide de Python pour voir jusqu&#039;où nous pourrions pousser la ressemblance avec une image donnée, tout en gardant l&#039;esprit du filage.&lt;br /&gt;
Pour cela nous avons dû comprendre le principe en lui-même, et nous avons ensuite élaboré plusieurs techniques pour parvenir au meilleur résultat possible.&lt;br /&gt;
&lt;br /&gt;
= Placer les clous =&lt;br /&gt;
&lt;br /&gt;
Pour commencer un filage, il nous faut avant tout une planche et des clous.&lt;br /&gt;
&lt;br /&gt;
Le placement des clous va définir l&#039;ensemble des droites qu&#039;il va nous être possible de tracer. Par exemple, les quatre clous gris sur l&#039;image ci-dessous permettent de tracer uniquement les six droites en rouge.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-importance-palcement-clous.png|center|100px]]&lt;br /&gt;
&lt;br /&gt;
Il est donc important de bien placer les clous pour obtenir un résultat satisfaisant.&lt;br /&gt;
Nous avons utilisé trois techniques différentes pour placer les clous au cours de ce projet.&lt;br /&gt;
&lt;br /&gt;
=== Représentation d&#039;un clou ===&lt;br /&gt;
&lt;br /&gt;
Avant de pouvoir placer un clou, il faut savoir comment le représenter.&lt;br /&gt;
Nous avons fait le choix de le représenter par un triplet : (coordonnée x, coordonnée y, côté).&lt;br /&gt;
Le côté est utilisé pour déterminer si il est possible de relier deux clous ; on considère qu&#039;on ne peut pas relier deux clous situés d&#039;un même côté.&lt;br /&gt;
Un clou est donc associé à un pixel de l&#039;image, et l&#039;ensemble de ces clous est stocké dans une liste.&lt;br /&gt;
&lt;br /&gt;
=== Faire le tour de l&#039;image ===&lt;br /&gt;
&lt;br /&gt;
Notre première approche a été de simplement placer des clous tous les 10 pixels autour de l&#039;image.&lt;br /&gt;
Cela permet d&#039;avoir de nombreuses possibilités pour tracer les droites, et de pouvoir atteindre une grande majorité des pixels de l&#039;image.&lt;br /&gt;
&lt;br /&gt;
L&#039;inconvénient de cette méthode est que les droites vont forcément d&#039;un bord à l&#039;autre de l&#039;image, et ne peuvent pas s&#039;arrêter au milieu, ce qui réduit les possibilités de représenter des détails.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple au ralenti de la génération de clous avec cette approche, sur une image carrée de 101 pixels de côté :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Generation-clous-autour-de-l-image.gif|center|202px]]&lt;br /&gt;
&lt;br /&gt;
=== Placer des clous aléatoires ===&lt;br /&gt;
&lt;br /&gt;
Pour pallier au problème de ne pas pouvoir arrêter une droite ailleurs que sur un bord, nous avons décider de rajouter des clous dont la position a été générée aléatoirement.&lt;br /&gt;
Pour ce faire, nous générons aléatoirement pour chaque clou sa coordonnée x (respectivement : y) un nombre entre 20 et la longueur (respectivement : hauteur) de l&#039;image - 20, pour qu&#039;ils ne soient pas trop près du bord.&lt;br /&gt;
Étant donné qu&#039;un clou au centre de l&#039;image doit pouvoir être relié à tous les autres, nous incrémentons à chaque clou la valeur de son côté, pour que chacun des clous générés aléatoirement ait un côté différent.&lt;br /&gt;
&lt;br /&gt;
Cette méthode permet d&#039;obtenir plus de détails, mais leur qualité repose sur des variables entièrement aléatoires, ce qui n&#039;est pas idéal.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple au ralenti de la génération de clous avec cette approche, sur une image carrée de 101 pixels de côté, avec 20 clous aléatoires : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Generation-clous-aleatoires.gif|center|202px]]&lt;br /&gt;
&lt;br /&gt;
=== Utiliser les contours ===&lt;br /&gt;
&lt;br /&gt;
Afin d&#039;obtenir des images plus détaillées, nous souhaitons placer les clous autour formes visibles dans nos images.&lt;br /&gt;
Cela permettra de mieux en délimiter les contours, et donc de les faire ressortir et de les dessiner plus fidèlement.&lt;br /&gt;
Pour y parvenir, nous utilisons un système de probabilités.&lt;br /&gt;
Cela signifie que chaque pixel possède un poids, et que plus ce poids est grand, plus il est probable que ce pixel soit choisi.&lt;br /&gt;
&lt;br /&gt;
Pour déterminer ce poids, nous utilisons de la détection de contours. En utilisant un filtre sur une image (dans notre cas le filtre [https://github.com/python-pillow/Pillow/blob/main/src/PIL/ImageFilter.py#L327 FIND_EDGES] de la bibliothèque Python [https://github.com/python-pillow/Pillow/ Pillow]), on peut obtenir une image sur laquelle les contours des formes de l&#039;image de départ ressortent en blanc, et le reste en noir, comme sur l&#039;exemple ci-dessous.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Filtre-laplacien.png|center]]&lt;br /&gt;
&lt;br /&gt;
Nous pouvons ensuite déterminer les probabilités à partir de cette image.&lt;br /&gt;
Pour ce faire, on commence par récupérer la valeur de chaque pixel de l&#039;image dans une matrice de dimension (h, l), avec h la hauteur en pixels de l&#039;image, et l sa longueur.&lt;br /&gt;
La valeur d&#039;un pixel dans une image en nuances de gris correspond à sa luminosité : 0 correspond au noir, 255 au blanc, et 127 à un gris moyen.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple d&#039;une image en niveaux de gris et de la matrice correspondante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-passage-pixels-matrice.png|center]]&lt;br /&gt;
&lt;br /&gt;
À partir de cette matrice, on va créer une matrice de dimension identique, dans lequel chaque élément sera la somme de la valeur du pixel correspondant dans la matrice précédente et la valeur de l&#039;élément précédent.&lt;br /&gt;
&lt;br /&gt;
Voici ce que donnerait cette nouvelle matrice en reprenant l&#039;exemple précédent :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-passage-pixels-matrice-somme-cumulative.png|center]]&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons cette matrice, nous pouvons générer un nombre aléatoire situé entre 0 et la dernière valeur de la matrice que nous allons appeler r.&lt;br /&gt;
Il ne nous reste plus qu&#039;à parcourir la matrice jusqu&#039;à tomber sur un nombre plus grand que r.&lt;br /&gt;
Les coordonnées de ce nombre dans la matrice, et donc celles du pixel auquel il est associé seront associées à un nouveau clou.&lt;br /&gt;
Par exemple, si on obtient r = 268, un clou sera placé en bas à gauche, car le nombre en bas à gauche de la deuxième matrice est le premier à être plus grand que 268.&lt;br /&gt;
&lt;br /&gt;
Plus des pixels seront des contours marqués, plus ils seront clairs une fois le filtre appliqué. Ils auront donc plus de chances d&#039;être tirés au sort, comme illustré ci-dessous.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-probas-pixels-laplacien.png|center]]&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;à placer autant de clous que l&#039;on veut, et nous avons notre liste de clous.&lt;br /&gt;
Nous ne plaçons pas manuellement de clous sur le bord de l&#039;image avec cette méthode, et la notion de &amp;quot;côté&amp;quot; est peu utile ; on considère que tous les clous peuvent-être reliés entre eux, chaque clou possède donc un &amp;quot;côté&amp;quot; différent.&lt;br /&gt;
&lt;br /&gt;
= Trouver la droite à tracer =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nos clous sont placés, il faut savoir lesquels relier entre eux.&lt;br /&gt;
Nous aurons toujours un clou de départ, qui pour la première droite sera le premier clou de la liste, et pour les droites suivantes, le clou d&#039;arrivée de la dernière droite tracée.&lt;br /&gt;
&lt;br /&gt;
=== Mesurer la différence entre deux images ===&lt;br /&gt;
&lt;br /&gt;
Pour décider à quel clou nous devons relier notre clou de départ, nous commençons par choisir aléatoirement une liste de clous à tester.&lt;br /&gt;
On garde aléatoirement la moitié des clous, pour diviser par deux le nombre de calculs, tout en gardant un grand nombre de possibilités.&lt;br /&gt;
&lt;br /&gt;
Pour chacun de ces clous, on calcule la liste des pixels que la droite allant du clou de départ à ce clou d&#039;arrivée traverse.&lt;br /&gt;
On compare ensuite pour chaque pixel de cette liste sa valeur dans notre image résultat provisoire et dans l&#039;image de départ en niveau de gris.&lt;br /&gt;
En faisant la somme de la valeur absolue de la différence entre les valeurs de chaque pixel de notre liste sur les deux images, et en la divisant par le nombre de pixels de la droite, on obtient la valeur de la différence moyenne par pixel entre les deux images.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple illustré, en calculant la différence sur les quatres pixels des images :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-calcul-difference-images.png|center]]&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons calculé cette différence, il faut calculer la différence que l&#039;on obtiendrait si la droite était tracée.&lt;br /&gt;
On répète donc les opérations précédentes, en modifiant la valeur des pixels de notre image résultat provisoire.&lt;br /&gt;
On soustrait à cette nouvelle différence le résultat obtenu précédemment, et cela nous donne la valeur de la réduction moyenne de la différence par pixel que l&#039;on obtiendrait si on traçait la droite.&lt;br /&gt;
Plus ce résultat est faible, plus la droite rapproche notre résultat de l&#039;image de départ. Si ce résultat est positif, cela signifie que notre résultat s&#039;éloigne de l&#039;image originale.&lt;br /&gt;
&lt;br /&gt;
On observe par exemple que si on assombrit le pixel en haut à gauche de l&#039;image de droite, la différence entre les deux images va diminuer, et l&#039;image de droite va donc se rapprocher de celle de gauche :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-calcul-difference-images-2.png|center]]&lt;br /&gt;
&lt;br /&gt;
La différence entre l&#039;image de gauche et celle de droite diminue donc d&#039;une valeur de 77 - 32 = 45 par pixel en moyenne.&lt;br /&gt;
&lt;br /&gt;
On calcule donc ce résultat pour toutes nos droites, et on trouve le clou qui réduit le plus l&#039;erreur.&lt;br /&gt;
On trace donc une droite jusqu&#039;à ce clou, puis on cherche de nouveau le meilleur clou, et ainsi de suite. Mais alors, à quel moment faut-il s&#039;arrêter ?&lt;br /&gt;
&lt;br /&gt;
=== La condition d&#039;arrêt ===&lt;br /&gt;
&lt;br /&gt;
Dans note implémentation de cet algorithme, nous avons fait le choix de s&#039;arrêter lorsque la meilleure droite éloigne notre résultat de l&#039;image de départ trois fois d&#039;affilé.&lt;br /&gt;
Nous n&#039;arrêtons pas dès que le résultat s&#039;éloigne car il arrive souvent qu&#039;une droite qui éloigne notre résultat de l&#039;image de départ permette ensuite de tracer une meilleure droite, qui va améliorer notre résultat.&lt;br /&gt;
&lt;br /&gt;
= Tracer la droite =&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir trouver la meilleure droite, encore faut-il savoir par quels pixels cette droite passe.&lt;br /&gt;
&lt;br /&gt;
=== Représenter une image ===&lt;br /&gt;
&lt;br /&gt;
Et avant de savoir par quels pixels elle passe, il faut d&#039;abord représenter ces pixels.&lt;br /&gt;
&lt;br /&gt;
Durant ce projet, nous avons travaillé uniquement sur des images en niveaux de gris, nous représentons donc une image par une matrice de dimension identique à cette image, dans laquelle chaque élément de la matrice représente un pixel, comme vu dans la partie précédente.&lt;br /&gt;
Pour importer une image, on la convertit donc en niveaux de gris, puis on récupère la valeur de chaque pixel pour en faire une matrice.&lt;br /&gt;
Pour créer une image blanche, on crée une matrice de la taille souhaitée et on initialise touts les valeurs à 255, la valeur du blanc.&lt;br /&gt;
&lt;br /&gt;
=== Calculer la liste des pixels traversés ===&lt;br /&gt;
&lt;br /&gt;
Pour connaître la liste des pixels traversés par une droite, on utilise son équation de type y = ax + b où y est une ordonnée (une coordonnée y), x une abscisse (une coordonnée x), a le coefficient directeur de la droite, et b son ordonnée à l&#039;origine (la valeur de y quand x vaut 0).&lt;br /&gt;
&lt;br /&gt;
Pour calculer les valeurs a et b, on utilise les coordonnées des deux points (des deux clous) que la droite traverse.&lt;br /&gt;
On nomme x1 et y1 les coordonnées du clou de départ, et x2 et y2 le coordonnées du clou d&#039;arrivée.&lt;br /&gt;
Excepté le cas des droites verticales, on a a = (y2 - y1) / (x2 - x1) et b = y1 - x1 * a .&lt;br /&gt;
&lt;br /&gt;
Deux cas apparaissent alors, celui dans lequel a appartient à [-1, 1], et celui dans lequel il n&#039;est pas dedans.&lt;br /&gt;
Dans le premier cas, la droite va être plus proche de l&#039;axe des abscisses que de l&#039;axe des ordonnées, et inversement dans le second cas.&lt;br /&gt;
&lt;br /&gt;
Voici quelques exemples :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-intervalle-a.png|center]]&lt;br /&gt;
&lt;br /&gt;
On peut observer que dans le premier cas (en bleu), il y a plusieurs pixels par ligne, et un seul par colonne, et inversement dans le deuxième cas (en rouge).&lt;br /&gt;
&lt;br /&gt;
On traite donc ces deux cas différemment :&lt;br /&gt;
&lt;br /&gt;
- Dans le premier cas, on détermine y pour chaque valeur de x entre x1 et x2 grâce au résultat de l&#039;opération ax + b que l&#039;on arrondit pour obtenir les coordonnées d&#039;un pixel.&lt;br /&gt;
&lt;br /&gt;
- Dans le second cas, on détermine x pour chaque valeur de y entre y1 et y2 grâce au résultat de l&#039;opération (y - b) / a que l&#039;on arrondit également.&lt;br /&gt;
&lt;br /&gt;
Dans le cas des droites verticales, a n&#039;est pas défini car il faudrait diviser par 0. On fabrique donc la liste de pixels en laissant la coordonnée x constante, et en ajoutant toutes les coordonnées y entre y1 et y2.&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons notre liste de pixel, on modifie la valeur de chaque pixel dans la liste pour tracer la droite.&lt;br /&gt;
Nous avons fait le choix de modifier de 51 la valeur des pixels, pour obtenir 6 niveaux de gris qui sont du plus foncé au plus clair : 255 -&amp;gt; 204 -&amp;gt; 153 -&amp;gt; 102 -&amp;gt; 51 -&amp;gt; 0.&lt;br /&gt;
&lt;br /&gt;
=== Utiliser le format SVG ===&lt;br /&gt;
&lt;br /&gt;
Pour obtenir un résultat moins pixelisé, nous utilisons le format [https://fr.wikipedia.org/wiki/Scalable_Vector_Graphics SVG].&lt;br /&gt;
Ce format est un format vectoriel, ce qui signifie qu&#039;il ne stocke pas des pixels mais des formes et leurs coordonnées.&lt;br /&gt;
Cela permet de pouvoir zoomer sur une image sans percevoir les pixels.&lt;br /&gt;
&lt;br /&gt;
Nous utilisons ce format uniquement pour le résultat, les calculs utilisent toujours des matrices de pixels.&lt;br /&gt;
Afin de rester cohérents avec les six niveaux de gris, les droites tracées ont une opacité de 20%.&lt;br /&gt;
&lt;br /&gt;
Voici une comparaison de la même image de 10 pixels de côté en PNG à gauche, et en SVG à droite :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Comparaison-png-svg.png|center]]&lt;br /&gt;
&lt;br /&gt;
= Évolution de l&#039;algorithme =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Résultats finaux =&lt;br /&gt;
Après de nombreux essais, voici les résultats que nous obtenons en utilisant le laplacien pour tracer nos droites, des clous qui sont sur le contour de l&#039;image et le svg pour un résultat plus net. &lt;br /&gt;
&lt;br /&gt;
Photographie du hibou:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Hiboux_original.png|360px|left]]&lt;br /&gt;
[[Fichier:Hiboux_svg.png|360px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Photographie de Louciane:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Louciane_originale.jpg|360px|left]]&lt;br /&gt;
[[Fichier:Louciane_svg.png|360px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Photographie des pommes:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Pommes_originale.jpg|left]] [[Fichier:Pomme_svg.png|360px|right]]&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Pommes_originale.jpg&amp;diff=16910</id>
		<title>Fichier:Pommes originale.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Pommes_originale.jpg&amp;diff=16910"/>
		<updated>2026-05-10T20:58:18Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Photographie originale des pommes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Photographie originale des pommes.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Louciane_originale.jpg&amp;diff=16909</id>
		<title>Fichier:Louciane originale.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Louciane_originale.jpg&amp;diff=16909"/>
		<updated>2026-05-10T20:57:39Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Photographie originale de notre camarade.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Photographie originale de notre camarade.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hibou_original.png&amp;diff=16908</id>
		<title>Fichier:Hibou original.png</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hibou_original.png&amp;diff=16908"/>
		<updated>2026-05-10T20:56:36Z</updated>

		<summary type="html">&lt;p&gt;Lheote : /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Photographie originale du hibou.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hibou_original.png&amp;diff=16907</id>
		<title>Fichier:Hibou original.png</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hibou_original.png&amp;diff=16907"/>
		<updated>2026-05-10T20:56:07Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Photographie originale du hiboux.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Photographie originale du hiboux.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Pomme_svg.png&amp;diff=16906</id>
		<title>Fichier:Pomme svg.png</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Pomme_svg.png&amp;diff=16906"/>
		<updated>2026-05-10T20:52:14Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Rendu final de la photo des pommes en svg, et utilisant le laplacien.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Rendu final de la photo des pommes en svg, et utilisant le laplacien.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Louciane_svg.png&amp;diff=16905</id>
		<title>Fichier:Louciane svg.png</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Louciane_svg.png&amp;diff=16905"/>
		<updated>2026-05-10T20:51:36Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Rendu final de la photo de notre camarade en svg, et utilisant le laplacien.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Rendu final de la photo de notre camarade en svg, et utilisant le laplacien.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hiboux_svg.png&amp;diff=16904</id>
		<title>Fichier:Hiboux svg.png</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Hiboux_svg.png&amp;diff=16904"/>
		<updated>2026-05-10T20:50:12Z</updated>

		<summary type="html">&lt;p&gt;Lheote : Rendu final du hiboux en svg, et utilisant le laplacien.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Rendu final du hiboux en svg, et utilisant le laplacien.&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Filage_d%27image_et_trac%C3%A9_de_droites_pour_un_rendu_artistique&amp;diff=16863</id>
		<title>Filage d&#039;image et tracé de droites pour un rendu artistique</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Filage_d%27image_et_trac%C3%A9_de_droites_pour_un_rendu_artistique&amp;diff=16863"/>
		<updated>2026-05-10T15:44:10Z</updated>

		<summary type="html">&lt;p&gt;Lheote : /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Projet réalisé dans le cadre du cours [[VISI201_CMI_:_visite_de_laboratoire]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Étudiants :&#039;&#039;&#039; [http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Utilisateur:Goralczyk Goralczyk Elliot], [http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Utilisateur:Lheote Lhéoté Anaïs]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tuteur :&#039;&#039;&#039; [https://jacquesolivierlachaud.github.io/ Jacques-Olivier Lachaud]&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
Un filage d&#039;image est la reproduction d&#039;une image à partir de clous sur une planche et d&#039;un fil noir pour retracer l&#039;image. &lt;br /&gt;
Lors de ce projet, nous avons reproduit cette technique artistique à l&#039;aide de python pour voir jusqu&#039;où nous pourrions pousser la ressemblance avec une image donnée.&lt;br /&gt;
Pour cela nous avons du comprendre le principe en lui-même et nous avons ensuite élaboré plusieurs techniques pour pavenir au meilleur résultat possible.&lt;br /&gt;
&lt;br /&gt;
= Placer les clous =&lt;br /&gt;
&lt;br /&gt;
Le placement des clous va définir l&#039;ensemble des droites qu&#039;il va nous être possible de tracer. Par exemple, les quatre clous gris sur l&#039;image ci-dessous permettent de tracer uniquement les six droites en rouge.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-importance-palcement-clous.png|center|100px]]&lt;br /&gt;
&lt;br /&gt;
Il est donc important de bien placer les clous pour obtenir un résultat satisfaisant.&lt;br /&gt;
Nous avons utilisé trois techniques différentes pour placer les clous au cours de ce projet.&lt;br /&gt;
&lt;br /&gt;
=== Représentation d&#039;un clou ===&lt;br /&gt;
&lt;br /&gt;
Avant de pouvoir placer un clou, il faut savoir comment le représenter.&lt;br /&gt;
Nous avons fait le choix de le représenter par un triplet : (coordonnée x, coordonnée y, côté).&lt;br /&gt;
Le côté est utilisé pour déterminer si il est possible de relier deux clous ; on considère qu&#039;on ne peut pas relier deux clous situés d&#039;un même côté.&lt;br /&gt;
Un clou est donc associé à un pixel de l&#039;image, et l&#039;ensemble de ces clous est stocké dans une liste.&lt;br /&gt;
&lt;br /&gt;
=== Faire le tour de l&#039;image ===&lt;br /&gt;
&lt;br /&gt;
Notre première approche a été de simplement placer des clous tous les 10 pixels autour de l&#039;image.&lt;br /&gt;
Cela permet d&#039;avoir de nombreuses possibilités pour tracer les droites, et de pouvoir atteindre une grande majorité des pixels de l&#039;image.&lt;br /&gt;
&lt;br /&gt;
L&#039;inconvénient de cette méthode est que les droites vont forcément d&#039;un bord à l&#039;autre de l&#039;image, et ne peuvent pas s&#039;arrêter au milieu, ce qui réduit les possibilités de représenter des détails.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple au ralenti de la génération de clous avec cette approche, sur une image carrée de 101 pixels de côté :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Generation-clous-autour-de-l-image.gif|center|202px]]&lt;br /&gt;
&lt;br /&gt;
=== Placer des clous aléatoires ===&lt;br /&gt;
&lt;br /&gt;
Pour pallier au problème de ne pas pouvoir arrêter une droite ailleurs que sur un bord, nous avons décider de rajouter des clous dont la position a été générée aléatoirement.&lt;br /&gt;
Pour ce faire, nous générons aléatoirement pour chaque clou sa coordonnée x (respectivement : y) un nombre entre 20 et la longueur (respectivement : hauteur) de l&#039;image - 20, pour qu&#039;ils ne soient pas trop près du bord.&lt;br /&gt;
Étant donné qu&#039;un clou au centre de l&#039;image doit pouvoir être relié à tous les autres, nous incrémentons à chaque clou la valeur de son côté, pour que chacun des clous générés aléatoirement ait un côté différent.&lt;br /&gt;
&lt;br /&gt;
Cette méthode permet d&#039;obtenir plus de détails, mais leur qualité repose sur des variables entièrement aléatoires, ce qui n&#039;est pas idéal.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple au ralenti de la génération de clous avec cette approche, sur une image carrée de 101 pixels de côté, avec 20 clous aléatoires : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:Generation-clous-aleatoires.gif|center|202px]]&lt;br /&gt;
&lt;br /&gt;
=== Utiliser les contours ===&lt;br /&gt;
&lt;br /&gt;
Afin d&#039;obtenir des images plus détaillées, nous souhaitons placer les clous autour formes visibles dans nos images.&lt;br /&gt;
Cela permettra de mieux en délimiter les contours, et donc de les faire ressortir et de les dessiner plus fidèlement.&lt;br /&gt;
Pour y parvenir, nous utilisons un système de probabilités.&lt;br /&gt;
Cela signifie que chaque pixel possède un poids, et que plus ce poids est grand, plus il est probable que ce pixel soit choisi.&lt;br /&gt;
&lt;br /&gt;
Pour déterminer ce poids, nous utilisons de la détection de contours. En utilisant un filtre sur une image (dans notre cas le filtre [https://github.com/python-pillow/Pillow/blob/main/src/PIL/ImageFilter.py#L327 FIND_EDGES] de la bibliothèque Python [https://github.com/python-pillow/Pillow/ Pillow]), on peut obtenir une image sur laquelle les contours de l&#039;image de départ ressortent en blanc, et le reste en noir, comme sur l&#039;exemple ci-dessous.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Filtre-laplacien.png|center]]&lt;br /&gt;
&lt;br /&gt;
Nous pouvons ensuite déterminer les probabilités à partir de cette image.&lt;br /&gt;
Pour ce faire, on commence par récupérer la valeur de chaque pixel de l&#039;image dans une matrice de dimension &amp;lt;math&amp;gt;(h, l)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt; h &amp;lt;/math&amp;gt; la hauteur en pixels de l&#039;image, et &amp;lt;math&amp;gt; l &amp;lt;/math&amp;gt; sa longueur.&lt;br /&gt;
La valeur d&#039;un pixel dans une image en nuances de gris correspond à sa luminosité : 0 correspond au noir, 255 au blanc, et 127 à un gris moyen.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple d&#039;une image en niveaux de gris et de la matrice correspondante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-passage-pixels-matrice.png|center]]&lt;br /&gt;
&lt;br /&gt;
À partir de cette matrice, on va créer une matrice de dimension identique, dans lequel chaque élément sera la somme de la valeur du pixel correspondant dans la matrice précédente et la valeur de l&#039;élément précédent.&lt;br /&gt;
&lt;br /&gt;
Voici ce que donnerait cette nouvelle matrice en reprenant l&#039;exemple précédent :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-passage-pixels-matrice-somme-cumulative.png|center]]&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons cette matrice, nous pouvons générer un nombre aléatoire situé entre 0 et la dernière valeur de la matrice que nous allons appeler &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;.&lt;br /&gt;
Il ne nous reste plus qu&#039;à parcourir la matrice jusqu&#039;à tomber sur un nombre plus grand que &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;.&lt;br /&gt;
Les coordonnées de ce nombre dans la matrice, et donc celles du pixel auquel il est associé seront associées à un nouveau clou.&lt;br /&gt;
Par exemple, si on obtient &amp;lt;math&amp;gt;r = 268&amp;lt;/math&amp;gt;, un clou sera placé en bas à gauche, car le nombre en bas à gauche de la deuxième matrice est le premier à être plus grand que 268.&lt;br /&gt;
&lt;br /&gt;
Plus des pixels seront des contours marqués, plus ils seront clairs une fois le filtre appliqué. Ils auront donc plus de chances d&#039;être tirés au sort, comme illustré ci-dessous.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-probas-pixels-laplacien.png|center]]&lt;br /&gt;
&lt;br /&gt;
Il ne nous reste plus qu&#039;à placer autant de clous que l&#039;on veut, et nous avons notre liste de clous.&lt;br /&gt;
Nous ne plaçons pas manuellement de clous sur le bord de l&#039;image avec cette méthode, et la notion de &amp;quot;côté&amp;quot; est peu utile ; on considère que tous les clous peuvent-être reliés entre eux, chaque clou possède donc un &amp;quot;côté&amp;quot; différent.&lt;br /&gt;
&lt;br /&gt;
= Trouver la droite à tracer =&lt;br /&gt;
&lt;br /&gt;
Maintenant que nos clous sont placés, il faut savoir lesquels relier entre eux.&lt;br /&gt;
Nous aurons toujours un clou de départ, qui pour la première droite sera le premier clou de la liste, et pour les droites suivantes, le clou d&#039;arrivée de la dernière droite tracée.&lt;br /&gt;
&lt;br /&gt;
=== Mesurer la différence entre deux images ===&lt;br /&gt;
&lt;br /&gt;
Pour décider à quel clou on doit relier notre clou de départ, nous commençons par choisir aléatoirement une liste de clous à tester.&lt;br /&gt;
On garde aléatoirement la moitié des clous, pour diviser par deux le nombre de calculs, tout en gardant un grand nombre de possibilités.&lt;br /&gt;
&lt;br /&gt;
Pour chacun de ces clous, on calcule la liste des pixels que la droite allant du clou de départ à ce clou d&#039;arrivée traverse.&lt;br /&gt;
On compare ensuite pour chaque pixel de cette liste sa valeur dans notre image résultat provisoire et dans l&#039;image de départ en niveau de gris.&lt;br /&gt;
En faisant la somme de la valeur absolue de la différence entre les valeurs de chaque pixel de notre liste sur les deux images, et en la divisant par le nombre de pixels de la droite, on obtient la valeur de la différence moyenne par pixel entre les deux images.&lt;br /&gt;
&lt;br /&gt;
Voici un exemple illustré, en calculant la différence sur les quatres pixels des images :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-calcul-difference-images.png|center]]&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons calculé cette différence, il faut calculer la différence que l&#039;on obtiendrait si la droite eétait tracée.&lt;br /&gt;
On répète donc les opérations précédentes, en modifiant la valeur des pixels de notre image résultat provisoire.&lt;br /&gt;
On soustrait à cette nouvelle différence le résultat obtenu précédemment, et cela nous donne la valeur de la réduction moyenne de la différence par pixel que l&#039;on obtiendrait si on traçait la droite.&lt;br /&gt;
Plus ce résultat est faible, plus la droite rapproche notre résultat de l&#039;image de départ. Si ce résultat est positif, cela signifie que notre résultat s&#039;éloigne de l&#039;image originale.&lt;br /&gt;
&lt;br /&gt;
On observe par exemple que si on assombrit le pixel en haut à gauche de l&#039;image de droite, la différence entre les deux images va diminuer, et l&#039;image de droite va donc se rapprocher de celle de gauche :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Exemple-calcul-difference-images-2.png|center]]&lt;br /&gt;
&lt;br /&gt;
La différence entre l&#039;image de gauche et celle de droite diminue donc d&#039;une valeur de 77 - 32 = 45 par pixel en moyenne.&lt;br /&gt;
&lt;br /&gt;
On calcule donc ce résultat pour toutes nos droites, et on trouve le clou qui réduit le plus l&#039;erreur.&lt;br /&gt;
On trace donc une droite jusqu&#039;à ce clou, puis on cherche de nouveau le meilleur clou, et ainsi de suite. Mais alors, à quel moment faut-il s&#039;arrêter ?&lt;br /&gt;
&lt;br /&gt;
=== La condition d&#039;arrêt ===&lt;br /&gt;
&lt;br /&gt;
Dans note implémentation de cet algorithme, nous avons fait le choix de s&#039;arrêter lorsque la meilleure droite éloigne notre résultat de l&#039;image de départ trois fois d&#039;affilé.&lt;br /&gt;
Nous n&#039;arrêtons pas dès que le résultat s&#039;éloigne car il arrive souvent qu&#039;une droite qui éloigne notre résultat de l&#039;image de départ permette ensuite de tracer une meilleure droite, qui va améliorer notre résultat.&lt;br /&gt;
&lt;br /&gt;
= Tracer la droite =&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir trouver la meilleure droite, encore faut-il savoir par quels pixels cette droite passe.&lt;br /&gt;
&lt;br /&gt;
=== Représenter une image ===&lt;br /&gt;
&lt;br /&gt;
Et avant de savoir par quels pixels elle passe, il faut d&#039;abord représenter ces pixels.&lt;br /&gt;
&lt;br /&gt;
Durant ce projet, nous avons travaillé uniquement sur des images en niveaux de gris, nous représentons donc une image par une matrice de dimension identique à cette image, dans laquelle chaque élément de la matrice représente un pixel, comme vu dans la partie précédente.&lt;br /&gt;
Pour importer une image, on la convertit donc en niveaux de gris, puis on récupère la valeur de chaque pixel pour en faire une matrice.&lt;br /&gt;
Pour créer une image blanche, on crée une matrice de la taille souhaitée et on initialise touts les valeurs à 255, la valeur du blanc.&lt;br /&gt;
&lt;br /&gt;
=== Calculer la liste des pixels traversés ===&lt;br /&gt;
&lt;br /&gt;
Pour connaître la liste des pixels traversés par une droite, on utilise son équation de type y = ax + b où y est une ordonnée (une coordonnée y), x une abscisse (une coordonnée x), a le coefficient directeur de la droite, et b son ordonnée à l&#039;origine (la valeur de y quand x vaut 0).&lt;br /&gt;
&lt;br /&gt;
Pour calculer les valeurs a et b, on utilise les coordonnées des deux points (des deux clous) que la droite traverse.&lt;br /&gt;
On nomme x1 et y1 les coordonnées du clou de départ, et x2 et y2 le coordonnées du clou d&#039;arrivée.&lt;br /&gt;
Excepté le cas des droites verticales, on a a = (y2 - y1) / (x2 - x1) et b = y1 - x1 * a .&lt;br /&gt;
&lt;br /&gt;
Deux cas apparaissent alors, celui dans lequel a appartient à [-1, 1], et celui dans lequel il n&#039;est pas dedans.&lt;br /&gt;
Dans le premier cas, la droite va être plus proche de l&#039;axe des abscisses que de l&#039;axe des ordonnées, et inversement dans le second cas.&lt;br /&gt;
&lt;br /&gt;
Voici quelques exemples :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Schema-intervalle-a.png|center]]&lt;br /&gt;
&lt;br /&gt;
On peut observer que dans le premier cas (en bleu), il y a plusieurs pixels par ligne, et un seul par colonne, et inversement dans le deuxième cas (en rouge).&lt;br /&gt;
&lt;br /&gt;
On traite donc ces deux cas différemment :&lt;br /&gt;
&lt;br /&gt;
- Dans le premier cas, on détermine y pour chaque valeur de x entre x1 et x2 grâce au résultat de l&#039;opération ax + b que l&#039;on arrondit pour obtenir les coordonnées d&#039;un pixel.&lt;br /&gt;
&lt;br /&gt;
- Dans le second cas, on détermine x pour chaque valeur de y entre y1 et y2 grâce au résultat de l&#039;opération (y - b) / a que l&#039;on arrondit également.&lt;br /&gt;
&lt;br /&gt;
Dans le cas des droites verticales, a n&#039;est pas défini car il faudrait diviser par 0. On fabrique donc la liste de pixels en laissant la coordonnée x constante, et en ajoutant toutes les coordonnées y entre y1 et y2.&lt;br /&gt;
&lt;br /&gt;
Une fois que nous avons notre liste de pixel, on modifie la valeur de chaque pixel dans la liste pour tracer la droite.&lt;br /&gt;
Nous avons fait le choix de modifier de 51 la valeur des pixels, pour obtenir 6 niveaux de gris qui sont du plus foncé au plus clair : 255 -&amp;gt; 204 -&amp;gt; 153 -&amp;gt; 102 -&amp;gt; 51 -&amp;gt; 0.&lt;br /&gt;
&lt;br /&gt;
=== Utiliser le format SVG ===&lt;br /&gt;
&lt;br /&gt;
Pour obtenir un résultat moins pixelisé, nous utilisons le format [https://fr.wikipedia.org/wiki/Scalable_Vector_Graphics SVG].&lt;br /&gt;
Ce format est un format vectoriel, ce qui signifie qu&#039;il ne stocke pas des pixels mais des formes et leurs coordonnées.&lt;br /&gt;
Cela permet de pouvoir zoomer sur une image sans percevoir les pixels.&lt;br /&gt;
&lt;br /&gt;
Nous utilisons ce format uniquement pour le résultat, les calculs utilisent toujours des matrices de pixels.&lt;br /&gt;
Afin de rester cohérents avec les six niveaux de gris, les droites tracées ont une opacité de 20%.&lt;br /&gt;
&lt;br /&gt;
Voici une comparaison de la même image de 10 pixels de côté en PNG à gauche, et en SVG à droite :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Comparaison-png-svg.png|center]]&lt;br /&gt;
&lt;br /&gt;
= Évolution de l&#039;algorithme =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Résultats finaux =&lt;/div&gt;</summary>
		<author><name>Lheote</name></author>
	</entry>
</feed>