Python manipulation d'image tkinter

Le problème exposé dans ce sujet a été résolu.

Bonsoir, je souhaite réaliser une machine a photo en python… j’aimerai placer une photo par defaut dans une frame lorsque mon application se lance (plus tard, lorsque j’aurai prit une photo, je voudrai que la nouvelle photo prise remplace l’ancienne…). Seulement lorsque je place ma photo dans la frame (1920x1080) je souhaite qu’elle fasse la même taille que cette frame sans être rognée ce qui pour le moment est le cas (voir l.85).

Toute aide est la bienvenue !

PS : je débute et je n’ai pas reçu de formation en Python donc soyez indulgent sur la qualité du code… :)

mon code :

from tkinter import *
from picamera import PiCamera
import time
from time import sleep
from PIL import Image, ImageTk
import os
from pynput import keyboard

camera = PiCamera()

###chemin d'accès photos
path = '/home/pi/Desktop/Python/Projet/Photos/Photo'


###décompte en secondes
count = 2

###personnalisation de la camera
camera.resolution = (1920,1080)
camera.framerate = 60

###fonction camera
def take_a_photo():
    ###date/heure (locale) de la photo
    dateiso = time.strftime("%Y-%m-%d_%H-%M-%S")
    camera.start_preview(fullscreen = False, window = (50,50,640,480))
    countdown(count)
    camera.capture(path+'_'+dateiso+'.jpeg')
    photo_name = (path+'_'+dateiso+'.jpeg')
    count_label.config(text='Photographie effectuée')
    camera.stop_preview()
    
    #####maphoto = Image.open(path+'_'+dateiso+'.jpeg')    ## Chargement d'une image à partir de PIL
    #####photo = ImageTk.PhotoImage(maphoto)
    #####photo_label = Label(frame, image=photo)
    #####photo_label.image = photo

    print (photo_name)
    
    photo = Image.open(photo_name)
    photo.show(photo_label)

###fonction horloge
def digital_clock(): 
    time_live = time.strftime("%H:%M:%S")
    horloge.config(text=time_live)
    ###actualisation toutes les 500ms
    horloge.after(500, digital_clock)
       
###fonction décompte
def countdown(count):
    while count:
        mins, secs = divmod(count, 60)
        timer = '{:d}'.format(secs)
        #count_label.config(text=count)
        print(timer, end="\r")
        time.sleep(1)
        count -= 1
    print('Photographie effectuée')

###creation mainWindow
mainWindow = Tk()

###personnalisation de la fenetre
mainWindow.title("PhotoBox")
mainWindow.config(background='black')
mainWindow.attributes('-fullscreen', True) #application en plein écran
mainWindow.bind('<Escape>',lambda e: mainWindow.destroy()) #pour enlever le plein écran et quitter

###creation frame
frame = Frame(mainWindow, width=350, height=200, bg='black')

###ajout texte
label_title = Label(mainWindow, text="PhotoBox", font=("koliko-Bold.ttf", 30), bg='black',fg='white')

###ajout décompte
count_label = Label(frame, font=("koliko-Bold.ttf", 20), bg='black', fg='white')

###ajout bouton photo
photo_button = Button(frame, text="Prendre une photo", font=("koliko-Bold.ttf", 20), bg='white', fg='black', command=take_a_photo)

###ajout commentaires
commentaries_label = Label(frame, text="Merci de rester immobile pendant la prise", font=("koliko-Bold.ttf", 10), bg='black', fg='white')

###photo
maphoto = Image.open("Photos/Photo2023-09-2817-26-42.jpeg")    ## Chargement d'une image à partir de PIL
photo = ImageTk.PhotoImage(maphoto)   ## Création d'une image compatible Tkinter
photolabel = Label(frame, image=photo, width = 500, height = 400)
photolabel.image = photo # Maintient en vie de photo dans un objet non détruit

###ajout horloge
horloge = Label(mainWindow, font="koliko-Bold.ttf", bg='black', fg='white')

