diy:projets:vintage
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| diy:projets:vintage [2018/05/31 14:07] – [Le programme] tphilibert | diy:projets:vintage [2018/06/01 10:58] (Version actuelle) – [Solutions possibles et améliorations] tphilibert | ||
|---|---|---|---|
| Ligne 13: | Ligne 13: | ||
| ====Outils requis==== | ====Outils requis==== | ||
| - | * Un classifier entraîné dans la détection du visage, comme [[https:// | + | Aucun outil spécifique n'est requis pour faire fonctionner ce programme. |
| - | * Cette [[https:// | + | ====Librairies==== |
| - | Le tout à placer dans le même dossier que celui du programme.\\ | + | Ce programme |
| - | \\ | + | |
| - | __Remarques: | + | |
| - | * Le classifier donné est celui utilisé par le programme. Vous pouvez le remplacer par n' | + | |
| <code python> | <code python> | ||
| - | # Load XML Classifier | + | import |
| - | face_cascade = cv2.CascadeClassifier(' | + | import numpy as np |
| + | import copy | ||
| + | import random as rng | ||
| + | import sys | ||
| </ | </ | ||
| - | //ligne 133//.\\ | + | //lignes 1 à 5//.\\ |
| - | * N'importe quelle image peut-être l'image de base du moment qu'elle s'appelle | + | \\ |
| - | ====Librairies==== | + | * '' |
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | ---- | ||
| ====== Explication du programme ====== | ====== Explication du programme ====== | ||
| + | ====Le contrôle d' | ||
| + | Il s'agit d'un pan entier de code contrôlant l' | ||
| + | {{ : | ||
| + | Ce n'est pas nécessairement excitant mais ça permet au programme de détecter différentes erreurs, de s' | ||
| + | Si cela vous intéresse, le contrôle s' | ||
| + | ---- | ||
| + | ====Les fonctions==== | ||
| + | Ce programme contient 7 fonctions: | ||
| + | * **generateCircleMask**(// | ||
| + | * **cappedValue**(// | ||
| + | * **applyVariationToBGRPixel**(// | ||
| + | * **maskDifference**(// | ||
| + | * **vintage**(// | ||
| + | * **options**(). | ||
| + | * **optionTime**(// | ||
| + | |||
| + | **generateCircleMask**\\ | ||
| + | <code python> | ||
| + | def generateCircleMask(img, | ||
| + | |||
| + | h,w,v = img.shape | ||
| + | sq_rad = radius**2 | ||
| + | toThreshold = cv2.cvtColor(img.astype(' | ||
| + | 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, | ||
| + | else: | ||
| + | toThreshold[i, | ||
| + | ret, circleMask = cv2.threshold(toThreshold, | ||
| + | return circleMask | ||
| + | </ | ||
| + | //lignes 9 à 21//\\ | ||
| + | \\ | ||
| + | La fonction prend une image //img// et renvoie un masque circulaire de centre //center// et de rayon //radius// de la même taille que celle de l' | ||
| + | \\ | ||
| + | |||
| + | **cappedValue**\\ | ||
| + | <code python> | ||
| + | def cappedValue(value, | ||
| + | |||
| + | if(value < least): | ||
| + | value = least | ||
| + | elif(value > most): | ||
| + | value = most | ||
| + | return value | ||
| + | </ | ||
| + | //lignes 25 à 31//\\ | ||
| + | \\ | ||
| + | La fonction prend une valeur //value// et s' | ||
| + | \\ | ||
| + | |||
| + | **applyVariationToBGRPixel**\\ | ||
| + | <code python> | ||
| + | def applyVariationToBGRPixel(pixel, | ||
| + | |||
| + | b,g,r = pixel | ||
| + | if(withRNG): | ||
| + | b = cappedValue(b - (var + rng.randint(low_rng, | ||
| + | g = cappedValue(g - (var + rng.randint(low_rng, | ||
| + | r = cappedValue(r - (var + rng.randint(low_rng, | ||
| + | else: | ||
| + | b = cappedValue(b - var) | ||
| + | g = cappedValue(g - var) | ||
| + | r = cappedValue(r - var) | ||
| + | pixel = [b,g,r] | ||
| + | return pixel | ||
| + | </ | ||
| + | //lignes 35 à 47//\\ | ||
| + | \\ | ||
| + | La fonction prend un pixel \\pixel\\ (i.e. un objet à trois dimensions), | ||
| + | Si le booléen //withRNG// est vrai, à chaque instance de var lui sera ajouté une valeur aléatoire comprise dans l' | ||
| + | \\ | ||
| + | |||
| + | **maskDifference**\\ | ||
| + | <code python> | ||
| + | def maskDifference(mask1, | ||
| + | |||
| + | h,w = mask1.shape | ||
| + | mask_diff = copy.copy(mask1) | ||
| + | for i in range (0,h): | ||
| + | for j in range (0,w): | ||
| + | if(mask1[i, | ||
| + | mask_diff[i, | ||
| + | else: | ||
| + | mask_diff[i, | ||
| + | return mask_diff | ||
| + | </ | ||
| + | //lignes 51 à 61//\\ | ||
| + | \\ | ||
| + | La fonction prend deux masques //mask1// et //mask2// de même taille et renvoie le masque résultant de leur différence.\\ | ||
| + | \\ | ||
| + | |||
| + | **vintage**\\ | ||
| + | <code python> | ||
| + | def vintage(img): | ||
| + | |||
| + | # Useful datas | ||
| + | height, width, value = img.shape | ||
| + | |||
| + | # Get Canny edges | ||
| + | grayimg = cv2.cvtColor(img, | ||
| + | edgyimg = cv2.Canny(grayimg, | ||
| + | |||
| + | # Dilate edges | ||
| + | rect = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, | ||
| + | thicc_img = cv2.dilate(edgyimg, | ||
| + | |||
| + | # Thickening edges | ||
| + | invertimg = cv2.bitwise_not(thicc_img) | ||
| + | colorgray = cv2.cvtColor(invertimg, | ||
| + | ret, mask = cv2.threshold(grayimg, | ||
| + | mask_inv = mask | ||
| + | roi = grayimg[0: | ||
| + | img1_bg = cv2.bitwise_and(roi, | ||
| + | img2_fg = cv2.bitwise_and(img, | ||
| + | img1_bg = cv2.cvtColor(img1_bg, | ||
| + | addimg = cv2.add(img1_bg, | ||
| + | img[0: | ||
| + | |||
| + | # Speckle Noise | ||
| + | gauss = np.random.randn(height, | ||
| + | gauss = gauss.reshape(height, | ||
| + | img = img + (img * gauss)/16 | ||
| + | |||
| + | # Sepia filter I | ||
| + | sepia = np.matrix([[0.272, | ||
| + | img = cv2.transform(img, | ||
| + | |||
| + | # Toneing | ||
| + | center_h = int(height/ | ||
| + | center_w = int(width/ | ||
| + | mask = generateCircleMask(img, | ||
| + | outer_mask = generateCircleMask(img, | ||
| + | outer_mask = maskDifference(outer_mask, | ||
| + | var = 5 | ||
| + | unb = 1 | ||
| + | low = -2 | ||
| + | high = 2 | ||
| + | for i in range (0,height): | ||
| + | for j in range (0,width): | ||
| + | if(mask[i, | ||
| + | img[i, | ||
| + | elif(outer_mask[i, | ||
| + | img[i, | ||
| + | |||
| + | # Sepia filter II | ||
| + | sepia = np.matrix([[0.272, | ||
| + | img = cv2.transform(img, | ||
| + | |||
| + | # Gaussian blur | ||
| + | img = cv2.GaussianBlur(img, | ||
| + | |||
| + | # Border | ||
| + | bs = 10 | ||
| + | img = cv2.copyMakeBorder(img, | ||
| + | |||
| + | # Return result | ||
| + | return img | ||
| + | </ | ||
| + | //lignes 65 à 128//\\ | ||
| + | \\ | ||
| + | La fonction prend une image //img//.\\ | ||
| + | La partie ''# | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | La partie '' | ||
| + | \\ | ||
| + | |||
| + | **options**\\ | ||
| + | <code python> | ||
| + | def options(): | ||
| + | print(" | ||
| + | name_i = input(" | ||
| + | print("" | ||
| + | image = cv2.imread(name_i) | ||
| + | try: | ||
| + | dtype_debug = image.dtype | ||
| + | except AttributeError as ae: | ||
| + | print(" | ||
| + | raise ae | ||
| + | |||
| + | print(" | ||
| + | name_o = input(" | ||
| + | print("" | ||
| + | |||
| + | return image, | ||
| + | </ | ||
| + | //lignes 132 à 147//\\ | ||
| + | Communique avec l' | ||
| + | __Remarque: | ||
| + | \\ | ||
| + | |||
| + | **optionTime**\\ | ||
| + | <code python> | ||
| + | def optionTime(time): | ||
| + | # See Execution time of vintage function | ||
| + | print(" | ||
| + | know = input(" | ||
| + | if(know == ' | ||
| + | print(" | ||
| + | </ | ||
| + | //lignes 151 à 156//\\ | ||
| + | Demande à afficher le temps //time// d' | ||
| + | __Remarque: | ||
| + | \\ | ||
| + | |||
| + | ====Le main==== | ||
| + | Le main ne s' | ||
| + | |||
| + | ---- | ||
| + | =====Problèmes et améliorations===== | ||
| + | ====Problèmes==== | ||
| + | Le programme est particulièrement lent (~4s). | ||
| + | |||
| + | ====Solutions possibles et améliorations==== | ||
| + | Doter le programme d'une meilleure algorithmie pour notamment virer des opérations en trop/peu utiles. Le réécrire en C++ serait aussi un bon moyen pour booster ses performances.\\ | ||
| + | \\ | ||
| + | Pour les améliorations possibles, on pourrait envisager du temps réel et une meilleure gestion d' | ||
| + | \\ | ||
| + | \\ | ||
| + | \\ | ||
| + | ---- | ||
| + | //Merci pour votre attention.// | ||
| + | // | ||
| + | |||
diy/projets/vintage.1527775642.txt.gz · Dernière modification : de tphilibert
