TP2: Synthèse de textures

Le but de ce tp est d'expérimenter la synthèse de textures ainsi que le transfert de textures.

In [1]:
# Importation des librairies ipython
%matplotlib inline
%load_ext autoreload
%autoreload 1
%aimport tp2

from matplotlib import pyplot as plt
plt.rcParams['figure.figsize'] = (16.0, 10.0)
import skimage
from IPython.display import Image, display, display_pretty, display_html, display_jpeg
import scipy
import numpy as np

Les textures utilisées dans les prochaines sections du tp sont présentées ici. Il s'agit d'une texture de briques, de texte et de nuages.

In [2]:
bricks = skimage.img_as_float(plt.imread('textures/bricks_small.jpg'))
text = skimage.img_as_float(plt.imread('textures/text_small.jpg'))
white = skimage.img_as_float(plt.imread('textures/white_small.jpg'))
forest = skimage.img_as_float(plt.imread('textures/forest_above_yuksom.jpg'))
potato = skimage.img_as_float(plt.imread('textures/potatoes.jpg'))
sea = skimage.img_as_float(plt.imread('textures/sea.jpg'))

Texture échantillonnée aléatoirement, sans chevauchement

La première méthode de synthèse de textures consiste à échantillonées des blocs aléatoirement et de les placer un à côté de l'autres. Cette technique ne donne évidemment pas d'excellent résultats. Dans ce cas, comme dans les cas suivant, les paramètres à utiliser sont très important et changent selon la texture que l'on cherche à reproduire. Les résultats présentés montrent cet algorithme avec plusieurs valeurs de tailles de blocs.

In [3]:
def show_random(image, filename, outsize, patchsize, sp=(1,1,1)):
    out = tp2.quilt_random(image, outsize, patchsize)
    #plt.imsave(filename, out)
    #display(Image(url=filename), filename=filename)
    plt.subplot(*sp)
    plt.imshow(out)
    plt.axis('off')


