<?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=Chardonnet</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=Chardonnet"/>
	<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Sp%C3%A9cial:Contributions/Chardonnet"/>
	<updated>2026-05-21T09:57:53Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=13605</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=13605"/>
		<updated>2022-05-11T15:13:11Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La complexité de ce programme est de l&#039;ordre de ln(N), car le trie des liste domine.&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.bmp&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. Pour l&#039;image C, son format par défaut est en bmp.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;br /&gt;
&lt;br /&gt;
== Liens ==&lt;br /&gt;
Une version mise à jour du code présenté est disponible sur github à l&#039;adresse [https://github.com/clau555/color-transfer https://github.com/clau555/color-transfer].&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=12716</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=12716"/>
		<updated>2021-03-29T21:29:55Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La complexité de ce programme est de l&#039;ordre de ln(N), car le trie des liste domine.&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.bmp&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. Pour l&#039;image C, son format par défaut est en bmp.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;br /&gt;
&lt;br /&gt;
== Liens ==&lt;br /&gt;
Une version mise à jour du code présenté est disponible sur github à l&#039;adresse [https://github.com/LucCha42/color-transfer https://github.com/LucCha42/color-transfer].&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=12715</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=12715"/>
		<updated>2021-03-29T21:29:23Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La complexité de ce programme est de l&#039;ordre de ln(N), car le trie des liste domine.&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.bmp&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. Pour l&#039;image C, son format par défaut est en bmp.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;br /&gt;
&lt;br /&gt;
== Liens ==&lt;br /&gt;
Une version mise à jour du code présenté est disponible sur github à l&#039;adresse [[https://github.com/LucCha42/color-transfer https://github.com/LucCha42/color-transfer]].&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=VISI201_CMI_:_visite_de_laboratoire&amp;diff=11880</id>
		<title>VISI201 CMI : visite de laboratoire</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=VISI201_CMI_:_visite_de_laboratoire&amp;diff=11880"/>
		<updated>2019-05-23T08:45:16Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : Mise à jour du lien du Transport optimal&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Cours du semestre 2 du parcours CMI Informatique (licence INFO).&lt;br /&gt;