""" +CREATION+ """
""" -CREATION- """

""" +PLACEMENT+ """
label_title.pack(pady=(50,0))
horloge.pack()
frame.pack(expand=True)
photo_label.grid(row=0, column=0)
count_label.grid(row=1, column=0)
photo_button.grid(row=2, column=0)
commentaries_label.grid(row=3, column=0)
""" -PLACEMENT- """

###appel de la fonction horloge
digital_clock()

###affichage
mainWindow.mainloop()
+0 -0

Bonjour,

Je remarque dans ton code une certaine confusion dans les variables : photolabel est définie ligne 88 mais n’est pas utilisée et photo_label est utilisée ligne 101 mais n’est définie qu’à l’intérieur d’une fonction (donc n’existe pas à la racine du programme).

Mais en simplifiant le code à l’extrême pour ne garder que ce qui pose problème ici, on obtient :

from tkinter import *
from PIL import Image, ImageTk

mainWindow = Tk()

mainWindow.title("PhotoBox")
mainWindow.attributes('-fullscreen', True)

maphoto = Image.open("image.jpg")
photo = ImageTk.PhotoImage(maphoto)
photolabel = Label(mainWindow, image=photo, width=500, height=400)

photolabel.pack()

mainWindow.mainloop()

qui définit simplement une image (avec une taille de 500×400) et l’affiche dans une fenêtre. La photo que j’utilise de mon côté a une définition de 1391×927, et se retrouve effectivement rognée puisque seul le coin haut-gauche tient dans la zone de 500×400.

Une solution serait de redimensionner la photo côté PIL (l’objet obtenu par Image.open) pour qu’elle tienne dans la zone définie. Ainsi en ajoutant maphoto.thumbnail((500, 400)) entre mes lignes 9 et 10 j’obtiens le comportement voulu : la photo est redimensionnée en fonction de la taille donnée, tout en conservant son ratio (environ 1,5 et non 1,25 comme défini par la zone 500×400).

Pour redimensionner sans conserver le ratio, tu pourrais utiliser maphoto = maphoto.resize((500, 400)).

Bonjour, désolé pour la réponse tardive …

Mon problème actuel à bien été résolu je te remercie ! J’ai une autre question maintenant ;) … Comment faire pour que lorsque je prends une nouvelle photo, la photo initiale soit remplacée ? Le problème (je pense que la compréhension de mon côté n’est pas bonne) est que la prise d’une nouvelle photo est faite à l’aide d’une fonction et que ma photo (à la base) est dans une variable de la fonction principale.

Merci beaucoup pour l’aide !

PS : le code n’a pas changé, c’est le même que lorsque j’ai ouvert cette discussion.

+0 -0

Oui c’est possible sans problème, l’erreur rencontrée ne vient pas de là.

L’erreur est que dans ta fonction tu dois avoir cette ligne photo_label.config(image=photo) juste avant une ligne qui définit cette variable photo (photo = ...).
Python ne sait alors pas si le nom photo fait référence à une variable globale définie dans le module (la variable photo dans ton code initial) ou à une variable locale à ta fonction mais qui n’est pas encore définie.

La solution serait donc de placer la définition de la variable avant la ligne qui l’utilise.

Ah, je pense que le soucis est lié à la perte de référence vers ton image. C’est le même soucis contre lequel tu essayais de lutter dans ton code initial en faisant

photolabel.image = photo # Maintient en vie de photo dans un objet non détruit

En effet, tkinter intègre l’image dans le label mais n’en garde pas la trace. Ce qui fait qu’à la sortie de la fonction, l’image n’est plus référencée par aucune variable (les variables de la fonction étant détruites) et n’existe donc plus : elle disparaît (la frame grise).

La solution que tu avais consiste donc à garder la trace de cette image, en l’enregistrant comme un attribut d’un objet défini au niveau du module (photolabel ici).
Une autre solution pourrait être de stocker les images chargées dans une liste ou un dictionnaire défini dans le module.

