Ceci est une ancienne révision du document !
Table des matières
Présentation du projet
vintage est un programme qui a pour but d'appliquer un effet vintage; vieilli à une image donnée ou prise.
Ce programme n'a pas d'autre but que de divertir.
Exemple d'exécution de ce programme:
Outils requis et Librairies Python
Le programme
Le programme se trouve en intégralité ici.
Outils requis
Aucun outil spécifique n'est requis pour faire fonctionner ce programme.
Librairies
Ce programme utilise les librairies suivantes:
import cv2 import numpy as np import copy import random as rng import sys
lignes 1 à 5.
cv2
référence la librairie OpenCV permettant de nombreuses opérations sur les images en Python et C++
numpy
référence la librairie NumPy prodiguant une meilleure création/utilisation/gestion des objets à plusieurs dimensions.
sys
référence la librairie sys pour la gestion des paramètres en Python.
Explication du programme
Le contrôle d'erreur
Il s'agit d'un pan entier de code contrôlant l'arbre d'argument suivant:
Ce n'est pas nécessairement excitant mais ça permet au programme de détecter différentes erreurs, de s'arrêter dans de meilleures conditions et en indiquant l'erreur en question.
Si cela vous intéresse, le contrôle s'étend lignes 163 à 196.
Les fonctions
Ce programme contient 7 fonctions:
- generateCircleMask(img,center,radius).
- cappedValue(value,least=0,most=255).
- applyVariationToBGRPixel(pixel,var,withRNG=False,low_rng=0,high_rng=0).
- maskDifference(mask1,mask2).
- vintage(img).
- options().
- optionTime(time).
generateCircleMask
def generateCircleMask(img,center,radius): h,w,v = img.shape sq_rad = radius**2 toThreshold = cv2.cvtColor(img.astype('uint8',copy=False),cv2.COLOR_BGR2GRAY) for i in range (0,h): for j in range (0,w): if(((i-center[0])**2 + (j-center[1])**2) <= sq_rad): toThreshold[i,j] = 0 else: toThreshold[i,j] = 255 ret, circleMask = cv2.threshold(toThreshold, 10, 255, cv2.THRESH_BINARY) return circleMask
lignes 9 à 21
cappedValue
def cappedValue(value,least=0,most=255): if(value < least): value = least elif(value > most): value = most return value
lignes 25 à 31
applyVariationToBGRPixel
def applyVariationToBGRPixel(pixel,var,withRNG=False,low_rng=0,high_rng=0): b,g,r = pixel if(withRNG): b = cappedValue(b - (var + rng.randint(low_rng,high_rng))) g = cappedValue(g - (var + rng.randint(low_rng,high_rng))) r = cappedValue(r - (var + rng.randint(low_rng,high_rng))) else: b = cappedValue(b - var) g = cappedValue(g - var) r = cappedValue(r - var) pixel = [b,g,r] return pixel
lignes 35 à 47
maskDifference
def maskDifference(mask1,mask2): h,w = mask1.shape mask_diff = copy.copy(mask1) for i in range (0,h): for j in range (0,w): if(mask1[i,j] == 0 and mask2[i,j] == 255): mask_diff[i,j] = 255 else: mask_diff[i,j] = 0 return mask_diff
lignes 51 à 61
vintage
def vintage(img): # Useful datas height, width, value = img.shape # Get Canny edges grayimg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) edgyimg = cv2.Canny(grayimg,50,200,apertureSize=3) # Dilate edges rect = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)) thicc_img = cv2.dilate(edgyimg,rect,iterations=1) # Thickening edges invertimg = cv2.bitwise_not(thicc_img) colorgray = cv2.cvtColor(invertimg,cv2.COLOR_GRAY2BGR) ret, mask = cv2.threshold(grayimg, 10, 255, cv2.THRESH_BINARY) mask_inv = mask roi = grayimg[0:height, 0:width] img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv) img2_fg = cv2.bitwise_and(img,img,mask = mask) img1_bg = cv2.cvtColor(img1_bg,cv2.COLOR_GRAY2BGR) addimg = cv2.add(img1_bg,img2_fg) img[0:height, 0:width] = addimg # Speckle Noise gauss = np.random.randn(height,width,value) gauss = gauss.reshape(height,width,value) img = img + (img * gauss)/16 # Sepia filter I sepia = np.matrix([[0.272,0.534,0.131],[0.349,0.686,0.168],[0.393,0.769,0.189]]) img = cv2.transform(img,sepia) # Toneing center_h = int(height/2) center_w = int(width/2) mask = generateCircleMask(img,[center_h,center_w],center_h-5) outer_mask = generateCircleMask(img,[center_h,center_w],center_h+5) outer_mask = maskDifference(outer_mask,mask) var = 5 unb = 1 low = -2 high = 2 for i in range (0,height): for j in range (0,width): if(mask[i,j] == 255): img[i,j] = applyVariationToBGRPixel(img[i,j],var,True,low,high) elif(outer_mask[i,j] == 255): img[i,j] = applyVariationToBGRPixel(img[i,j],int(var/2),True,low,high) # Sepia filter II sepia = np.matrix([[0.272,0.534,0.131],[0.349,0.686,0.168],[0.393,0.769,0.189]]) img = cv2.transform(img,sepia) # Gaussian blur img = cv2.GaussianBlur(img,(5,5),0) # Border bs = 10 img = cv2.copyMakeBorder(img,bs,bs,bs,bs,cv2.BORDER_CONSTANT,value=(230,245,245)) # Return result return img
lignes 65 à 128
options
def options(): print("Nom ou chemin de l'image à traiter (avec l'extension)") name_i = input("-> ") print("") image = cv2.imread(name_i) try: dtype_debug = image.dtype except AttributeError as ae: print("Erreur,",name_i,"ne peut pas être lu (fichier invalide ou absent)\n") raise ae print("Quel nom donner à l'image en sortie (avec l'extension)?") name_o = input("-> ") print("") return image,name_o
lignes 132 à 147
optionTime
def optionTime(time): # See Execution time of vintage function print("Voulez-vous connaître le temps d'execution de la fonction vintage? [y/n]") know = input("-> ") if(know == 'y'): print("Temps d'execution du programme:",time,"secondes")
\\lignes 151 à 156\\
====Le main====
Il s'agit là aussi d'un bout de code pas très passionnant. Il s'étend lignes 115 jusqu'à la fin et se résume à:
* Chargement des classifiers.
* Chargement du flash lumineux.
* Débuter le traitement selon la méthode choisie, i.e:
* Soit en appliquant la fonction puis en écrivant le résultat si le traitement est sur image fixe.
* Soit en appliquant la fonction en continue et en l'affichant le résultat en temps réel jusqu'à pression de la touche Q
.
* Quitter.
—-