sizes = [5, 10, 20, 30, 50]
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(bricks)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(bricks, "output/random_bricks.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(text)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(text, "output/random_text.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(white)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(white, "output/random_white.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(forest)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(forest, "output/random_forest.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(sea)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(sea, "output/random_sea.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(potato)
plt.axis('off')
plt.title('original')
for i, size in enumerate(sizes):
    show_random(potato, "output/random_potato.png", (200,200,3), (size, size,3), sp=(1,len(sizes)+1,i+2))
    plt.title("patchsize: {}".format(size))

Chevauchement de blocs

Dans cette section, on échantillonne les blocs en fonction de leur similarité sur une section de chevauchement. Cette technique assure une certaine cohérence dans le choix des blocs. Les résultats de cette section montrent l'influence de la grandeur de la zone de chevauchement.

In [4]:
def show_simple(image, filename, outsize, patchsize, overlap, tol, sp=(1,1,1)):
    out = tp2.quilt_simple(image, outsize, patchsize, overlap, tol)
    #plt.imsave(filename, out)
    #display(Image(url=filename), filename=filename)
    plt.subplot(*sp)
    plt.imshow(out)

overlaps = [1, 5, 10, 15]
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(bricks)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(bricks, "output/simple_bricks.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(text)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(text, "output/simple_text.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(white)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(white, "output/simple_white.png", (200, 200, 3), (20, 20, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(forest)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(forest, "output/simple_forest.png", (200, 200, 3), (20, 20, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(sea)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(sea, "output/simple_sea.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))

plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(potato)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_simple(potato, "output/simple_potato.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
 

Recherche de joint

Dans cette section, on applique la même technique que dans la section précédente. Cependant, plutôt que de simplement recopier les blocs dans leur totalité, on cherche la séparation où la différence entre les deux blocs est minimale.

In [5]:
def show_quilt_cut(image, filename, outsize, patchsize, overlap, tol, sp=(1,1,1)):
    out = tp2.quilt_cut(image, outsize, patchsize, overlap, tol)
    #plt.imsave(filename, out)
    #display(Image(url=filename), filename=filename)
    plt.subplot(*sp)
    plt.imshow(out)

overlaps = [1, 5, 10, 15]
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(bricks)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(bricks, "output/quilt_bricks.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(text)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(text, "output/quilt_text.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(white)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(white, "output/quilt_white.png", (200, 200, 3), (20, 20, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(forest)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(forest, "output/quilt_forest.png", (200, 200, 3), (20, 20, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(sea)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(sea, "output/quilt_sea.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))
    
plt.figure()
plt.subplot(1, len(sizes)+1,1)
plt.imshow(potato)
plt.axis('off')
plt.title('original')
for i, overlap in enumerate(overlaps):
    show_quilt_cut(potato, "output/quilt_potato.png", (200, 200, 3), (50, 50, 3), overlap, 0.3, sp=(1,len(sizes)+1,i+2))
    plt.title("overlap: {}".format(overlap))

Transfert de textures

Dans cette section, on applique certains concepts des sections précédentes pour transférer des textures d'un object à un autre. Par exemple, on peut appliquer la texture d'une toast et y faire apparaitre le visage de Maxime. Les résultats présentés dans cette section montrent le transfert de texture du sketch sur le visage de Feynman, de la texture de toast sur le visage de Maxime et de la peinture de Van Gogh sur mon visage.

Pour étudier l'effet des paramètres sur cette technique, les résultats présentés sont effectués avec plusieurs valeurs de $\alpha$.

In [6]:
feynman = skimage.img_as_float(plt.imread('transfert/feynman.tiff'))
maxime = skimage.img_as_float(plt.imread('transfert/max-pascontent2.jpg'))
maxime = scipy.misc.imresize(maxime, 0.125)
feynman = scipy.misc.imresize(feynman, 0.5)
olivier = skimage.img_as_float(plt.imread('transfert/olivier.jpg'))
olivier = scipy.misc.imresize(olivier, 0.1)


sketch = skimage.img_as_float(plt.imread('transfert/sketch.tiff'))
toast = skimage.img_as_float(plt.imread('transfert/toast.jpg'))
#vgogh = skimage.img_as_float(plt.imread('the-starry-night.jpg'))
#vgogh = scipy.misc.imresize(vgogh, 0.5)
plt.subplot(1,2,1)
plt.imshow(sketch)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(toast)
plt.axis('off')
Out[6]:
(-0.5, 159.5, 157.5, -0.5)
In [7]:
def show_texture(sample, filename, img, patchsize, overlap, tol, alpha, sp=(1,1,1)):
    out = tp2.texture_transfer(sample, patchsize, overlap, tol, img, alpha)
    #plt.imsave(filename, out)
    #display(Image(url=filename), filename=filename)
    plt.subplot(*sp)
    plt.imshow(out)
    
alphas = np.linspace(0, 0.6, 4)

plt.figure()
plt.subplot(1, len(alphas)+1,1)
plt.imshow(feynman)
plt.axis('off')
plt.title('original')
for i, alpha in enumerate(alphas):
    show_texture(sketch, 'output/texture_feynman.png', feynman, (30, 30, 3), 13, 0.3, alpha, sp=(1, len(alphas)+1, i+2))
    plt.title(r"$\alpha$: {}".format(alpha))
    
plt.figure()
plt.subplot(1, len(alphas)+1,1)
plt.imshow(maxime)
plt.axis('off')
plt.title('original')
for i, alpha in enumerate(alphas):
    show_texture(toast, 'output/texture_feynman.png', maxime, (30, 30, 3), 13, 0.3, alpha, sp=(1, len(alphas)+1, i+2))
    plt.title(r"$\alpha$: {}".format(alpha))
    
plt.figure()
plt.subplot(1, len(alphas)+1,1)
plt.imshow(olivier)
plt.axis('off')
plt.title('original')
for i, alpha in enumerate(alphas):
    show_texture(sketch, 'output/texture_feynman.png', olivier, (30, 30, 3), 13, 0.3, alpha, sp=(1, len(alphas)+1, i+2))
    plt.title(r"$\alpha$: {}".format(alpha))

Crédits supplémentaires

Comme crédits supplémentaires, la version itérative de l'algorithme de transfert de textures a été implémentée. Dans cette version, la taille des «patch» est réduite du tiers à chaque itération. Pour l'itération $i$ de $N$, la valeur de $\alpha$ est déterminée à l'aide de l'équation: $$\alpha_i = 0.8 * \frac{i - 1}{N - 1} + 0.1$$

In [10]:
def show_iter_texture(sample, filename, img, patchsize, overlap, tol, n_iter, sp=(1,1,1)):
    out = tp2.iterative_texture_transfer(sample, patchsize, overlap, tol, img, n_iter)
    #plt.imsave(filename, out)
    #display(Image(url=filename), filename=filename)
    plt.subplot(*sp)
    plt.imshow(out)
    
n_iters = [2, 3]

plt.figure()
plt.subplot(1, len(n_iters)+1,1)
plt.imshow(feynman)
plt.axis('off')
plt.title('original')
for i, n_iter in enumerate(n_iters):
    show_iter_texture(sketch, 'output/texture_feynman.png', feynman, (40, 40, 3), 13, 0.3, n_iter, sp=(1, len(n_iters)+1, i+2))
    plt.title("N: {}".format(n_iter))
    
plt.figure()
plt.subplot(1, len(n_iters)+1,1)
plt.imshow(maxime)
plt.axis('off')
plt.title('original')
for i, n_iter in enumerate(n_iters):
    show_iter_texture(toast, 'output/texture_feynman.png', maxime, (40, 40, 3), 13, 0.3, n_iter, sp=(1, len(n_iters)+1, i+2))
    plt.title("N: {}".format(n_iter))
    
plt.figure()
plt.subplot(1, len(n_iters)+1,1)
plt.imshow(olivier)
plt.axis('off')
plt.title('original')
for i, n_iter in enumerate(n_iters):
    show_iter_texture(sketch, 'output/texture_feynman.png', olivier, (40, 40, 3), 13, 0.3, n_iter, sp=(1, len(n_iters)+1, i+2))
    plt.title("N: {}".format(n_iter))