Bien sûr, le voici :

from tkinter import *
from picamera import PiCamera
import time
from time import sleep
from PIL import Image, ImageTk
import os
from pynput import keyboard

camera = PiCamera()

###chemin d'accès photos
path = '/home/pi/Desktop/Python/Projet/Photos/Photo'


###décompte en secondes
count = 2

###personnalisation de la camera
camera.resolution = (1920,1080)
camera.framerate = 60

###fonction camera
def take_a_photo():
    ###date/heure (locale) de la photo
    dateiso = time.strftime("%Y-%m-%d_%H-%M-%S")
    camera.start_preview(fullscreen = False, window = (50,50,640,480))
    countdown(count)
    camera.capture(path+'_'+dateiso+'.jpeg')
    photo_name = (path+'_'+dateiso+'.jpeg')
    count_label.config(text='Photographie effectuée')
    camera.stop_preview()
    
    #####maphoto = Image.open(path+'_'+dateiso+'.jpeg')    ## Chargement d'une image à partir de PIL
    #####photo = ImageTk.PhotoImage(maphoto)
    #####photo_label = Label(frame, image=photo)
    #####photo_label.image = photo

    print (photo_name)
    
    #photo = Image.open(photo_name)
    #photo.show(photo_label)
    
    photo = ImageTk.PhotoImage(maphoto)
    photo_label.config(image = photo)
    photo_label.image = photo

###fonction horloge
def digital_clock(): 
    time_live = time.strftime("%H:%M:%S")
    horloge.config(text=time_live)
    ###actualisation toutes les 500ms
    horloge.after(500, digital_clock)
       
###fonction décompte
def countdown(count):
    while count:
        mins, secs = divmod(count, 60)
        timer = '{:d}'.format(secs)
        #count_label.config(text=count)
        print(timer, end="\r")
        time.sleep(1)
        count -= 1
    print('Photographie effectuée')

###creation mainWindow
mainWindow = Tk()

###personnalisation de la fenetre
mainWindow.title("Instant Photo")
mainWindow.config(background='black')
mainWindow.attributes('-fullscreen', True) #application en plein écran
mainWindow.bind('<F>',lambda e: mainWindow.destroy()) #pour enlever le plein écran et quitter

###creation frame
frame = Frame(mainWindow, width=350, height=200, bg='black')

###ajout texte
label_title = Label(mainWindow, text="Instant Photo", font=("koliko-Bold.ttf", 60), bg='black',fg='white')

###ajout décompte
count_label = Label(frame, font=("koliko-Bold.ttf", 20), bg='black', fg='white')

###ajout bouton photo
photo_button = Button(frame, text="Prendre une photo", font=("koliko-Bold.ttf", 20), bg='white', fg='black', command=take_a_photo)

###ajout commentaires
commentaries_label = Label(frame, text="Merci de rester immobile pendant la prise", font=("koliko-Bold.ttf", 10), bg='black', fg='white')

###photo
maphoto = Image.open("imagetest.png")    ## Chargement d'une image à partir de PIL
maphoto = maphoto.resize((1920,1080))
photo = ImageTk.PhotoImage(maphoto)   ## Création d'une image compatible Tkinter
photo_label = Label(frame, image=photo, width = 1920, height = 1080)
photo_label.image = photo # Maintient en vie de photo dans un objet non détruit

###ajout horloge
horloge = Label(mainWindow, font="koliko-Bold.ttf", bg='black', fg='white')

""" +CREATION+ """
""" -CREATION- """

""" +PLACEMENT+ """
label_title.pack(pady=(50,0))
horloge.pack()
frame.pack(expand=True)
photo_label.grid(row=0, column=0)
count_label.grid(row=1, column=0)
photo_button.grid(row=2, column=0)
commentaries_label.grid(row=3, column=0)
""" -PLACEMENT- """

###appel de la fonction horloge
digital_clock()

###affichage
mainWindow.mainloop()
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte