(C) Copyright Franck CHEVRIER 2019-2020 http://www.python-lycee.com/
Pour exécuter une saisie Python, sélectionner la cellule et valider avec SHIFT+Entrée.
Le but de cette activité est d'apprendre à composer une nouvelles image à partir de deux images initiales.
Cette activité fait suite à l'activité sur les traitements d'images n°1 (Application de filtres).
1. Superposition d'images
2. Réalisation d'un anaglyphe
3. Incrustation sur fond vert
Dans cette partie, on souhaite obtenir une nouvelle image par superposition de deux images.
1.1. Exécuter les cellules ci-dessous, qui permettent chacune :
# import du module permettant la gestion des images
from PIL import Image
#ouverture de l'image 1
Im1 = Image.open('img/Compo/oiseau.jpg')
#affichage du format, du type et de la dimension de l'image 2
print("Nom: Im1","\nFormat:",Im1.format,"\nMode:",Im1.mode,"\nDimensions:",Im1.size) ;
#affichage de l'image
Im1
Nom: Im1 Format: JPEG Mode: RGB Dimensions: (640, 360)
#ouverture de l'image 2
Im2 = Image.open('img/Compo/montagne.jpg')
#affichage du format, du type et de la dimension de l'image 2
print("Nom: Im2","\nFormat:",Im2.format,"\nMode:",Im2.mode,"\nDimensions:",Im2.size) ;
#affichage de l'image
Im2
Nom: Im2 Format: JPEG Mode: RGB Dimensions: (640, 360)
1.2. Superposition par saturation.
$\;\;\;\;\;$On donne la fonction Python sup_saturation ci-dessous.
$\;\;\;\;\;$a. On suppose que les codes R,G,B de deux pixels correspondants dans les images originales sont (50,200,70) et (40,120,30).
$\;\;\;\;\;\;\;\;$Quel sera le code R,G,B du pixel de l'image obtenue?
$\;\;\;\;\;$b. Exécuter les deux cellules ci-dessous pour tester la fonction sup_saturation.
$\;\;\;\;\;$c. Que peux-t-on dire de la luminosité de l'image obtenue par rapport à celles des images originales?
def sup_saturation(im_or1,im_or2):
"""
fonction qui superpose deux images par saturation
"""
# vérification que les images sont de même format et taille
if (im_or1.format,im_or1.mode,im_or1.size) != (im_or2.format,im_or2.mode,im_or2.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = im_or1.size
# création d'une image vierge, de même format et même taille que les images initiales
im_composee = Image.new( mode=im_or1.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_or1 = im_or1.load()
pix_or2 = im_or2.load()
pix_composee = im_composee.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
R1,G1,B1 = pix_or1[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or1
R2,G2,B2 = pix_or2[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or2
R = R1+R2
G = G1+G2
B = B1+B2
pix_composee[x,y] = R,G,B #écriture des composantes R,G,B du pixel modifié
# on renvoie l'image modifiée
return im_composee
sup_saturation(Im1,Im2)
1.3. Superposition par maximum.
$\;\;\;\;\;$On souhaite construire les composantes des pixels de la nouvelle image en prenant la plus grande des composantes des deux images.
$\;\;\;\;\;$Écrire la fonction Python sup_max qui convient.
$\;\;\;\;\;$Aide : On peut utiliser la fonction Python max pour le calcul d'un maximum.
# Écrire ici la fonction sup_max
def sup_max(im_or1,im_or2):
"""
fonction qui superpose deux images par moyenne
"""
# vérification que les images sont de même format et taille
if (im_or1.format,im_or1.mode,im_or1.size) != (im_or2.format,im_or2.mode,im_or2.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = im_or1.size
# création d'une image vierge, de même format et même taille que les images initiales
im_composee = Image.new( mode=im_or1.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_or1 = im_or1.load()
pix_or2 = im_or2.load()
pix_composee = im_composee.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
R1,G1,B1 = pix_or1[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or1
R2,G2,B2 = pix_or2[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or2
R = max(R1,R2)
G = max(G1,G2)
B = max(B1,B2)
pix_composee[x,y] = R,G,B #écriture des composantes R,G,B du pixel modifié
# on renvoie l'image modifiée
return im_composee
# Tester ici un appel à la fonction sup_max
sup_max(Im1,Im2)
1.4. Superposition par la moyenne.
$\;\;\;\;\;$On souhaite construire les composantes des pixels de la nouvelle image par calculs des moyennes des composantes des pixels initiaux.
$\;\;\;\;\;$Écrire la fonction Python sup_moyenne qui convient.
# Écrire ici la fonction sup_moyenne
def sup_moyenne(im_or1,im_or2):
"""
fonction qui superpose deux images par moyenne
"""
# vérification que les images sont de même format et taille
if (im_or1.format,im_or1.mode,im_or1.size) != (im_or2.format,im_or2.mode,im_or2.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = im_or1.size
# création d'une image vierge, de même format et même taille que les images initiales
im_composee = Image.new( mode=im_or1.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_or1 = im_or1.load()
pix_or2 = im_or2.load()
pix_composee = im_composee.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
R1,G1,B1 = pix_or1[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or1
R2,G2,B2 = pix_or2[x,y] #récupération des composantes R,G,B du pixel original de l'image originale im_or2
R = (R1+R2)//2 # ou int((R1+R2)*0.5)
G = (G1+G2)//2
B = (B1+B2)//2
pix_composee[x,y] = R,G,B #écriture des composantes R,G,B du pixel modifié
# on renvoie l'image modifiée
return im_composee
# Tester ici la fonction sup_moyenne
sup_moyenne(Im1,Im2)
- Si vous disposez de deux images (de mêmes type et dimensions), allez à la question 2.1.a.
- Si vous ne disposez pas d'images, passez directement à la question 2.1.b. pour utiliser les images fournies.
2.1.a. TELECHARGEMENT DE VOS IMAGES
$\;\;\;\;\;\;\;\;$Exécuter successivement les cellules ci-dessous pour télécharger des images personnelles.
$\;\;\;\;\;\;\;\;$Elles seront stockées respectivement dans les variables image_gauche et image_droite.
$\;\;\;\;\;\;\;\;$Passer ensuite directement à la question 2.2.
#Cellule pour le téléchargement de votre image de gauche
from PIL import Image
import ipywidgets as widgets
uploader1 = widgets.FileUpload(accept='image/*',multiple=False)
print("Cliquer pour charger l'image de gauche :")
display(uploader1)
#Cellule pour la mise en mémoire de votre image de gauche
from io import BytesIO
try:
[uploaded_file1] = uploader1.value
image_gauche = Image.open(BytesIO(uploader1.value[uploaded_file1]['content']))
print("Nom: image_gauche","\nFormat:",image_gauche.format,"\nMode:",image_gauche.mode,"\nDimensions:",image_gauche.size)
display(image_gauche)
except:
print("Vous n'avez pas chargé d'image ou son format n'est pas reconnu")
#Cellule pour le téléchargement de votre image de droite
uploader2 = widgets.FileUpload(accept='image/*',multiple=False)
print("Cliquer pour charger l'image de droite :")
display(uploader2)
#Cellule pour la mise en mémoire de votre image de droite
try:
[uploaded_file2] = uploader2.value
image_droite = Image.open(BytesIO(uploader2.value[uploaded_file2]['content']))
print("Nom: image_droite","\nFormat:",image_droite.format,"\nMode:",image_droite.mode,"\nDimensions:",image_droite.size)
display(image_droite)
except:
print("Vous n'avez pas chargé d'image ou son format n'est pas reconnu")
2.1.b. TELECHARGEMENT DES IMAGES FOURNIES
$\;\;\;\;\;\;\;\;$Exécuter la cellule ci-dessous pour télécharger les images fournies.
$\;\;\;\;\;\;\;\;$Elles seront stockées respectivement dans les variables image_gauche et image_droite.
# Cellule pour charger les images fournies
image_gauche = Image.open('img/Compo/test_gauche.jpg')
image_droite = Image.open('img/Compo/test_droite.jpg')
print("Nom: image_gauche","\nFormat:",image_gauche.format,"\nMode:",image_gauche.mode,"\nDimensions:",image_gauche.size) ; display(image_gauche)
print("Nom: image_droite","\nFormat:",image_droite.format,"\nMode:",image_droite.mode,"\nDimensions:",image_droite.size) ; display(image_droite)
Nom: image_gauche Format: JPEG Mode: RGB Dimensions: (550, 366)
Nom: image_droite Format: JPEG Mode: RGB Dimensions: (550, 366)
2.2. Anaglyphe rapide : On souhaite réaliser l'anaglyphe de la façon suivante :
Pour chaque pixel de l’image à créer, on lui attribue la composante rouge de l'image de gauche, et les composantes bleue et verte de l'image de droite.
$\;\;\;\;\;$a. Écrire la fonction Python anaglyphe_rapide qui convient.
# Écrire ici la fonction anaglyphe_rapide
def anaglyphe_rapide(image_gauche,image_droite):
"""
fonction qui réalise un anaglyphe rapide
"""
# vérification que les images sont de même format et taille
if (image_gauche.format,image_gauche.mode,image_gauche.size) != (image_droite.format,image_droite.mode,image_droite.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = image_gauche.size
# création d'une image vierge, de même format et même taille que les images initiales
anaglyphe = Image.new( mode=image_gauche.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_gauche = image_gauche.load()
pix_droit = image_droite.load()
pix_anaglyphe = anaglyphe.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
Rg,Gg,Bg = pix_gauche[x,y] #récupération des composantes R,G,B du pixel de l'image de gauche
Rd,Gd,Bd = pix_droit[x,y] #récupération des composantes R,G,B du pixel de l'image de droite
R = Rg
G = Gd
B = Bd
pix_anaglyphe[x,y] = R,G,B
# on renvoie l'image modifiée
return anaglyphe
$\;\;\;\;\;$b. Tester la fonction anaglyphe_rapide.
# Tester ici la fonction anaglyphe_rapide
anaglyphe_rapide(image_gauche,image_droite)
2.3. Anaglyphe précis :
On souhaite diminuer l'altération des couleurs de l'anaglyphe réalisé.
Pour cela, on calcule les composantes R,G,B du pixel de l'anaglyphe à l'aide du tableau suivant.
Anaglyphe | $\;\;$ | $\color{red}{R_g}$ | $\color{green}{G_g}$ | $\color{blue}{B_g}$ | $\color{red}{R_d}$ | $\color{green}{G_d}$ | $\color{blue}{B_d}$ | |
---|---|---|---|---|---|---|---|---|
$\color{red}{R}$ | $\;\;$ | $41$% | $47$% | $16$% | $-1$% | $-3$% | $0$% | |
$\color{green}{G}$ | $\;\;$ | $-4$% | $-4$% | $-2$% | $38$% | $73$% | $1$% | |
$\color{blue}{B}$ | $\;\;$ | $-5$% | $-6$% | $1$% | $-6$% | $-13$% | $130$% |
Par exemple, la composante rouge R de l'anaglyphe se calcule à l'aide de la formule : R = int(0.41*Rg+0.47*Gg+0.16*Bg-0.01*Rd-0.03*Gd).
$\;\;\;\;\;$a. Écrire la fonction Python anaglyphe_precis qui convient.
# Écrire ici la fonction anaglyphe_precis
def anaglyphe_precis(image_gauche,image_droite):
"""
fonction qui réalise un anaglyphe precis
"""
# vérification que les images sont de même format et taille
if (image_gauche.format,image_gauche.mode,image_gauche.size) != (image_droite.format,image_droite.mode,image_droite.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = image_gauche.size
# création d'une image vierge, de même format et même taille que les images initiales
anaglyphe = Image.new( mode=image_gauche.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_gauche = image_gauche.load()
pix_droit = image_droite.load()
pix_anaglyphe = anaglyphe.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
Rg,Gg,Bg = pix_gauche[x,y] #récupération des composantes R,G,B du pixel de l'image de gauche
Rd,Gd,Bd = pix_droit[x,y] #récupération des composantes R,G,B du pixel de l'image de droite
R = int(0.41*Rg+0.47*Gg+0.16*Bg-0.01*Rd-0.03*Gd)
G = int(-0.04*Rg-0.04*Gg-0.02*Bg+0.38*Rd+0.73*Gd+0.01*Bd)
B = int(-0.05*Rg-0.06*Gg-0.01*Bg-0.06*Rd-0.13*Gd+1.30*Bd)
pix_anaglyphe[x,y] = R,G,B
# on renvoie l'image modifiée
return anaglyphe
$\;\;\;\;\;$b. Tester la fonction anaglyphe_precis.
# Tester ici la fonction anaglyphe_precis
anaglyphe_precis(image_gauche,image_droite)
- Si vous disposez d'une image sur fond vert et d'une image de paysage (de mêmes type et dimensions), allez à la question 3.1.a.
- Si vous ne disposez pas d'images, passez directement à la question 3.1.b. pour utiliser les images fournies.
3.1.a. TELECHARGEMENT DE VOS IMAGES
$\;\;\;\;\;\;\;\;$Exécuter successivement les cellules ci-dessous pour télécharger des images personnelles.
$\;\;\;\;\;\;\;\;$Elles seront stockées respectivement dans les variables fond_vert et paysage.
$\;\;\;\;\;\;\;\;$Passer ensuite directement à la question 3.2.
#Cellule pour le téléchargement de votre image sur fond vert
from PIL import Image
import ipywidgets as widgets
uploader3 = widgets.FileUpload(accept='image/*',multiple=False)
print("Cliquer pour charger l'image sur fond vert :")
display(uploader3)
#Cellule pour la mise en mémoire de votre image sur fond vert
from io import BytesIO
try:
[uploaded_file3] = uploader3.value
fond_vert = Image.open(BytesIO(uploader3.value[uploaded_file3]['content']))
print("Nom: fond_vert","\nFormat:",fond_vert.format,"\nMode:",fond_vert.mode,"\nDimensions:",fond_vert.size)
display(fond_vert)
except:
print("Vous n'avez pas chargé d'image ou son format n'est pas reconnu")
#Cellule pour le téléchargement de votre image de paysage
uploader4 = widgets.FileUpload(accept='image/*',multiple=False)
print("Cliquer pour charger l'image de paysage :")
display(uploader4)
#Cellule pour la mise en mémoire de votre image de paysage
try:
[uploaded_file4] = uploader4.value
paysage = Image.open(BytesIO(uploader4.value[uploaded_file4]['content']))
print("Nom: paysage","\nFormat:",paysage.format,"\nMode:",paysage.mode,"\nDimensions:",paysage.size)
display(paysage)
except:
print("Vous n'avez pas chargé d'image ou son format n'est pas reconnu")
3.1.b. TELECHARGEMENT DES IMAGES FOURNIES
$\;\;\;\;\;\;\;\;$Exécuter la cellule ci-dessous pour télécharger les images fournies.
$\;\;\;\;\;\;\;\;$Elles seront stockées respectivement dans les variables fond_vert et paysage.
# Cellule pour charger les images fournies
fond_vert = Image.open('img/Compo/personnage_test.jpg')
paysage = Image.open('img/Compo/paysage_test.jpg')
print("Nom: fond_vert","\nFormat:",fond_vert.format,"\nMode:",fond_vert.mode,"\nDimensions:",fond_vert.size) ; display(fond_vert)
print("Nom: paysage","\nFormat:",paysage.format,"\nMode:",paysage.mode,"\nDimensions:",paysage.size) ; display(paysage)
Nom: fond_vert Format: JPEG Mode: RGB Dimensions: (640, 360)
Nom: paysage Format: JPEG Mode: RGB Dimensions: (640, 360)
3.2. On souhaite réaliser l'incrustation sur fond vert de la façon suivante :
$\;\;\;\;\;$a. Écrire la fonction Python incrustation qui convient.
# Écrire ici la fonction incrustation
def incrustation(fond_vert,paysage,CR=1.3,CB=1.3):
"""
fonction qui réalise l'incrustation de l'image sur fond vert dans le paysage
"""
# vérification que les images sont de même format et taille
if (fond_vert.format,fond_vert.mode,fond_vert.size) != (paysage.format,paysage.mode,paysage.size): return "Images incompatibles"
# récupération des dimensions des images originales
L,H = fond_vert.size
# création d'une image vierge, de même format et même taille que les images initiales
im_incrust = Image.new( mode=fond_vert.mode , size=(L,H) )
# ouverture de l'accès aux pixels des images
pix_fond_vert = fond_vert.load()
pix_paysage = paysage.load()
pix_incrust = im_incrust.load()
# on parcourt tous les pixels des images
for x in range(L):
for y in range(H):
Rv,Gv,Bv = pix_fond_vert[x,y] #récupération des composantes R,G,B du pixel original de l'image sur fond vert
Rp,Gp,Bp = pix_paysage[x,y] #récupération des composantes R,G,B du pixel original de l'image paysage
if Gv > CR*Rv and Gv > CB*Bv:
pix_incrust[x,y] = Rp,Gp,Bp
else:
pix_incrust[x,y] = Rv,Gv,Bv
# on renvoie l'image modifiée
return im_incrust
$\;\;\;\;\;$b. Tester la fonction incrustation.
$\;\;\;\;\;\;\;\;$Si nécessaire, on pourra modifier les valeurs des coefficients de seuil $C_R$ et $C_B$.
# Tester ici la fonction incrustation
incrustation(fond_vert,paysage)
(C) Copyright Franck CHEVRIER 2019-2020 http://www.python-lycee.com/