sam1902

Mosaic Image Projet Final

Mar 12th, 2018
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.90 KB | None | 0 0
  1. from PIL import Image, ImageFile
  2. from sys import argv
  3. from math import sqrt, floor # Pythagore
  4. import numpy as np # moyenne RGB rapide (optionel)
  5. from os import listdir, remove
  6. from os.path import isfile, join
  7.  
  8. # Pour un problème de compatibilité avec les jpeg...
  9. # voir http://bit.ly/2IkyJ6U
  10. ImageFile.LOAD_TRUNCATED_IMAGES = True
  11.  
  12. '''
  13.    Determine la distance euclidienne entre deux couleur (pythagore en 3D)
  14. '''
  15. def distance(color1, color2):
  16.     r1, g1, b1 = color1
  17.     r2, g2, b2 = color2
  18.     # Étonnament la manière la plus rapide
  19.     return sqrt((r2-r1)**2 + (g2-g1)**2 + (b2-b1)**2)
  20.  
  21. '''
  22.    Cherche l'image qui correspond le mieux au block de pixel donné
  23.    retourne l'image la plus adapté à ce block
  24. '''
  25. def getClosestImage(imgCrop, imgdb):
  26.     imgBlockAvgRGB = avgRGB(imgCrop) # Valeur moyenne RGB de l'image source
  27.  
  28.     # Cherche l'élément présentant la valeur RGB moyenne la plus proche
  29.     nearestRGB = min(imgdb.keys(), key=lambda imAvgRGB: distance(imAvgRGB, imgBlockAvgRGB))
  30.     nearestImg = imgdb[nearestRGB]
  31.     return nearestImg
  32.  
  33. '''
  34.    Obtient la valeur RGB (red, green, blue) moyenne d'une image
  35. '''
  36. def avgRGB(img):
  37.     return tuple(np.array(img).mean(axis=(0,1)))
  38.    
  39. '''
  40.    Normalise la taille de chaque image de la base de donnée
  41.    imgdb: base d'images à normaliser
  42.    size: tuple representant la taille voulue, ex: (tailleX, tailleY)
  43. '''
  44. def normaliseSize(imgdb, size):
  45.     for i in range(len(imgdb)):
  46.         imgdb[i] = imgdb[i].resize(size)
  47.     return imgdb
  48.  
  49. '''
  50.    Charge les images dans la base de donnée
  51. '''
  52. def loadMosaDatabase(imgDbPath):
  53.     # Contient toute les images utiles pour la mosaic
  54.     imgdb = []
  55.     for imagePath in listdir(imgDbPath):
  56.         # Obtient le chemin complet vers le fichier
  57.         imageFullPath = join(imgDbPath, imagePath)
  58.         # Passe à la boucle suivante si l'élément n'est pas un fichier
  59.         if not isfile(imageFullPath):
  60.             continue
  61.         # Ajoute l'objet image à la liste des images utiles
  62.         imgdb.append(Image.open(imageFullPath))
  63.     return imgdb
  64.  
  65. # Vérifie que tout les paramètres sont fournis
  66. if len(argv) < 5:
  67.     exit("Usage: python3 script.py cheminVersImage cheminVersBasededonnee resolution facteurDeSortie")
  68.  
  69. imgOrigPath = argv[1] # chemin vers l'image à "mosaiquer"
  70. imgDbPath = argv[2] # chemin vers le dossier contenant les images pour la mosaique
  71. resolution = int(argv[3]) # nombre de divisions de l'image originale
  72. outputFactor = abs(int(argv[4])) # facteur par lequel multiplier la taille de l'image d'entrée
  73.  
  74. img = Image.open(imgOrigPath) # Charge l'image originale
  75.  
  76. if outputFactor != 1: # Si la taille de l'image d'entrée doit être ajusté
  77.     img = img.resize((img.size[0]*outputFactor, img.size[1]*outputFactor))
  78.     print("L'image de mosaique sera {} fois plus grande que l'image d'entrée".format(outputFactor))
  79.  
  80. origSize = img.size # Garde en mémoire la taille de l'image originale pour plus tard
  81. print("Chargement des images dans la base de donnée... ")
  82. imgdb = loadMosaDatabase(imgDbPath) # Charge la base de donnée d'images
  83.  
  84. blockSize = ( floor(img.size[0]/resolution), floor(img.size[1]/resolution) )
  85. apprxSize = ( blockSize[0]*resolution, blockSize[1]*resolution )
  86.  
  87. print("La taille de image originale vas être changer en:\t {}".format(apprxSize))
  88. print("La mosaique se constitura d'images de taille:\t {}".format(blockSize))
  89. print("Changement de la taille de l'image originale en {}...".format(apprxSize))
  90.  
  91. img = img.resize(apprxSize) # Change la taille de l'image originale pour tomber juste
  92. print("Changement de chaque image de la base de donnée {} ...".format(blockSize))
  93. imgdb = normaliseSize(imgdb, blockSize) # Change la taille des images pour convenir à la résolution
  94.  
  95. print("Construction du dictionnaire Image <--> valeur RGB moyenne...")
  96. imgDbAvgRGB = dict() # Dictionnaire liant chaque image à ses valeur RGB moyennes
  97. for im in imgdb:
  98.     imgDbAvgRGB[avgRGB(im)] = im
  99.  
  100. imgMosa = Image.new("RGB", apprxSize, (255,0,0)) # Contiendra la mosaique
  101.  
  102. print("Création de la mosaique...")
  103. for x in range(0, apprxSize[0], blockSize[0]): # Vas de 0 à apprxSize[0] en faisant x = x + blockSize[0] à chaque tour (step)
  104.     for y in range(0, apprxSize[1], blockSize[1]):
  105.         blockFrame = (x,y, x+blockSize[0], y+blockSize[1])
  106.         # Découpe la portion de l'image originale à faire correspondre
  107.         imgCrop = img.crop(blockFrame)
  108.         # Obtient l'image à placer dans le block actuel, depuis la base de donnée
  109.         imgBlock = getClosestImage(imgCrop, imgDbAvgRGB)
  110.         # colle l'image à placer dans sa position dans la nouvelle mosaique
  111.         imgMosa.paste(imgBlock, blockFrame)
  112.  
  113. print("Terminé !")
  114. print("Changement de la taille de la mosaique pour être égale à celle de l'image originale {}".format(origSize))
  115. imgMosa = imgMosa.resize(origSize)
  116. print("Fichier enregistré sous \"mosa.png\"")
  117. imgMosa.save("mosa.png")
Advertisement
Add Comment
Please, Sign In to add comment