&lt;br /&gt;
* Responsable pour 2018--2019: Jacques-Olivier Lachaud&lt;br /&gt;
* Responsable pour 2017--2018: Jacques-Olivier Lachaud&lt;br /&gt;
* Responsable pour 2016--2017: Jacques-Olivier Lachaud&lt;br /&gt;
&lt;br /&gt;
= Descriptif =&lt;br /&gt;
&lt;br /&gt;
L&#039;objectif du module est de faire découvrir les laboratoires, le monde de la recherche et les enseignants-chercheurs et chercheurs, ainsi que la réflexion scientifique. Cela se fait de deux manières. &lt;br /&gt;
&lt;br /&gt;
D&#039;abord, une partie de ce module consiste à assister à des séminaires dédiés aux étudiants CMI Informatique et Mathématique (1 fois par mois, les jeudi après-midi). [[http://www.lama.univ-savoie.fr/index.php?use=seminaires&amp;amp;&amp;amp;lang=fr&amp;amp;equipe=cmi&amp;amp;annee=1&amp;amp;lang=fr Planning des séminaires CMI]]&lt;br /&gt;
&lt;br /&gt;
Ces séminaires &amp;quot;grand public&amp;quot; portent sur des sujets variées en informatique et mathématiques.&lt;br /&gt;
&lt;br /&gt;
Les étudiants choisissent ensuite d&#039;approfondir un sujet proposé par les enseignants, ou un sujet motivé de leur choix (en accord avec le responsable du module). Ce travail se fait en interaction avec un tuteur académique (5-6 contacts au moins). Ce travail personnel tuteuré donne lieu à la rédaction d&#039;une synthèse sur le sujet sous forme d&#039;une page wiki/web, ainsi que d&#039;un mini-exposé.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Sujets réalisés (2018-2019) =&lt;br /&gt;
&lt;br /&gt;
* [[Transport optimal par coupe 1D et transfert de couleurs entre images]] (Lucas CHARDONNET)&lt;br /&gt;
* [[Génération et résolution de labyrinthes II]] (Romain THEODET)&lt;br /&gt;
* [[Rest &amp;amp; Pub-Sub : protocole hybride pour l&#039;IoT]] (Ewan RAKOTOANOSY)&lt;br /&gt;
* [[La suite de Conway et la classification périodique des &amp;quot;éléments&amp;quot;]] (Yohann THEPAUT)&lt;br /&gt;
* Initiation à la démonstration sur ordinateur et certification de logiciel&lt;br /&gt;
* [[Dilemme du prisonnier]] (Christophe CARMAGNAC)&lt;br /&gt;
&lt;br /&gt;
= Sujets proposés (2018-2019) =&lt;br /&gt;
&lt;br /&gt;
* Transport optimal par coupe 1D et transfert de couleurs entre images&lt;br /&gt;
* Génération et résolution de labyrinthes II&lt;br /&gt;
* REST + Pub/Sub : protocole hybride pour l’IoT&lt;br /&gt;
* La suite de Conway et la classification périodique des &amp;quot;éléments&amp;quot;&lt;br /&gt;
* Initiation à la démonstration sur ordinateur et certification de logiciel&lt;br /&gt;
* Algorithmes probabilistes/déterministes pour tester la primalité d&#039;un entier&lt;br /&gt;
* Dilemme du prisonnier&lt;br /&gt;
&lt;br /&gt;
== Transport optimal par coupe 1D et transfert de couleurs entre images ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Jacques-Olivier Lachaud&lt;br /&gt;
* Résumé: Le transfert de couleurs de l&#039;image Y vers l&#039;image X consiste à repeindre &amp;quot;au mieux&amp;quot; l&#039;image X avec la palette de couleurs de l&#039;image Y. L&#039;image repeinte X&#039; a alors les mêmes couleurs que l&#039;image Y (mais les pixels ne sont pas répartis pareils). Voir l&#039;exemple de transfert ci-dessous. Il existe plusieurs techniques de transfert de couleurs, mais nous étudierons une technique basée sur le transport optimal. Comme c&#039;est un problème assez difficile dans le cas général, nous verrons une variante dite par coupe 1D, qui simplifiera considérablement le problème de transport.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Ex-transfert-couleur-OT.png]]&lt;br /&gt;
&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# comprendre ce qu&#039;est une image niveaux couleur, et ce qu&#039;on appelle le transfert de couleurs.&lt;br /&gt;
*# comprendre le principe du transport optimal (discret).&lt;br /&gt;
*# comprendre et décrire le principe du transport optimal par coupe 1D, et comment se fait le calcul du meilleur transport dans ce cas.&lt;br /&gt;
*# Coder un programme de transfert de couleur, qui prend deux images couleurs et réalise le transfert de couleurs.&lt;br /&gt;
*# On pourra ensuite réfléchir à quelques améliorations simples (espace couleur YUV, grouper les pixels).&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** Le vrai &amp;quot;Transport Optimal&amp;quot; est vite très mathématique (ce sont des mesures qui sont transportées), mais on peut l&#039;aborder beaucoup plus simplement dans le cas discret (un nombre fini de valeurs) comme une simple assignation entre deux ensembles.&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Color_mapping Transfert de couleur Wikipedia]]&lt;br /&gt;
** [[https://hal.archives-ouvertes.fr/tel-01246096/file/hdr_hal2.pdf Habilitation de N. Papadakis]] (regardez les images plutôt).&lt;br /&gt;
&lt;br /&gt;
== Génération et résolution de labyrinthes II ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: François Boussion&lt;br /&gt;
* Résumé: On veut générer des labyrinthes aussi grands et complexes que possible, avec des murs dans une grille carré voire d&#039;autres domaines. Comment faire pour qu&#039;il y ait toujours un chemin de l&#039;entrée à la sortie ? Comment faire pour qu&#039;il n&#039;y ait qu&#039;un chemin ? Ensuite, comment trouver la sortie quand on est perdu dans le labyrinthe.&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# Comprendre comment représenter un labyrinthe avec une structure de données simple&lt;br /&gt;
*# Voir le lien avec la théorie des graphes et voir que le problème se résout de la même façon pour des grilles carrées, hexagonales ou autres.&lt;br /&gt;
*# Comprendre l&#039;algorithme d&#039;arbre couvrant minimum&lt;br /&gt;
*# Comprendre le principe du parcours en profondeur et de la récursivité&lt;br /&gt;
* Pour aller plus loin&lt;br /&gt;
*# coder la génération d&#039;un labyrinthe et sa visualisation&lt;br /&gt;
*# introduire des poids pour varier le labyrinthe&lt;br /&gt;
*# comment faire un labyrinthe sur grille hexagonale avec des tableaux.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Mod%C3%A9lisation_math%C3%A9matique_d%27un_labyrinthe Wikipedia]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Maze_generation_algorithm Version anglaise plus complète]]&lt;br /&gt;
&lt;br /&gt;
== REST + Pub/Sub : protocole hybride pour l’IoT ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: David Télisson&lt;br /&gt;
* Résumé: L’avènement de l’Internet des Objets (IoT) depuis une dizaine d’années a fait apparaitre des problématiques propres aux protocoles de communications liées à ces objets. En effet, l’échange de données dans ce contexte nécessite de tenir compte (au moins) des paramètres suivant : &lt;br /&gt;
*# Autonomie énergétique souvent limitée&lt;br /&gt;
*# Faible puissance des processeurs et taille réduite de la mémoire &lt;br /&gt;
*# Disponibilité « aléatoire » de l’accès aux réseaux de communication &lt;br /&gt;
&lt;br /&gt;
De nombreux protocoles cohabitent et la littérature du domaine foisonne d’exemples autour des réseaux dédiées (LORA, Sigfox, etc.) et des protocoles applicatifs (OPC-UA, MQTT, CoaP, XMPP) mais force est de constater que dans la réalité, ces solutions ne répondent pas toujours aux besoins des concepteurs qui leurs préfèrent encore le protocole HTTP. Celui-ci offre l’avantage d’implémenter un protocole applicatif (REST) en même temps qu’un protocole de transport de haut niveau (TCP/IP) permettant de passer les pare-feu. Cependant, la version actuel d’HTTP ne répond pas vraiment aux critères énoncés précédemment.&lt;br /&gt;
Depuis quelques années émerge donc l’idée d’enrichir HTTP pour créer un protocole hybride qui mêlerait les avantages de REST avec ceux proposés par les mécanismes de type Publish/Subscribe (MQTT, AMQP, JMS, etc.). En attendant cette éventuelle évolution, peut-on envisager de mettre en place un mécanisme de type Pub/Sub avec le protocole Websocket au-dessus d’HTTP ?&lt;br /&gt;
&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# Etudier et faire une synthèse des deux approches : REST et Pub/Sub &lt;br /&gt;
*# Implémentez un PoC (proof of concept) d’une solution hybride qui met en œuvre un mécanisme de Pub/Sub sur Websocket. .&lt;br /&gt;
*# Présenter un protocole de test pour valider ou invalider cette solution&lt;br /&gt;
&lt;br /&gt;
* Liens pour démarrer :&lt;br /&gt;
** https://nsrc.org/workshops/2018/apricot/iot/presentations/mqttvsrest_v4.pdf&lt;br /&gt;
** http://www.tigli.fr/lib/exe/fetch.php?media=cours:tutorial_mqtt_mit_2015_2016.pdf&lt;br /&gt;
** https://openclassrooms.com/fr/courses/3449001-utilisez-des-api-rest-dans-vos-projets-web&lt;br /&gt;
** http://www.lirmm.fr/~tibermacin/ens/ws/expose.pdf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== La suite de Conway et la classification périodique des &amp;quot;éléments&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur : Pierre Hyvernat&lt;br /&gt;
* La suite de Conway est la suite suivante : 1 ; 11 ; 21 ; 1211 ; 111221 ; ... Chaque terme est obtenu en &amp;quot;lisant&amp;quot; le terme précédent.                                                                                                                                                            &lt;br /&gt;
** &amp;quot;1&amp;quot; : un &amp;quot;1&amp;quot; -&amp;gt; 11&lt;br /&gt;
** &amp;quot;11&amp;quot; : deux &amp;quot;1&amp;quot; -&amp;gt; 21&lt;br /&gt;
** &amp;quot;21&amp;quot; : un &amp;quot;2&amp;quot;, un &amp;quot;1&amp;quot; -&amp;gt; 1211&lt;br /&gt;
** &amp;quot;1211&amp;quot; : un &amp;quot;1&amp;quot;, un &amp;quot;2&amp;quot;, deux &amp;quot;1&amp;quot; -&amp;gt; 111221&lt;br /&gt;
** etc.&lt;br /&gt;
Cette suite possède des propriétés étonantes données par le théorème &amp;quot;chimique&amp;quot;, le théorème &amp;quot;arithmétique&amp;quot; et le théorème &amp;quot;cosmologique&amp;quot;.&lt;br /&gt;
* Objectifs :                                                                                                                                                                                                                  &lt;br /&gt;
*# comprendre les énoncés de ces théorèmes, et l&#039;idée de la preuve du premier.                    &lt;br /&gt;
*# programmer la suite de Conway pour retrouver la classification des &amp;quot;atomes&amp;quot;&lt;br /&gt;
*# écrire un programme pour calculer expérimentalement une approximation de la constante &amp;quot;lambda&amp;quot; ainsi que des fréquences respectives des différents atomes.&lt;br /&gt;
*# écrire un programme pour calculer la suite de Robinson, une variante plus simple de la suite de Conway&lt;br /&gt;
&lt;br /&gt;
* Liens pour commencer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Suite_de_Conway suite de Conway]]&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Suite_de_Robinson suite de Robinson]]&lt;br /&gt;
&lt;br /&gt;
== [[Initiation à la démonstration sur ordinateur et certification de logiciel]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Tom Hirschowitz&lt;br /&gt;
* Résumé: [[https://coq.inria.fr Coq]] est un logiciel de mathématiques sur ordinateur, grâce auquel des programmes élaborés ont pu être certifiés ces dernières années.&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# prendre en main le logiciel [[https://coq.inria.fr Coq]] de démonstration sur ordinateur,&lt;br /&gt;
*# programmer certaines démonstrations basiques en Coq,&lt;br /&gt;
*# suivre le début du cours [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]],&lt;br /&gt;
* Pour aller plus loin : Software Foundations est un cours assez long et très bien fait, il y aura suffisamment à faire. Eventuellement, selon l&#039;intérêt de l&#039;étudiant, étude des fondements mathématiques de Coq.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]]&lt;br /&gt;
** [[https://coq.inria.fr Coq]]&lt;br /&gt;
&lt;br /&gt;
== Algorithmes probabilistes/déterministes pour tester la primalité d&#039;un entier  ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur : Sébastien Tavenas&lt;br /&gt;
* Pouvoir tester si un entier est un nombre premier semble être une brique de base si l&#039;on souhaite faire de l&#039;arithmétique sur un ordinateur. Le crible d&#039;Érathostène enseigné dans les petites classes se montre beaucoup trop lent en pratique. L&#039;algorithme probabiliste utilisé le plus rapide est le test de Fermat. Or, si on regarde les algorithmes des librairies &amp;quot;génériques&amp;quot;, on peut s&#039;apercevoir que la fonction &#039;mpz_probab_prime_p&#039; de la librairie &#039;gmp&#039; sur c++ utilise un test probabiliste de Miller-Rabin, la fonction &#039;isPrime&#039; de la classe &#039;Prime&#039; dans java utilise aussi un test de Miller-Rabin mais qui est déterminisé, alors que la fonction &#039;isprime&#039; de la librairie &#039;sympy&#039; dans python effectue un test de Miller-Rabin si l&#039;entier est plus petit que 2^64 et un test BPSW fort si l&#039;entier est plus grand. Ainsi, une fonction déjà implémentée de test de primalité peut se tromper ou non, être instantanée ou moins. Que dire alors de l&#039;algorithme polynomial déterministe et toujours correct proposé par AKS?                                                                                                                                                &lt;br /&gt;
* Objectifs :                                                                                                                                                                                                             &lt;br /&gt;
*# Comprendre quelques tests de primalité et comment l&#039;aléatoire est utilisé dans ces algorithmes&lt;br /&gt;
*# Comprendre la notion de nombre pseudopremier qui explique, entre autre, quand il vaut mieux utiliser le test de Fermat ou celui de Miller-Rabin                     &lt;br /&gt;
*# Programmer quelques uns des ces tests et les comparer&lt;br /&gt;
*# Essayer de dérandomiser ces tests à l&#039;aide de hitting-sets précalculés&lt;br /&gt;
&lt;br /&gt;
* Liens pour commencer&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Primality_test Tests de primalité]]&lt;br /&gt;
&lt;br /&gt;
== Dilemme du prisonnier ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Gerald Cavallini&lt;br /&gt;
* Résumé: Le dilemme du prisonnier caractérise en théorie des jeux une situation où deux joueurs auraient&lt;br /&gt;
intérêt à coopérer, mais où, en l’absence de communication entre les deux joueurs, chacun choisira&lt;br /&gt;
de trahir l&#039;autre si le jeu n&#039;est joué qu&#039;une fois.&lt;br /&gt;
&lt;br /&gt;
On peut informatiquement modéliser ce dilemme à l’aide de matrices de gains et conserver la&lt;br /&gt;
mémoire des choix de l’adversaire. Ce modèle appliqué à un grand nombre d’individus peut être&lt;br /&gt;
utilisé pour comprendre l’émergence de stratégies stables dans l’économie, l’écologie, l’évolution&lt;br /&gt;
des espèces ...&lt;br /&gt;
&lt;br /&gt;
On peut visualiser spatialement les interactions entre individus en les représentants par des pixels et&lt;br /&gt;
en leurs associant une couleur en fonction de leurs stratégies.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Dilemme.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Objectifs&lt;br /&gt;
*# Comprendre le dilemme du prisonnier&lt;br /&gt;
*# Comprendre la notion de stratégie&lt;br /&gt;
*# Penser un modèle spatiale pour « opposer » des individus qui appliquent des stratégies différentes&lt;br /&gt;
*# Développer une interface pour visualiser dans le temps l’évolution d’une population d’individus adoptants des stratégies différentes.&lt;br /&gt;
&lt;br /&gt;
* Lien :&lt;br /&gt;
*# [https://fr.wikipedia.org/wiki/Dilemme_du_prisonnier Dilemme du prisonnier Wikipedia]&lt;br /&gt;
*# [http://cormas.cirad.fr/fr/applica/dps.htm Site spécifique]&lt;br /&gt;
&lt;br /&gt;
= Sujets réalisés (2017-2018) =&lt;br /&gt;
&lt;br /&gt;
* [[VISI201 Analyse syntaxique (Tristan Porteries, 2018)]]&lt;br /&gt;
* [[Segmentation d&#039;image par détection de contours et algorithme &amp;quot;ligne de partage des eaux&amp;quot;]] (Nils Ruet, 2018)&lt;br /&gt;
* [[Fouille de données textuelles à partir des &amp;quot;Exercices de style&amp;quot; de R. Queneau]] (Rémi Bouvier, 2018)&lt;br /&gt;
* [[Transformées en distance, diagramme de Voronoi et applications en geometry processing]] (Robin Wagner, 2018)&lt;br /&gt;
* [[Pavages de Penrose]] (Brunelle Cordier-Pierre-Bès, 2018)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Sujets proposés (2017-2018) =&lt;br /&gt;
&lt;br /&gt;
* Segmentation d&#039;image par détection de contours et algorithme &amp;quot;ligne de partage des eaux&amp;quot;&lt;br /&gt;
* Initiation à la démonstration sur ordinateur et certification de logiciel&lt;br /&gt;
* Fouille de données textuelles à partir des &amp;quot;Exercices de style&amp;quot; de R. Queneau&lt;br /&gt;
* Transformées en distance, diagramme de Voronoi et applications en geometry processing&lt;br /&gt;
* Pavages de Penrose&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Segmentation d&#039;image par détection de contours et algorithme &amp;quot;ligne de partage des eaux&amp;quot;]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Jacques-Olivier Lachaud&lt;br /&gt;
* Résumé: La segmentation d&#039;image vise à identifier les régions d&#039;intérêt dans une image. Typiquement, une région d&#039;intérêt est une zone de l&#039;image plutôt homogène (les pixels ont des valeurs proches) et le contour entre deux régions d&#039;intérêt est tracé là où les valeurs subissent de fortes variations. La méthode de segmentation proposée ici suit ce principe en enchaînant deux calculs: (1) un premier traitement calcule une image &amp;quot;gradient&amp;quot; et fabrique une image dont les valeurs élevées correspondent à des zones de fortes variations, (2) le deuxième algorithme voit cette image comme un relief 3D et identifie ses bassins hydrographiques. Cette identification des lignes de partage des eaux permet de découper l&#039;image en ses zones d&#039;intérêt.&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# comprendre ce qu&#039;est une image niveaux de gris ou couleur, ce qu&#039;est le gradient d&#039;une image et ce qu&#039;on appelle segmentation d&#039;image.&lt;br /&gt;
*# décrire un algorithme de calcul du gradient d&#039;une image, e.g. le filtre de Sobel, voire les convolutions par dérivées de Gaussienne.&lt;br /&gt;
*# décrire le principe de ligne de partage des eaux (&amp;quot;watershed&amp;quot; en anglais), ses différentes définitions équivalentes, et les différents types d&#039;algorithmes pour la calculer.&lt;br /&gt;
*# Coder un programme de segmentation d&#039;image, qui prend une image (niveaux de gris) en entrée, calcule son gradient, et extrait les bassins de sa ligne de partage des eaux.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Watershed_(image_processing) Watershed Wikipedia]]&lt;br /&gt;
** Luc Vincent and Pierre Soille. Watersheds in digital spaces: an efficient algorithm based on immersion simulations. In IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 13, Num. 6 (1991), pages 583–598 [[https://pdfs.semanticscholar.org/a381/9dda9a5f00dbb8cd3413ca7422e37a0d5794.pdf PDF]]&lt;br /&gt;
&lt;br /&gt;
== [[Initiation à la démonstration sur ordinateur et certification de logiciel]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Tom Hirschowitz&lt;br /&gt;
* Résumé: [[https://coq.inria.fr Coq]] est un logiciel de mathématiques sur ordinateur, grâce auquel des programmes élaborés ont pu être certifiés ces dernières années.&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# prendre en main le logiciel [[https://coq.inria.fr Coq]] de démonstration sur ordinateur,&lt;br /&gt;
*# programmer certaines démonstrations basiques en Coq,&lt;br /&gt;
*# suivre le début du cours [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]],&lt;br /&gt;
* Pour aller plus loin : Software Foundations est un cours assez long et très bien fait, il y aura suffisamment à faire. Eventuellement, selon l&#039;intérêt de l&#039;étudiant, étude des fondements mathématiques de Coq.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]]&lt;br /&gt;
** [[https://coq.inria.fr Coq]]&lt;br /&gt;
&lt;br /&gt;
== [[Fouille de données textuelles à partir des &amp;quot;Exercices de style&amp;quot; de R. Queneau]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Laurent Vuillon&lt;br /&gt;
* Résumé: L&#039;idée de ce projet est de se familiariser avec les techniques de fouille de données textuelles à partir des &amp;quot;Exercices de style&amp;quot; de R. Queneau (https://fr.wikipedia.org/wiki/Exercices_de_style). On cherchera à comprendre la structure du vocabulaire du corpus de textes, à utiliser les techniques de TF/IDF pour extraire les mots significatifs du corpus puis à tester les techniques de LDA (Allocation de Dirichlet latente) pour extraire automatiquement les thématiques du corpus afin de construire des regroupements par thème. On pourra également proposer des visualisations des résultats afin de rendre accessible visuellement l&#039;analyse de données produite sur le corpus de documents.&lt;br /&gt;
* Objectifs: Introduction à la fouille de données au travers d&#039;un cas pratique&lt;br /&gt;
* Pour aller plus loin&lt;br /&gt;
** http://blogperso.univ-rennes1.fr/stephane.tuffery/&lt;br /&gt;
** http://www.editionstechnip.com/en/catalogue-detail/1005/data-mining-et-statistique-decisionnelle.html&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** https://fr.wikipedia.org/wiki/Exploration_de_donn%C3%A9es&lt;br /&gt;
** https://fr.wikipedia.org/wiki/TF-IDF&lt;br /&gt;
** &amp;quot;Recherche d&#039;information : applications, modèles et algorithmes; Data mining, décisionnel et big data&amp;quot; de Amini et Gaussier aux éditions Eyrolles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Transformées en distance, diagramme de Voronoi et applications en geometry processing]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Jacques-Olivier Lachaud&lt;br /&gt;
* Résumé: Les nuages de points constituent une source de données géométriques importantes (cf LIDAR scanner, 3D scanner) et qui permet de construire des modèles géométriques 3D d&#039;objets réels. La difficulté est de transformer ces nuages de points en des surfaces (souvent des surfaces triangulées, c&#039;est-à-dire des triangles collés entre eux). Un outil essentiel dans ce processus est la transformée en distance, le diagramme de Voronoi (et son dual la triangulation de Delaunay). A partir de ces outils, des algorithmes existent pour reconstruire les surfaces, estimer la géométrie du nuage de point (sa normale par exemple), etc.&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# Comprendre ce qu&#039;est une distance, une transformée en distance, et un diagramme de Voronoi. Comprendre ce qu&#039;est la stabilité d&#039;une fonction.&lt;br /&gt;
*# Identifier les propriétés des diagrammes de Voronoi, de leur dual la triangulation de Delaunay, et comprendre leurs variantes comme les diagrammes de puissance&lt;br /&gt;
*# Identifier le lien avec l&#039;axe médian et les squelettes&lt;br /&gt;
*# Décrire les principaux algorithmes de calcul des transformées en distance et du diagramme de Voronoi, pour des nuages de point quelconques ou pour des nuages de points à coordonnées entières.&lt;br /&gt;
*# Présenter un algorithme de reconstruction de surface utilisant le diagramme de Voronoi&lt;br /&gt;
*# Coder un algorithme de calcul du diagramme de Voronoi et, si le temps le permet, un algorithme de reconstruction de surface.&lt;br /&gt;
&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Voronoi_diagram Diagramme de Voronoi Wikipedia]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Distance_transform Transformée en distance Wikipedia]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Topological_skeleton Squelette Wikipedia]]&lt;br /&gt;
** [[http://dgtal.org/doc/nightly/moduleVolumetric.html Transformées discrètes en distance DGtal]]&lt;br /&gt;
&lt;br /&gt;
== [[Pavages de Penrose]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur : Pierre Hyvernat&lt;br /&gt;
* Résumé : le &amp;quot;cerf-volant&amp;quot; et la &amp;quot;fléchette&amp;quot; de Penrose sont deux tuiles qui permettent de recouvrir le plan, mais uniquement de manière non-périodique. Autrement dit, les pavages correspondants ne sont pas obtenus en répétant un même motif de     manière régulière. A cause de ceci, il n&#039;est pas évident de générer un tel      pavage. &lt;br /&gt;
&lt;br /&gt;
[[Fichier:P2.png]]&lt;br /&gt;
&lt;br /&gt;
* Objectifs&lt;br /&gt;
*# comprendre les notion de pavage périodique, non périodique et apériodique,&lt;br /&gt;
*# comprendre la méthode &amp;quot;inflation / déflation&amp;quot; pour générer des pavages de    Penrose des différents types,                                                   &lt;br /&gt;
*# comprendre le lien entre les 2 (ou 3) types de pavage de Penrose             &lt;br /&gt;
*# écrire un programme permettant de générer de tels pavages : avec la méthode  &amp;quot;inflation / déflation&amp;quot; et avec la méthode &amp;quot;grille de de Bruijn&amp;quot;&lt;br /&gt;
*# utiliser ces méthodes pour générer d&#039;autres types de pavages apériodique.&lt;br /&gt;
&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Pavage_de_Penrose pavage de Penrose (wikipedia]]&lt;br /&gt;
** [[https://www.maa.org/sites/default/files/pdf/pubs/focus/Gardner_PenroseTilings1-1977.pdf Penrose Tiling (Marting Gardner, en anglais)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Algorithmes d&#039;analyse syntaxique]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur : Pierre Hyvernat&lt;br /&gt;
&lt;br /&gt;
* Résumé : le code source d&#039;un programme, d&#039;un fichier de configuration d&#039;un serveur de base de données ou le code d&#039;une page web sont des données &#039;&#039;textuelles&#039;&#039; et &#039;&#039;structurées&#039;&#039;. Il est possible de définir exactement quelles données sont correctes, et quelle est leur signification. (Cela est beaucoup plus difficile pour des textes en langue naturelle par exemple.) En ce sens, il est possible de lire, d&#039;interpréter ces données à l&#039;aide d&#039;un programme. On parle &#039;&#039;d&#039;analyseur syntaxique&#039;&#039; ou de &#039;&#039;parseur&#039;&#039;. Il existe de nombreux outils pour faire ça automatiquement, mais il est parfois important (et toujours intéressant) de comprendre les mécanismes correspondant. C&#039;est ce que ce stage propose de faire.&lt;br /&gt;
&lt;br /&gt;
* Objectifs :&lt;br /&gt;
*# étudier la formalisation du problème à travers la notion de &#039;&#039;langage&#039;&#039; et les premiers étages de la hiérachie de Chomsky (langages réguliers et grammaires hors contexte).&lt;br /&gt;
*# comprendre le lien entre les langages et les automates (automates finis / automates à pile)&lt;br /&gt;
*# implémenter un parseur &amp;quot;from scratch&amp;quot; et le tester sur des petits exemples simples, &amp;quot;à la main&amp;quot;, soit en calculant &amp;quot;à la volée&amp;quot; la sémantique d&#039;un langage, soit en produisant des &amp;quot;arbres de syntaxe abstraits&amp;quot;, qui pourront être analysés par la suite,&lt;br /&gt;
*# comprendre les restrictions souvent imposées sur les grammaires afin d&#039;améliorer l&#039;efficacité du parseur (&#039;&#039;LL*(k)&#039;&#039;, &#039;&#039;LR&#039;&#039;, etc.)&lt;br /&gt;
*# à partir de là, de nombreuses pistes sont ouvertes :&lt;br /&gt;
*#* essayer d&#039;écrire un petit outils qui puisse lire une grammaire, et générer un parseur pour cette grammaire,&lt;br /&gt;
*#* comparer l&#039;approche &amp;quot;automate&amp;quot; avec l&#039;approche &amp;quot;combinateurs&amp;quot; et &amp;quot;parseur récursifs&amp;quot;&lt;br /&gt;
*#* améliorer l&#039;efficacité des parseurs produits&lt;br /&gt;
*#* ajouter des fonctionnalités,&lt;br /&gt;
*#* ...&lt;br /&gt;
&lt;br /&gt;
* Liens pour démarrer :&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Parsing page wikipedia &amp;quot;parsing&amp;quot;]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Recursive_descent_parser page wikipedia &amp;quot;recursive descent parser&amp;quot;]]&lt;br /&gt;
** Le livre référence sur le parsing est probablement &amp;quot;Compilers: Principles, Techniques, and Tools&amp;quot; de Aho, Sethi et Ullman (le &amp;quot;dragon book&amp;quot;)&lt;br /&gt;
** [[https://web.stanford.edu/class/archive/cs/cs143/cs143.1128/ exemples de notes cours de compilation]]&lt;br /&gt;
&lt;br /&gt;
= Sujets réalisés (2016-2017) =&lt;br /&gt;
&lt;br /&gt;
* [[Algorithme de rendu de scène 3D par Z-buffer]]&lt;br /&gt;
* [[Traitement d&#039;image]]&lt;br /&gt;
* [[Nim et la théorie des jeux impartiaux]]&lt;br /&gt;
* [[Calculabilité et modèles de calcul]]&lt;br /&gt;
* [[Génération et résolution de labyrinthes]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Sujets proposés (2016-2017) =&lt;br /&gt;
&lt;br /&gt;
== [[Algorithme de rendu de scène 3D par Z-buffer]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Jacques-Olivier Lachaud&lt;br /&gt;
* Résumé: Le Z-buffer est un algorithme classique de rendu de scène 3D. C&#039;est celui (avec quelques variantes) qui est implémenté dans nos cartes graphiques 3D et qui permet de visualiser des scènes extrêmement complexes en temps réel (typiquement 24 image/s).&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# décrire le principe de la projection 3D vers 2D&lt;br /&gt;
*# décrire la rastérisation des triangles sur une image en pixel&lt;br /&gt;
*# expliquer le principe du Z-buffer qui permet de gérer le fait que certains objets sont cachés par d&#039;autres&lt;br /&gt;
*# expliquer comment les couleurs sont calculées par pixel&lt;br /&gt;
*# indiquer les qualités et limitations de l&#039;algorithme&lt;br /&gt;
* Pour aller plus loin&lt;br /&gt;
*# mettre du code démo (WebGL) avec quelques explications sur le pipeline graphique OpenGL&lt;br /&gt;
*# expliquer comment on peut utiliser cet algorithme pour calculer des ombres (shadow map)&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Z-buffer Wikipedia]]&lt;br /&gt;
** [[https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/overview-rasterization-algorithm Scratch a pixel]]&lt;br /&gt;
&lt;br /&gt;
== [[Traitement d&#039;image]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Jacques-Olivier Lachaud&lt;br /&gt;
* Résumé: Le traitement d&#039;image rassemble tous les algorithmes utilisés pour transformer les images, les améliorer, éliminer certaines perturbations, augmenter ou diminuer le contraste, changer les couleurs vers d&#039;autres couleurs, éliminer le flou ou les yeux rouges, faire du cartooning pour un rendu moins photo-réaliste, etc.&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# identifier les grandes familles de traitement: restauration, égalisation, élimination du flou de déplacement, segmentation, etc&lt;br /&gt;
*# identifier les grandes familles de techniques: filtrage spatial, filtrage fréquentiel, optimisation, etc&lt;br /&gt;
*# comprendre les points communs et différences entre le traitement des images noir et blanc et le traitement des images couleurs.&lt;br /&gt;
*# choisir un ou deux algorithmes de traitement et les expliquer en détails&lt;br /&gt;
* Pour aller plus loin&lt;br /&gt;
*# Coder un algorithme de traitement d&#039;image simple (e.g, un filtrage médian, ou un algo qui transporte les couleurs d&#039;une photo vers une autre photo)&lt;br /&gt;
&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Traitement_d%27images Wikipedia]]&lt;br /&gt;
** [[http://www.ipol.im/ Image Processing on line]] (permet de tester en ligne des algorithmes sur vos images)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== [[Nim et la théorie des jeux impartiaux]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Pierre Hyvernat&lt;br /&gt;
&lt;br /&gt;
* Étudiant : Luca Chapelle&lt;br /&gt;
&lt;br /&gt;
* Le jeu de Nim (aussi appelé jeu des allumettes) est l&#039;un des premiers jeux ayant été analysé mathématiquement (par Charles Bouton en 1901). Les stratégies gagnantes peuvent être calculées en utilisant le développement en base 2 des nombres, et l&#039;opération d&#039;&amp;quot;addition de Nim&amp;quot; (XOR). La théorie de ce type de jeux (jeux &amp;quot;impartiaux&amp;quot;) est assez simple, mais de nombreuses instances de jeux sont encore non résolues.&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# comprendre la théorie du jeu de Nim (et la programmer)&lt;br /&gt;
*# comprendre le théorème de Sprague Grundy qui montre que tout jeu impartial est équivalent à un jeu de nim&lt;br /&gt;
*# regarder quelques autres exemples de tels jeux : jeu de Nim déguisés, ou jeux véritablement différents&lt;br /&gt;
*# programmer une version naịve de recherche de stratégie basée sur le théorème de Sprague-Grundy pour quelques jeux&lt;br /&gt;
&lt;br /&gt;
* Liens pour commencer&lt;br /&gt;
** [https://fr.wikipedia.org/wiki/Jeux_de_Nim jeu de Nim]&lt;br /&gt;
** [https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_de_Sprague-Grundy théorème de Sprague Grundy]&lt;br /&gt;
** [https://fr.wikipedia.org/wiki/Jeu_de_Grundy jeu de Grundy]&lt;br /&gt;
&lt;br /&gt;
== La suite de Conway et la classification périodique des &amp;quot;éléments&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur : Pierre Hyvernat&lt;br /&gt;
* La suite de Conway est la suite suivante : 1 ; 11 ; 21 ; 1211 ; 111221 ; ... Chaque terme est obtenu en &amp;quot;lisant&amp;quot; le terme précédent.                                                                                                                                                            &lt;br /&gt;
** &amp;quot;1&amp;quot; : un &amp;quot;1&amp;quot; -&amp;gt; 11&lt;br /&gt;
** &amp;quot;11&amp;quot; : deux &amp;quot;1&amp;quot; -&amp;gt; 21&lt;br /&gt;
** &amp;quot;21&amp;quot; : un &amp;quot;2&amp;quot;, un &amp;quot;1&amp;quot; -&amp;gt; 1211&lt;br /&gt;
** &amp;quot;1211&amp;quot; : un &amp;quot;1&amp;quot;, un &amp;quot;2&amp;quot;, deux &amp;quot;1&amp;quot; -&amp;gt; 111221&lt;br /&gt;
** etc.&lt;br /&gt;
Cette suite possède des propriétés étonantes données par le théorème &amp;quot;chimique&amp;quot;, le théorème &amp;quot;arithmétique&amp;quot; et le théorème &amp;quot;cosmologique&amp;quot;.&lt;br /&gt;
* Objectifs :                                                                                                                                                                                                                  &lt;br /&gt;
*# comprendre les énoncés de ces théorèmes, et l&#039;idée de la preuve du premier.                    &lt;br /&gt;
*# programmer la suite de Conway pour retrouver la classification des &amp;quot;atomes&amp;quot;&lt;br /&gt;
*# écrire un programme pour calculer expérimentalement une approximation de la constante &amp;quot;lambda&amp;quot; ainsi que des fréquences respectives des différents atomes.&lt;br /&gt;
*# écrire un programme pour calculer la suite de Robinson, une variante plus simple de la suite de Conway&lt;br /&gt;
&lt;br /&gt;
* Liens pour commencer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Suite_de_Conway suite de Conway]]&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Suite_de_Robinson suite de Robinson]]&lt;br /&gt;
&lt;br /&gt;
== Initiation à la démonstration sur ordinateur et certification de logiciel ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Tom Hirschowitz&lt;br /&gt;
* Résumé: [[https://coq.inria.fr Coq]] est un logiciel de mathématiques sur ordinateur, grâce auquel des programmes élaborés ont pu être certifiés ces dernières années.&lt;br /&gt;
* Objectifs: &lt;br /&gt;
*# prendre en main le logiciel [[https://coq.inria.fr Coq]] de démonstration sur ordinateur,&lt;br /&gt;
*# programmer certaines démonstrations basiques en Coq,&lt;br /&gt;
*# suivre le début du cours [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]],&lt;br /&gt;
* Pour aller plus loin : Software Foundations est un cours assez long et très bien fait, il y aura suffisamment à faire. Eventuellement, selon l&#039;intérêt de l&#039;étudiant, étude des fondements mathématiques de Coq.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://www.cis.upenn.edu/~bcpierce/sf Software Foundations]]&lt;br /&gt;
** [[https://coq.inria.fr Coq]]&lt;br /&gt;
&lt;br /&gt;
== [[Calculabilité et modèles de calcul]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Rodolphe Lepigre&lt;br /&gt;
* Résumé: Une fonction f sur l&#039;ensemble des entiers naturels est dite calculable s&#039;il existe une procedure effective (ou un algorithme) qui permet, étant donné un entier n, de calculer f(n) en temps fini. Il existe divers modèles de calcul qui permettent de représenter toutes les fonctions calculables : machines de Turing, λ-calcul, automates cellulaires, ...&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# comprendre la notion de fonction calculable,&lt;br /&gt;
*# comparer l&#039;ensemble des fonctions à l&#039;ensemble des fonctions calculables,&lt;br /&gt;
*# regarder et comparer quelque modèles de calcul,&lt;br /&gt;
*# programmer un modèle de calcul et comprendre les limitations pratiques.&lt;br /&gt;
&lt;br /&gt;
* Liens pour commencer:&lt;br /&gt;
** https://fr.wikipedia.org/wiki/Calculabilité&lt;br /&gt;
** https://fr.wikipedia.org/wiki/Machine_de_Turing&lt;br /&gt;
** https://fr.wikipedia.org/wiki/Lambda-calcul&lt;br /&gt;
** https://fr.wikipedia.org/wiki/Jeu_de_la_vie&lt;br /&gt;
&lt;br /&gt;
== [[Génération et résolution de labyrinthes]] ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: &amp;lt;strike&amp;gt;Jacques-Olivier Lachaud&amp;lt;/strike&amp;gt; Xavier Provençal&lt;br /&gt;
* Résumé: On veut générer des labyrinthes aussi grands et complexes que possible, avec des murs dans une grille carré voire d&#039;autres domaines. Comment faire pour qu&#039;il y ait toujours un chemin de l&#039;entrée à la sortie ? Comment faire pour qu&#039;il n&#039;y ait qu&#039;un chemin ? Ensuite, comment trouver la sortie quand on est perdu dans le labyrinthe.&lt;br /&gt;
* Objectifs:&lt;br /&gt;
*# Comprendre comment représenter avec une structure de données un labyrinthe&lt;br /&gt;
*# Voir le lien avec la théorie des graphes et voir que le problème se résout de la même façon pour des grilles carrées, hexagonales ou autres.&lt;br /&gt;
*# Comprendre l&#039;algorithme d&#039;arbre couvrant minimum&lt;br /&gt;
*# Comprendre le principe du parcours en profondeur et de la récursivité&lt;br /&gt;
* Pour aller plus loin&lt;br /&gt;
*# coder la génération d&#039;un labyrinthe et sa visualisation&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Mod%C3%A9lisation_math%C3%A9matique_d%27un_labyrinthe Wikipedia]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Maze_generation_algorithm Version anglaise plus complète]]&lt;br /&gt;
&lt;br /&gt;
== Pavages par polyomino ==&lt;br /&gt;
&lt;br /&gt;
* Tuteur: Xavier Provençal&lt;br /&gt;
* Résumé : On s&#039;intéresse aux pavages du plan par des tuiles formées de petits carrés collés les uns aux autres, appelé &amp;quot;polyominos&amp;quot;. Étant donné une tuile, peut-on paver le plan ? Si oui, avec quelles opérations (translation et/ou rotations et/ou réflexions) Une fois un pavage réalisé, on observe ses propriétés. Quelles symétries ? Le pavage est-il identique du point de vue de chacune des tuiles ? Si ce n&#039;est pas le cas, en combien de classes peut-on diviser ces tuiles ?&lt;br /&gt;
On s&#039;intéressera aussi à des propriétés connexes. Au lieu de paver tout le plan, on peut essayer de paver une région finie donnée. Plus localement, peut-on encercler complètement une tuile avec des copies d&#039;elle-même, sans former de trous ? Si oui, peut-on faire de même avec la proto-tuile formée par la tuile de départ et toutes ses copies ? Si oui, combien de fois peut-on répéter l&#039;opération ?&lt;br /&gt;
* Objectifs :&lt;br /&gt;
*# Comprendre les différentes classes de pavages (isohédral, k-isohédral, anisohédral).&lt;br /&gt;
*# Pour chacun des sept types de pavages &amp;quot;isohédraux&amp;quot;, comprendre le lien entre les symétries du pavages et la caractérisation des tuiles qui le réalisent.&lt;br /&gt;
*# Pour un pavage k-isohédral, identifier les &amp;quot;classes d&#039;équivalences&amp;quot; et le &amp;quot;domaine fondamental&amp;quot;.&lt;br /&gt;
* Pour aller plus loin :&lt;br /&gt;
*# Coder la génération de tuiles capables de paver le plan en fonction pour une classe de pavages donnée.&lt;br /&gt;
*# Étudier et implémenter certains algorithmes pour le pavages d&#039;un domaine fini.&lt;br /&gt;
* Liens pour démarrer&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Polyomino Polyomino]]&lt;br /&gt;
** [[https://en.wikipedia.org/wiki/Polyomino Polyomino (en)]]&lt;br /&gt;
** [[https://fr.wikipedia.org/wiki/Pavage_par_des_polygones_r%C3%A9guliers Pavages]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11877</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11877"/>
		<updated>2019-05-22T16:44:31Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La complexité de ce programme est de l&#039;ordre de ln(N), car le trie des liste domine.&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.bmp&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. Pour l&#039;image C, son format par défaut est en bmp.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11862</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11862"/>
		<updated>2019-05-22T11:35:31Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.jpg&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. De même pour l&#039;image C.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation4b.jpg&amp;diff=11861</id>
		<title>Fichier:Experimentation4b.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation4b.jpg&amp;diff=11861"/>
		<updated>2019-05-22T11:32:43Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation4a.jpg&amp;diff=11860</id>
		<title>Fichier:Experimentation4a.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation4a.jpg&amp;diff=11860"/>
		<updated>2019-05-22T11:31:50Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3c.jpg&amp;diff=11859</id>
		<title>Fichier:Experimentation3c.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3c.jpg&amp;diff=11859"/>
		<updated>2019-05-22T11:31:20Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3b.jpg&amp;diff=11858</id>
		<title>Fichier:Experimentation3b.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3b.jpg&amp;diff=11858"/>
		<updated>2019-05-22T11:30:49Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3a.jpg&amp;diff=11857</id>
		<title>Fichier:Experimentation3a.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation3a.jpg&amp;diff=11857"/>
		<updated>2019-05-22T11:30:20Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : *Source de l&amp;#039;image A : https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340
*Source de l&amp;#039;image B : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*Source de l&#039;image A : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11856</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11856"/>
		<updated>2019-05-22T11:29:14Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.jpg&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. De même pour l&#039;image C.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour les ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;br /&gt;
*Source de l&#039;image A bis : [[https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340 https://www.deviantart.com/rockspire/art/Canyon-concept-art-187906340]]&lt;br /&gt;
*Source de l&#039;image B bis : [[https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750 https://vignette.wikia.nocookie.net/starwars/images/b/bd/All_Terrain_Exploration_Droid.png/revision/latest?cb=20140511072750]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation2b.jpg&amp;diff=11855</id>
		<title>Fichier:Experimentation2b.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation2b.jpg&amp;diff=11855"/>
		<updated>2019-05-22T11:24:37Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation2a.jpg&amp;diff=11854</id>
		<title>Fichier:Experimentation2a.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation2a.jpg&amp;diff=11854"/>
		<updated>2019-05-22T11:23:16Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : *Source de l&amp;#039;image A : https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1b.jpg&amp;diff=11853</id>
		<title>Fichier:Experimentation1b.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1b.jpg&amp;diff=11853"/>
		<updated>2019-05-22T11:21:00Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1a.jpg&amp;diff=11852</id>
		<title>Fichier:Experimentation1a.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1a.jpg&amp;diff=11852"/>
		<updated>2019-05-22T11:18:08Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1a.jpg&amp;diff=11851</id>
		<title>Fichier:Experimentation1a.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Experimentation1a.jpg&amp;diff=11851"/>
		<updated>2019-05-22T11:16:52Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : Source de l&amp;#039;image A : [https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]
Source de l&amp;#039;image B : [https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source de l&#039;image A : [https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]&lt;br /&gt;
Source de l&#039;image B : [https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11850</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11850"/>
		<updated>2019-05-22T11:14:02Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : /* Expérimentations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.jpg&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. De même pour l&#039;image C.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour les ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11849</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11849"/>
		<updated>2019-05-22T11:13:18Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.jpg&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. De même pour l&#039;image C.&lt;br /&gt;
&lt;br /&gt;
== Expérimentations ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
Si l&#039;on fait l&#039;inverse de ce qui a été fait précédemment, en prenant l&#039;image du graffiti en palette, on obtient une image de sortie chargée en &amp;quot;bruit&amp;quot;, du fait du fort contraste de couleurs que présente le graffiti.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation1a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation1b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant une image palette présentant toute les nuances entre le noir et le blanc, l&#039;image de sortie est parfaitement net, du fait de sa linéarité.&amp;lt;/br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation2a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation2b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
En prenant deux images aux couleurs assez homogènes mais très contrastées entre elles, l&#039;image de sortie est plutôt correcte malgré quelques imperfections sur certaines couleurs (notamment les zones sombres).&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut aussi inverser le rôle des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation3c.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
On peut essayer de prendre les deux images recolorisées entre elles pour les ré-effectuer un transfert, et observer si l&#039;image de sortie est proche de l&#039;originale.&amp;lt;/br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation4a.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:experimentation4b.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Les couleurs sont reconnues dans leur globalité, mais l&#039;information dite &amp;quot;géographique&amp;quot; est perdue, vu que chaque pixel est traité indépendamment des autres.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp2.jpg&amp;diff=11848</id>
		<title>Fichier:Transport-simp2.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp2.jpg&amp;diff=11848"/>
		<updated>2019-05-21T20:46:14Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : Chardonnet a téléversé une nouvelle version de Fichier:Transport-simp2.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Dilemme_du_prisonnier&amp;diff=11771</id>
		<title>Dilemme du prisonnier</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Dilemme_du_prisonnier&amp;diff=11771"/>
		<updated>2019-05-19T13:42:18Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : Correction d&amp;#039;absence de ponctuation à un certain endroit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Le dilemme du prisonnier à été inventer en 1950 par Albert William Tucker et fait parti de la théorie des jeux qui est un domaine des mathématiques étudiant les interactions entre différents individus qui sont conscients ou non de ces interactions. Ils devront donc faire des choix dont ils sont conscients ou non lors de ces interactions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Le dilemme du prisonnier ==&lt;br /&gt;
&lt;br /&gt;
Les individus sont soumis dans le dilemme du prisonnier à une interaction où ils ont deux choix : soit ils coopèrent avec l’autre individu, soit ils le trahissent. Les individus sont récompensés selon la matrice des Paiements suivante :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Tableau matrice paiements.PNG]]&lt;br /&gt;
&lt;br /&gt;
L’intérêt de la configuration actuelle de la matrice des Paiements actuelle est que les individus ont un intérêt certain à trahir l’autre mais que la coopération est la meilleur option pour les deux individus. On représente l’intérêt à trahir par rapport à la coopération par la variable B qui dans notre exemple est égale à 1,85. &lt;br /&gt;
&lt;br /&gt;
Afin de simplifier notre modèle nous ne considérerons que deux comportements possibles qui sont :&lt;br /&gt;
&lt;br /&gt;
-Le Croyant qui coopérera systématiquement&lt;br /&gt;
&lt;br /&gt;
-Le Traître qui trahira systématiquement&lt;br /&gt;
&lt;br /&gt;
== Spatialisation du Dilemme du prisonnier ==&lt;br /&gt;
&lt;br /&gt;
Nous spatialisons le dilemme du prisonnier afin d’expliquer en partie des observations dans le vivant où les êtres vivants coopèrent entre eux alors qu’ils ont tout à y gagner en ne le faisant pas. Pour étayer nos propos on propose la citation suivante :« The prisoners’ Dilemma is an interesting metaphor for the fundamental biological problem of how cooperative behaviour may evolve and be maintained »([https://www.researchgate.net/publication/216634494_Evolutionary_Games_and_Spatial_Chaos Nowak, M.A. et May, R.M. 1992. Evolutionary games and spatial chaos]). En spatialisant le dilemme du prisonnier nous pouvons observer l’évolution des pratiques dans des situations variées. Il est à noter que nous pouvons aussi établir des liens entre les domaines de l’économie et de la sociologie notamment.&lt;br /&gt;
&lt;br /&gt;
Les prisonniers sont au voisinage de Moore (8 voisins) de tel sorte à ce que dans l’espace les voisins d’un prisonnier lambda soient disposés de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
1       2       3&lt;br /&gt;
&lt;br /&gt;
4       P       5&lt;br /&gt;
&lt;br /&gt;
6       7       8&lt;br /&gt;
&lt;br /&gt;
L’espace dans lequel ils évoluent est un espace toroïdale (bordures ouvertes) en forme de carré de dimension n*n. On peut aussi le représenter comme une matrice carré avec les bordures qui communiquent entre elles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
À Chaque tour les prisonniers vont jouer au dilemme du prisonnier avec chacun de leurs voisins. Ils obtiendront un score conformément à leurs choix et à la matrice des Paiements. Puis chacun leur tour mettre à jour leur stratégie en fonction du score des voisins.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir visualiser l&#039;évolution de notre espace nous avons créer un programme en Java afin de profiter des aspects suivant de Java:&lt;br /&gt;
&lt;br /&gt;
Le premier est la programmation objet, cela nous permet de diviser la complexité de notre programme dans plusieurs objets interagissants entre eux. Nous pouvons aussi créer des abstractions d&#039;objets qui nous permettent d&#039;avoir des objets qui ont des comportements différents les uns des autres mais ayants tous des points communs ce qui permet de les manipulés plus facilement.&lt;br /&gt;
&lt;br /&gt;
Le second est la bibliothèque Abstract Windows Toolkit (ou AWT pour faire plus court). Qui nous permet de faire sans trop de problèmes une fenêtre personnalisable qui affiche des composants grapihques. Ces composants étant eux mêmes variées, on utilisera surtout les propriétés du composant Canvas dans ce programme. Grâce à l’héritage permis par la programmation objet nous pouvons créer nos propres composants graphiques pour afficher nos résultats.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notre programme crée donc une fenêtre qui affiche les prisonniers en fonction de leur stratégie actuelle et de leur dernière stratégie.Le code couleur est le suivant :&lt;br /&gt;
&lt;br /&gt;
-en rouge les Traîtres qui l’ont été pendant 2 tours consécutifs&lt;br /&gt;
&lt;br /&gt;
-en jaune les Croyants qui sont devenus Traîtres&lt;br /&gt;
&lt;br /&gt;
-en vert les Traîtres devenus Croyants&lt;br /&gt;
&lt;br /&gt;
-en bleu les Croyants qui l’ont été pendant 2 tours consécutifs&lt;br /&gt;
&lt;br /&gt;
== Une expérience intéressante ==&lt;br /&gt;
&lt;br /&gt;
On propose dans cette partie de commencer à étudier un cas en particulier. Dans cette première expérience nous fixons B à 1,85 et plaçons un traître au milieu de croyants dans une grille de 301 par 301. Nous pensons que cette configuration donnera des résultats intéressants car B n&#039;est pas assez grand pour permettre une domination complète des Traîtres ou pas assez petit pour permettre une domination complète des Croyants.&lt;br /&gt;
&lt;br /&gt;
Après quelques tours de la simulation nous observons l&#039;image suivante:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen_première_exp.PNG]]&lt;br /&gt;
&lt;br /&gt;
Nous pouvons voir grâce à la bordure verte que le carré de traîtres au centre de l&#039;image est en train de rétrécir alors que dans les coins des îlots de traîtres apparaissent comme nous le montre la grand quantité de jaune.&lt;br /&gt;
&lt;br /&gt;
Nous passons sous silence quelques tours pour arriver à la situation suivante:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen première exp 2.PNG]]&lt;br /&gt;
&lt;br /&gt;
Nous pouvons voir à présent que les comportements dans la simulation varient beaucoup comme témoignent l&#039;abondance de prisonniers affichés en jaune et en vert.&lt;br /&gt;
&lt;br /&gt;
Lors du déroulé de cette simulation nous avons pus récolter C qui est le rapport entre le nombre de croyants dans la matrice sur le nombre de prisonniers au total. Cette variable nous permettra de visualiser l&#039;évolution du nombre de croyants dans la simulation rapidement. Nous allons maintenant montrer son évolution au court du temps dans la simulation.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen Graph_première exp.PNG]]&lt;br /&gt;
&lt;br /&gt;
Nous pouvons ainsi observer sur le graphique que C semble tendre vers environ 0.3 montrant de ce fait que la simulation est dominé par les traîtres mais que les croyants résistent tout de même. Les variations de C ne sont pas de ce que l&#039;on observe sur le graphique et la simulation cycliques ce qui veut dire que même si le nombre de croyants semble à peut près stable il n&#039;en reste pas moins fluctuant.&lt;br /&gt;
&lt;br /&gt;
== Automatisation des expériences ==&lt;br /&gt;
&lt;br /&gt;
Nous avons pus observer une simulation particulière mais nous devons maintenant pouvoir faire des observations autres que visuelles car nous n’avons pas le temps de le faire pour toutes les expériences permisses par notre modèle. On n’as alors décidé donc de créer un objet dans le programme pour extraire les données des expériences et nous les résumées. Nous ne montrerons toutefois que les expériences que l’on juge intéressantes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous voulons tout d&#039;abord mesurer l&#039;influence de B sur l&#039;évolution d&#039;une répartition aléatoire. Pour cela nous fixerons les paramètres suivants pour chaque simulation. Dans chaque simulation on aura systématiquement 10% de traîtres répartis aléatoirement parmi 90% de croyants. La dimension des matrices sera de 200*200. Nous ferons variez B entre 1.75 et 2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour un B appartenant à [1.75;1.8[ On observe la simulation suivante au bout de 400 tours:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen_B_1,75_10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
On observe des réseaux de traîtres interconnectés entre eux mais pouvant être indépendants avec une taille minimale d&#039;un carré de 4 traîtres. On observe aussi des zones ou les prisonniers alternent entre traître et croyant, on les repères en cherchant les zones en jaune ou en vert.&lt;br /&gt;
&lt;br /&gt;
Le graphique de l&#039;évolution de C est le suivant:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen Graph B 1,75 10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
Ce graphique nous permet d&#039;affirmer que la simulation est à peut près stable car on observe toujours des petits chutes du nombre de croyants. C semble tendre par ailleurs vers 0.7.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour un B appartenant à [1.8;2[ On observe la simulation suivante au bout de 400 tours:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen B 1,9 10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
On observe une situation chaotique avec une majorité de Traîtres et des îlots de Croyants apparaissant et disparaissant au fur et à mesure de la simulation. On remarque aussi beaucoup de jaune et de verts sur les images cela nous montre que les comportements des prisonniers changent beaucoup.&lt;br /&gt;
&lt;br /&gt;
Le graphique de l&#039;évolution de C est le suivant:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen Graph B 1,9 10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
Ce graphique nous montre que la simulation n&#039;est pas stable mais que C se stabilise vers 0.3.&lt;br /&gt;
&lt;br /&gt;
Il est aussi à noter que sur les images B est à 1.9 et que plus B tend vers 1.8, C se stabilise vers 0.4.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour un B supérieur à 2 On observe la simulation suivante au bout de 400 tours:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen B 2 10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
On observe que les traîtres occupent quasiment tout l&#039;espace et que les croyants sont regroupés en îlots qui s&#039;étendent et se rétrécissent périodiquement.&lt;br /&gt;
&lt;br /&gt;
Le graphique de l&#039;évolution de C est le suivant:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Screen Graph B 2 10%.PNG]]&lt;br /&gt;
&lt;br /&gt;
Ce graphique nous montre que la simulation est très stable et que C tend vers 0.02.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Améliorations à apporter ==&lt;br /&gt;
&lt;br /&gt;
Nous n’avons pas exploré toutes les possibilités de notre modèle nous discuterons ici des améliorations à apportées à notre modèle.&lt;br /&gt;
&lt;br /&gt;
La première des améliorations que nous pourrions apporter pourrait être l’introduction de comportements avec un historique des actions passées de leurs voisins. Cela nous permettrait d’avoir des stratégies plus complexes à étudiées.&lt;br /&gt;
&lt;br /&gt;
La deuxième amélioration que nous pourrions apporter serait une amélioration au niveau du code. On proposerais de faire en sorte d’avoir un objet Stratégie qui se passerait de prisonnier en prisonnier et grâce à la programmation objet on pourrait créer des Stratégies variées avec peu de changements dans la structure du programme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
&lt;br /&gt;
[http://cormas.cirad.fr/fr/applica/dps.htm Lien vers le site du cormas]&lt;br /&gt;
&lt;br /&gt;
[https://www.researchgate.net/publication/216634494_Evolutionary_Games_and_Spatial_Chaos Lien vers l&#039;article original]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11699</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11699"/>
		<updated>2019-05-18T10:08:17Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
from PIL import Image&lt;br /&gt;
from random import randint&lt;br /&gt;
from operator import itemgetter&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
best_u = (0,0,0)&lt;br /&gt;
quality = 0&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot; Légende :&lt;br /&gt;
    im : image&lt;br /&gt;
    _RGB : objet image en rgb&lt;br /&gt;
    _rgb : liste de tuples rgb&lt;br /&gt;
    _ord : _rgb ordonné selon u&lt;br /&gt;
    u : vecteur tiré aléatoirement&lt;br /&gt;
    cost : coût&lt;br /&gt;
    _cur : courant &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def intro(fichier1, fichier2):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image&lt;br /&gt;
        Sortie : booléen&lt;br /&gt;
        Vérifie la compatibilité de taille et mode des deux images &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image A ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im1.format, im1.size, im1.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;=== Image B ===\nFormat : {}\nTaille : {}\nMode : {}&amp;quot;.format(im2.format, im2.size, im2.mode))&lt;br /&gt;
    print()&lt;br /&gt;
    if im1.size==im2.size and im1.mode==im2.mode :&lt;br /&gt;
        print(&amp;quot;Fichiers OK&amp;quot;)&lt;br /&gt;
        print()&lt;br /&gt;
        res = True&lt;br /&gt;
    else :&lt;br /&gt;
        print(&amp;quot;ATTENTION, incompatibilité des fichiers&amp;quot;)&lt;br /&gt;
        res = False&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_rgb(im):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : image&lt;br /&gt;
        Sortie : liste de tuples&lt;br /&gt;
        Convertie un objet image en liste rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im_RGB = im.convert(&#039;RGB&#039;)&lt;br /&gt;
    size = [ im_RGB.size[0], im_RGB.size[1] ]&lt;br /&gt;
    im_rgb = []&lt;br /&gt;
&lt;br /&gt;
    for j in range (0, size[1]):&lt;br /&gt;
        for i in range (0, size[0]):&lt;br /&gt;
            pix = im_RGB.getpixel((i, j))&lt;br /&gt;
            im_rgb.append(pix)&lt;br /&gt;
&lt;br /&gt;
    return(im_rgb)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def to_ord(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple (vecteur)&lt;br /&gt;
        Sortie : un tuple de deux listes de tuples&lt;br /&gt;
        Ordonne deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im1_ord = []&lt;br /&gt;
    im2_ord = []&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_rgb)):&lt;br /&gt;
        px1_ord = ( im1_rgb[i][0]*u[0] + im1_rgb[i][1]*u[1] + im1_rgb[i][2]*u[2], im1_rgb[i][0], im1_rgb[i][1], im1_rgb[i][2], i )&lt;br /&gt;
        im1_ord += [px1_ord]&lt;br /&gt;
&lt;br /&gt;
        px2_ord = ( im2_rgb[i][0]*u[0] + im2_rgb[i][1]*u[1] + im2_rgb[i][2]*u[2], im2_rgb[i][0], im2_rgb[i][1], im2_rgb[i][2], i )&lt;br /&gt;
        im2_ord += [px2_ord]&lt;br /&gt;
&lt;br /&gt;
    im1_ord.sort()&lt;br /&gt;
    im2_ord.sort()&lt;br /&gt;
&lt;br /&gt;
    for i in range(0,len(im1_ord)):&lt;br /&gt;
        #im2_ord[i][4] = im1_ord[i][4]&lt;br /&gt;
        #im2_ord[i] = tuple(im2_ord[i])&lt;br /&gt;
        im2_ord[i] = (im2_ord[i][0],im2_ord[i][1],im2_ord[i][2],im2_ord[i][3],im1_ord[i][4])&lt;br /&gt;
&lt;br /&gt;
    return(im1_ord, im2_ord)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cost(im1_rgb, im2_rgb, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples et un tuple&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le coût entre deux listes rgb selon un vecteur u &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    im12_ord = to_ord(im1_rgb, im2_rgb, u)&lt;br /&gt;
    im1_ord = im12_ord[0]&lt;br /&gt;
    im2_ord = im12_ord[1]&lt;br /&gt;
    dist = 0.0&lt;br /&gt;
    for i in range (0, len(im1_rgb)):&lt;br /&gt;
        dist += 1.0*(im1_ord[i][1]-im2_ord[i][1])**2 + 1.0*(im1_ord[i][2]-im2_ord[i][2])**2 + 1.0*(im1_ord[i][3]-im2_ord[i][3])**2&lt;br /&gt;
&lt;br /&gt;
    return dist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def best_cost(im1_rgb, im2_rgb):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrée : deux listes de tuples&lt;br /&gt;
        Sortie : un entier&lt;br /&gt;
        Calcul le meilleur coût entre deux listes rgb &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    u = (randint(-500,500), randint(-500,500), randint(-500,500)) # rand en flottant !&lt;br /&gt;
    best_cost = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    nb_u = 20 # nombre de tirages de u&lt;br /&gt;
    cost_list = [] # liste de tout les coûts que l&#039;on va calculer&lt;br /&gt;
    for i in range(0, nb_u):&lt;br /&gt;
        # print(&amp;quot;Calcul du meilleur coût en cours {}/{}&amp;quot;.format(i+1, nb_u))&lt;br /&gt;
        u = (randint(-500,500), randint(-500,500), randint(-500,500))&lt;br /&gt;
        cost_cur = cost(im1_rgb, im2_rgb, u)&lt;br /&gt;
        cost_list += [ cost_cur ]&lt;br /&gt;
&lt;br /&gt;
        # echo&lt;br /&gt;
        print( i+1, best_cost, cost_cur )&lt;br /&gt;
&lt;br /&gt;
        if cost_cur &amp;lt; best_cost :&lt;br /&gt;
            best_cost = cost_cur&lt;br /&gt;
            best_u = u&lt;br /&gt;
&lt;br /&gt;
    quality = min(cost_list) / max(cost_list)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;Meilleur vecteur u :&amp;quot;, best_u)&lt;br /&gt;
    print(&amp;quot;Qualité :&amp;quot;, quality)&lt;br /&gt;
    print()&lt;br /&gt;
    return best_cost&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def new_image(fichier1, fichier2, fichier3):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot; Entrées : deux fichiers image, puis le nom du fichier créé&lt;br /&gt;
        Sortie : rien&lt;br /&gt;
        Créer un fichier en transférant la palette du fichier 2 vers le fichier 1 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    global best_u&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    inittime = time.time()&lt;br /&gt;
    print (&#039;init&#039;,inittime)&lt;br /&gt;
&lt;br /&gt;
    im1 = Image.open(fichier1)&lt;br /&gt;
    im2 = Image.open(fichier2)&lt;br /&gt;
&lt;br /&gt;
    im1_rgb = to_rgb(im1)&lt;br /&gt;
    im2_rgb = to_rgb(im2)&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    intime = time.time() - inittime&lt;br /&gt;
    print (&#039;toRgb &#039;,intime)&lt;br /&gt;
    print()&lt;br /&gt;
&lt;br /&gt;
    best_cost(im1_rgb, im2_rgb)&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    intime = time.time() - inittime&lt;br /&gt;
    print (&#039;best_cost &#039;,intime)&lt;br /&gt;
&lt;br /&gt;
    # on récuperre les deux listes ordonnées par le meilleur vercteur&lt;br /&gt;
    var = to_ord(im1_rgb, im2_rgb, best_u)&lt;br /&gt;
    im1_ord = var[0]&lt;br /&gt;
    im2_ord = var[1]&lt;br /&gt;
    im3_rgb = [0]*len(im1_ord)&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    intime = time.time() - inittime&lt;br /&gt;
    print (&#039;to_ord &#039;,intime)&lt;br /&gt;
&lt;br /&gt;
    im2_ord.sort(key=itemgetter(4))&lt;br /&gt;
&lt;br /&gt;
    im3_rgb = im2_ord&lt;br /&gt;
    for i in range(0,len(im2_ord)):&lt;br /&gt;
        im3_rgb[i] = im2_ord[i][1:4]&lt;br /&gt;
        im3_rgb[i] = tuple(im3_rgb[i])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    intime = time.time() - inittime&lt;br /&gt;
    print (&#039;im3_rgb &#039;,intime)&lt;br /&gt;
&lt;br /&gt;
    im3 = Image.new(im1.mode, im1.size)&lt;br /&gt;
    im3.putdata(im3_rgb)&lt;br /&gt;
&lt;br /&gt;
    # echo&lt;br /&gt;
    intime = time.time() - inittime&lt;br /&gt;
    print (&#039;im3 &#039;,intime)&lt;br /&gt;
&lt;br /&gt;
    print()&lt;br /&gt;
    print(&amp;quot;sauvegarde du nouveau fichier&amp;quot;)&lt;br /&gt;
    im3.save(fichier3, &amp;quot;BMP&amp;quot;)&lt;br /&gt;
    print(&amp;quot;Fin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    im1.close()&lt;br /&gt;
    im2.close()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(fichier1, fichier2, fichier3):&lt;br /&gt;
    if intro(fichier1, fichier2):&lt;br /&gt;
        new_image(fichier1, fichier2, fichier3)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour exécuter le programme avec, par exemple, deux fichiers &amp;quot;imageA.jpg&amp;quot; et &amp;quot;imageB.jpg&amp;quot;, on entre dans l&#039;interpréteur la fonction&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;main(&amp;quot;imageA.jpg&amp;quot;, &amp;quot;imageB.jpg&amp;quot;, &amp;quot;imageC.jpg&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
L&#039;image C sera alors générée.&lt;br /&gt;
&lt;br /&gt;
Remarque : les deux fichiers d&#039;entrée ne sont pas obligatoirement au même format, mais doivent tout deux rester des images. De même pour l&#039;image C.&lt;br /&gt;
&lt;br /&gt;
== Expérimentation ==&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11680</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11680"/>
		<updated>2019-05-17T10:41:47Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver une technique permettant la meilleure recolorisation d&#039;une image A avec les pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B aux pixels de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise pour cela la technique du transport optimal qui va permettre d&#039;associer une valeur au transport entre pixels. Cette valeur s&#039;appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transport optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques unes :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transport de couleurs par coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transport de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;, car il offre une grande sensibilité quant à la distance entre deux pixels.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transport optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixel comme un point, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rang entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place de tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]] (A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]] (B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert, que l&#039;on abrège en rgb (pour red, green, blue). Chacune de ces composantes prend des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
Un pixel se note donc, par exemple :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;x = (x_{rouge},x_{vert},x_{bleu})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; quelconque.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal Simplification du transport optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme les pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le tranport doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert des couleurs ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certain vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associés pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]] (C)&lt;br /&gt;
&lt;br /&gt;
== Coefficients de perception ==&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
== Expérimentation ==&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11676</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11676"/>
		<updated>2019-05-17T09:55:55Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver la meilleure recolorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B au pixel de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise la technique du transport optimal, qui va permettre d&#039;associer une valeur au transport entre pixels, que l&#039;on appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]](A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]](B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme nos pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11645</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11645"/>
		<updated>2019-05-16T21:23:07Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver, au mieux, la recolorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B au pixel de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise la technique du transport optimal, qui va permettre d&#039;associer une valeur au transport entre pixels, que l&#039;on appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
À chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]](A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]](B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme nos pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11644</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11644"/>
		<updated>2019-05-16T21:08:49Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver, au mieux, la recolorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B au pixel de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise la technique du transport optimal, qui va permettre d&#039;associer une valeur au transport entre pixels, que l&#039;on appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]](A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]](B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme nos pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
*Source de l&#039;image A : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;br /&gt;
*Source de l&#039;image B : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imC.jpg&amp;diff=11643</id>
		<title>Fichier:Transport-imC.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imC.jpg&amp;diff=11643"/>
		<updated>2019-05-16T21:08:39Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imB.jpg&amp;diff=11642</id>
		<title>Fichier:Transport-imB.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imB.jpg&amp;diff=11642"/>
		<updated>2019-05-16T21:08:09Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : Source : https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source : [[https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/ https://www.flickr.com/photos/wolfgangstaudt/2252688630/in/photostream/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imA.jpg&amp;diff=11641</id>
		<title>Fichier:Transport-imA.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imA.jpg&amp;diff=11641"/>
		<updated>2019-05-16T21:07:25Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source : [[https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/ https://pixabay.com/photos/tag-street-art-mural-graffiti-1036811/]]&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imA.jpg&amp;diff=11640</id>
		<title>Fichier:Transport-imA.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-imA.jpg&amp;diff=11640"/>
		<updated>2019-05-16T21:06:13Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11639</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11639"/>
		<updated>2019-05-16T20:49:17Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le but du projet est de trouver, au mieux, la recolorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A. Pour cela il va falloir associer chacun des pixels de l&#039;image B au pixel de l&#039;image A dont il est le plus proche en terme de distance (dans l&#039;espace des couleurs).&lt;br /&gt;
&lt;br /&gt;
On utilise la technique du transport optimal, qui va permettre d&#039;associer une valeur au transport entre pixels, que l&#039;on appelle le coût.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différemment selon les domaines d&#039;application.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même aire et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est-à-dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manières de calculer un coût, qui sont chacune appropriées au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires (c&#039;est à dire composé du même nombre de pixels) où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]](1)&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
On a alors &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images, pour déterminer que tel pixel de l&#039;image B prendra la place tel pixel de l&#039;image A.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit sur l&#039;image (1)).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg|600px]](A)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imB.jpg|600px]](B)&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes les deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs, par convention, de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]L&#039;image A est en cyan et l&#039;image B en magenta.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal [https://www.lama.univ-savoie.fr/mediawiki/index.php/Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images#Simplification_du_transfert_optimal]. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme nos pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal, soit le meilleur coût possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11637</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11637"/>
		<updated>2019-05-16T17:52:45Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On appelle x les pixels de l&#039;image A et y les pixels de l&#039;image B.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ici, comme nos pixels x et y sont chacun représentés selon leurs trois composantes rgb, la distance au carré entre deux pixels est la somme des différences entre composantes correspondantes, le tout au carré, soit&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2=(x_{i_{rouge}}-y_{i_{rouge}})^2+(x_{i_{vert}}-y_{i_{vert}})^2+(x_{i_{bleu}}-y_{i_{bleu}})^2&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11635</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11635"/>
		<updated>2019-05-16T16:40:30Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-cout.jpg&amp;diff=11634</id>
		<title>Fichier:Transport-im-cout.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-cout.jpg&amp;diff=11634"/>
		<updated>2019-05-16T16:38:27Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-ord2.jpg&amp;diff=11633</id>
		<title>Fichier:Transport-im-ord2.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-ord2.jpg&amp;diff=11633"/>
		<updated>2019-05-16T16:23:18Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-ord1.jpg&amp;diff=11632</id>
		<title>Fichier:Transport-im-ord1.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im-ord1.jpg&amp;diff=11632"/>
		<updated>2019-05-16T16:22:57Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im3D-2.jpg&amp;diff=11631</id>
		<title>Fichier:Transport-im3D-2.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im3D-2.jpg&amp;diff=11631"/>
		<updated>2019-05-16T16:20:32Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11630</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11630"/>
		<updated>2019-05-16T16:20:03Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&lt;br /&gt;
&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg|600px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On se retrouve alors dans un cas similaire à la section Simplification du transport optimal. On peut ainsi faire correspondre les pixels entre eux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-ord2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im-cout.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-imC.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11629</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11629"/>
		<updated>2019-05-16T15:46:38Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points, on définit un vecteur unitaire &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11627</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11627"/>
		<updated>2019-05-16T15:19:43Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Puis on répète l&#039;opération, jusqu&#039;à que toutes les quantités de &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; soient transférées dans &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11626</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11626"/>
		<updated>2019-05-16T15:16:43Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (comme on le voit deux images plus haut).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11625</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11625"/>
		<updated>2019-05-16T15:12:34Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-simp2.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (ici, le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im3D-1.jpg&amp;diff=11624</id>
		<title>Fichier:Transport-im3D-1.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-im3D-1.jpg&amp;diff=11624"/>
		<updated>2019-05-16T15:11:30Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp2.jpg&amp;diff=11623</id>
		<title>Fichier:Transport-simp2.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp2.jpg&amp;diff=11623"/>
		<updated>2019-05-16T15:11:12Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp1.jpg&amp;diff=11622</id>
		<title>Fichier:Transport-simp1.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-simp1.jpg&amp;diff=11622"/>
		<updated>2019-05-16T15:09:56Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11621</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11621"/>
		<updated>2019-05-16T14:32:38Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&lt;br /&gt;
&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:transport-opti.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-simp1.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-simp2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (ici, le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-opti.jpg&amp;diff=11611</id>
		<title>Fichier:Transport-opti.jpg</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Fichier:Transport-opti.jpg&amp;diff=11611"/>
		<updated>2019-05-16T14:10:57Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11610</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11610"/>
		<updated>2019-05-16T14:08:33Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-opti.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-simp1.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-simp2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (ici, le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imA.jpg]][[Fichier:transport-imB.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-1.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im3D-2.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-ord.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-im-cout.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport-imC.jpg]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11609</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11609"/>
		<updated>2019-05-16T14:06:08Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_opti]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout doit se faire de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_simp1]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_simp2]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (ici, le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_imA]][[Fichier:transport_imB]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_im3D_1]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Mise en ordre des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_im3D_1]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_im_ord]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_im_cout]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Fichier:transport_imB]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11600</id>
		<title>Transport optimal par coupe 1D et transfert de couleurs entre images</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Transport_optimal_par_coupe_1D_et_transfert_de_couleurs_entre_images&amp;diff=11600"/>
		<updated>2019-05-15T14:06:46Z</updated>

		<summary type="html">&lt;p&gt;Chardonnet : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le transport optimal par coupe en une dimension peut être désigné, dans notre cas, par le fait de faire correspondre des listes de valeurs ordonnées selon une droite, pour ensuite les transférer l&#039;une vers l&#039;autre. Ici, les valeurs sont des pixels de couleur, et les listes de valeurs sont des images.&amp;lt;br/&amp;gt;&lt;br /&gt;
Ce principe permet de trouver, au mieux, la colorisation d&#039;une image A avec chaque pixels d&#039;une image B. Le résultat peut alors être assimilé à une réorganisation des pixels de l&#039;image B pour qu&#039;il ressemble le plus à l&#039;image A.&lt;br /&gt;
&lt;br /&gt;
== Principe du transfert optimal ==&lt;br /&gt;
&lt;br /&gt;
En théorie, le transport optimal peut se traduire par un déplacement de quantité d&#039;une position à une autre.&amp;lt;br/&amp;gt;&lt;br /&gt;
A chaque déplacement est associé un coût, que l&#039;on calcule différement selon les domaines.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut visualiser deux fonctions pour illustrer le propos.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On part du principe que nous sommes dans un cas discret, que &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;g&amp;lt;/math&amp;gt; sont de la même air et que leurs abscisses respectives sont nommées &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le but du transport optimal est de répartir les quantités des &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt; dans les quantités &amp;lt;math&amp;gt;g(y)&amp;lt;/math&amp;gt;. On note alors &amp;lt;math&amp;gt;q(x,y)&amp;lt;/math&amp;gt; la quantité &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; déplacée de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; à &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
On note le coût d&#039;un déplacement &amp;lt;math&amp;gt;c(x,y)&amp;lt;/math&amp;gt;. Le coup d&#039;un déplacement suivant une quantité est alors le produit entre la quantité déplacée et le coût du déplacement, soit &amp;lt;math&amp;gt;q(x,y)c(x,y)&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le tout se fait de manière optimale, c&#039;est à dire en ayant le coût global le plus bas possible. Coût global que l&#039;on note :&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;C=\sum_{i=1}^n q(x_i,y_i)c(x_i,y_i)&amp;lt;/math&amp;gt;, avec n le nombre d&#039;effectifs de &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; ou de &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Calcul du coût ===&lt;br /&gt;
&lt;br /&gt;
Il existe plusieurs manière de calculer un coût, qui sont chacune adéquat au domaine où elles s&#039;appliquent.&amp;lt;br/&amp;gt;&lt;br /&gt;
En voici quelques une :&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, le coût global est toujours optimal.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance au carré entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, la sensibilité à la distance parcourue est exponentielle (du fait de la fonction carré).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;math&amp;gt;c(x,y)=|x-y|^{1/2}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Soit la distance entre les deux points &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; et &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transfert de couleurs pas coupe 1D ==&lt;br /&gt;
&lt;br /&gt;
Le coût choisi pour le transfert de couleurs est &amp;lt;math&amp;gt;c(x,y)=|x-y|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Simplification du transfert optimal ===&lt;br /&gt;
&lt;br /&gt;
Dans le cadre de deux images de mêmes aires où l&#039;on veut transférer les pixels de l&#039;une à l&#039;autre, la notion de quantité disparaît.&amp;lt;br/&amp;gt;&lt;br /&gt;
En effet, on considère chaque pixels comme des points, et non des valeurs.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme il n&#039;y a plus de quantité, seul le coût d&#039;un déplacement importe pour obtenir un coût global optimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
Alors, le moyen d&#039;obtenir un coût global optimal est de faire correspondre chaque pixels de même rangs entre les deux images.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Mais ceci ne fonctionne que si les deux listes de pixels ont été préalablement ordonnées selon un vecteur (ici, le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Application pour deux images ===&lt;br /&gt;
&lt;br /&gt;
On prend donc deux images A et B de mêmes aires.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image A] [image B]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==== Représentation des deux images ====&lt;br /&gt;
&lt;br /&gt;
Les deux images peuvent être traduites par deux listes de pixels de même taille (car elles ont toutes deux la même aire).&amp;lt;br/&amp;gt;&lt;br /&gt;
Chaque pixel est lui même représenté par trois composantes : bleu, rouge et vert. Chacune de ces composantes prennent des valeurs allant de 0 à 255.&amp;lt;br/&amp;gt;&lt;br /&gt;
On peut ainsi représenter graphiquement les images dans un repère en trois dimensions par deux nuages de points.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image 1] [image 2]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ordonnance des pixels ====&lt;br /&gt;
&lt;br /&gt;
Pour ordonner ces deux nuages de points selon une droite &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, on définit son vecteur directeur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; qui est aussi un vecteur unitaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Le produit scalaire de chaque pixels d&#039;une image avec &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; donne le rang auquel le pixel correspond sur sa liste ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On ordonne donc les deux nuages de points pour obtenir deux listes ordonnée.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calcul du meilleur coût ====&lt;br /&gt;
&lt;br /&gt;
On peut ensuite calculer le coût global &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; entre les deux listes ordonnées.&amp;lt;br/&amp;gt;&lt;br /&gt;
Pour rappel, &amp;lt;math&amp;gt;C=\sum_{i=1}^n c(x_i,y_i)&amp;lt;/math&amp;gt;, avec &amp;lt;math&amp;gt;c(x_i,y_i)=|x_i-y_i|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image légendée]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Sachant que ce coût dépend du vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; tiré, on a &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
Comme le transfert doit être optimal, il faut trouver le vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; pour lequel &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; est minimal.&amp;lt;br/&amp;gt;&lt;br /&gt;
La méthode utilisée est donc de tirer au hasard &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt; un nombre suffisant de fois pour s&#039;approcher du &amp;lt;math&amp;gt;C(\vec{u})&amp;lt;/math&amp;gt; minimal.&lt;br /&gt;
&lt;br /&gt;
==== Transfert final ====&lt;br /&gt;
&lt;br /&gt;
Une fois que l&#039;on a trouvé le coût &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; le plus bas pour un certains vecteur &amp;lt;math&amp;gt;\vec{u}&amp;lt;/math&amp;gt;, il ne reste plus qu&#039;à faire correspondre les pixels de l&#039;image B avec l&#039;emplacement initial des pixels de l&#039;image A auxquels ils sont associé pour former l&#039;image sortante C.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[image C]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithme en python ==&lt;/div&gt;</summary>
		<author><name>Chardonnet</name></author>
	</entry>
</feed>