IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tkinter Python Discussion :

Utilisation de class Tkinter et OpenCV+Tkinter [Débutant(e)]


Sujet :

Tkinter Python

  1. #1
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2012
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 292
    Par défaut Utilisation de class Tkinter et OpenCV+Tkinter
    Bonjour,

    Je débute sous Tkinter et j'essaie "d'interfacer" mes fonctions utilisant OpenCV avec Tkinter.
    J'ai deux problèmes:

    1) je voudrai pouvoir afficher au cours des traitements une image courante (modifiée à chaque traitement). Je ne vois pas comment organiser mes classes pour ce problème. Cette image serait sur le label d'un frame ( voir image jointe).

    2) je ne trouve pas de moyen pour passer d'une image OpenCV (iplimage) vers une image Tkinter. J'ai essaiée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      pil_image = PIL.Image.fromstring(
                'RGB', 
                cv.GetSize(frame), 
                frame.tostring(), 
                'raw', 
                'BGR', 
                frame.width*3, 
                0)
        tk_image = ImageTk.PhotoImage(pil_image)% Erreur
    Une erreur est renvoiée (de PIL) : Too early to create image. L'architecture de mes classes n'est pas vraiment bien faite. Aussi si vous avez des propositions à améliorer.
    J'ai l'impression que les classes ne sont pas très bien élaborées. Je suis intéressé pour des idées sur ce point.
    Remarque: par la suite les variables 'global' seront enlevées avec la classe MainFrame qui gère l'affichage de l'image et les actualise les paramètres d'entrée des fonctions.
    Merci d'avance
    Images attachées Images attachées  
    Fichiers attachés Fichiers attachés
    • Type de fichier : py menu.py (13,3 Ko, 172 affichages)

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Tu es sûr de tes arguments ? La doc dit ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        cv_im = cv.CreateImage((320,200), cv.IPL_DEPTH_8U, 1)
        pi = Image.fromstring("L", cv.GetSize(cv_im), cv_im.tostring())
    Je parle de cette doc : http://opencv.willowgarage.com/docum.../cookbook.html

  3. #3
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2012
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 292
    Par défaut
    Merci pour votre réponse,

    L'exemple est pour une image niveau de gris. Dans mon cas c'est une image RGB.
    Pour être plus précis je montre les parties concernées:

    Dans la class ParamMeanShift:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	def launch_msf(self):
    		if path==None:
    			app.open()
    		img=ChargeImage(path)
    		self.img_filtree=FiltrageMeanShift(img,self.sp, self.sr, self.PyrScale)	
    		pil_image = Image.fromstring(
    				'RGB', 
    				cv.GetSize(self.img_filtree), 
    				(self.img_filtree).tostring(), 
    				'raw', 
    				'BGR', 
    				(self.img_filtree).width*3, 
    				0)
    		current_image = ImageTk.PhotoImage(pil_image ) # erreur ici
    Les fonctions appelées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def ChargeImage():
    	img = cv.LoadImage( path, cv.CV_LOAD_IMAGE_COLOR)
    	return img
    	
    def FiltrageMeanShift(img,sp,sr,PyrScale):
    
    	##  Filtre MeanShift denoising
    	print("filtrage meanshift...")
    	img_filtree=cv.CloneImage(img)
    	cv.PyrMeanShiftFiltering(img, img_filtree, sp,sr,PyrScale)
    	return	img_filtree
    Les fonctions étant très simples, je ne vois pas d'où vient cette erreur.

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2012
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 292
    Par défaut
    Je viens de remarquer qu'il n'y a pas d'erreur à ce niveau
    L'image OpenCV est bien convertit en PhotoImage.

    Le problème 1) persiste. Je déclare en global current_image dans les différentes classes. Bien que ça fonctionne, ce choix me paraît pas réellement optimal. Je pensais le passer en paramètre de chaque classe mais j'ai l'impression que ça revient au même. Ou bien peut-être transformer mes classes en classes dérivée d'une classe contenant current_image
    Une idée?

  5. #5
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2012
    Messages
    292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 292
    Par défaut
    Finalement le problème est résolue, j'ai utilisé la classe MainFrame comme Class principale. Les autres classes sont déclarer dans la class MainFrame (ParamMeanShift, ParamLight, ParamMarker, ParamFit).
    Voici la class MainFrame:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    class MainFrame(Tk.Frame):
    	""" Affiche paramètres """
    	def __init__(self, boss=None):
    		Tk.Frame.__init__(self) 
    		self.text=Tk.StringVar()
    		self.previous_choice=-1
    		self.frame = Tk.Frame(self)
     
    		self.buttons = [ Tk.Button(self, text="Mean-Shift filtering parmeters", command = lambda x = None: self.change_frame(0)),
    					Tk.Button(self, text="Correction light parameters", command = lambda x = None: self.change_frame(1)),
    					Tk.Button(self, text="Method search markers", command = lambda x = None: self.change_frame(2)),
    					Tk.Button(self, text="Method fitting ellipse", command = lambda x = None: self.change_frame(3)) ]
    		self.pack_buttons()
     
    		# Mode d'allocation des classes
    		self.alloc_subclasse = {0 : ParamMeanShift,
    								1 : ParamLight,
    								2 : ParamMarker,
    								3 : ParamFit}
    		# Allocation des sous classes
    		self.subclasses = [ ParamMeanShift(self.frame, self.buttons[0]), ParamLight(self.frame, self.buttons[1]), ParamMarker(self.frame, self.buttons[2]), ParamFit(self.frame, self.buttons[3]) ]
    		Tk.Button(self, text="Run All", command = self.runall).pack(side = Tk.BOTTOM)
     
    	def pack_buttons(self):
    		self.buttons[0].pack(fill=Tk.X)
    		self.buttons[1].pack(fill=Tk.X)
    		self.buttons[2].pack(fill=Tk.X)
    		self.buttons[3].pack(fill=Tk.X)
     
    	def change_frame(self, frame_choice):
    		""" Destruction du frame de la sous class courante et initialisation de la nouvelle sousclasse """
    		self.subclasses[self.previous_choice].destroy()
    		self.buttons[ self.previous_choice ]["background"] = "white"
    		self.pack_buttons()
    		self.buttons[frame_choice]["background"]="green"
    		self.subclasses[frame_choice]=self.alloc_subclasse[frame_choice](self.frame, self.buttons[frame_choice])
    		self.subclasses[frame_choice].pack()	
    		self.previous_choice = frame_choice		
     
    	def runall(self):
    		global path	, current_image
    		print("Running Mean-Shift Filtering...")
    		if path==None:
    			app.open()
    		self.img=ChargeImage(path)
    		self.img_filtree=FiltrageMeanShift(self.img, sp, sr, PyrScale)	
    		current_image= self.img_filtree
    		self.show_curr_img()
     
    		print("Running RGB->GL, Egalize Histogramme, Correction Light...")
    		current_image=Correction_light( current_image, correction_light, 0)
    		self.show_curr_img()		
     
    		print("Running Watershed...")
    		if method_search_marker=="2":
    			self.contour=Detection_contour(current_image)
    			self.markers= SearchMarker(self.contour, MS_Param.img_filtree, method_search_marker)
    		elif method_search_marker=="4":
    			self.markers= Segmentation(current_image)
    		else:
    			self.markers= SearchMarker(current_image, self.img_filtree, method_search_marker)
    		current_image=self.markers
    		self.show_curr_img()
    		print("Nombre de particules:"+repr(np.max(np.unique(self.markers))))
     
    		print("Searching fitting ellipses....")
    		try:
    			self.b=findEllipse(current_image, method_fit_ellispe, 1)
    		except ValueError:
    			print ValueError			
     
    	def show_curr_img(self):
    		global current_image
    		pil_image = None
    		# Conversion de numpy.ndarray OU cv.iplimage vers PIL.Image (ImageTk.Image)
    		if type(current_image) == cv.iplimage:
    			if current_image.nChannels == 3:
    				pil_image = ImageTk.Image.fromstring(
    						'RGB', 
    						cv.GetSize(current_image), 
    						current_image.tostring(), 
    						'raw', 
    						'BGR', 
    						current_image.width*3, 
    						0)	
    			elif current_image.nChannels==1:
    				pil_image = ImageTk.Image.fromstring(
    						'L', 
    						cv.GetSize(current_image), 
    						current_image.tostring())
    			else:
    				print("Error: Format non compatible nchannels!=1 ou 3")
    		elif type(current_image) == np.ndarray:
    			if len(np.shape(current_image)) == 3 or len(np.shape(current_image)) == 2:
    				if current_image.dtype == np.uint32:
    					im8bit = np.zeros(np.shape(current_image), dtype = np.int8)
    					im8bit += np.floor(current_image*255/(np.max(current_image)-np.min(current_image)))
    					pil_image = ImageTk.Image.fromarray(im8bit)
    				else:
    					pil_image = ImageTk.Image.fromarray(current_image)
    			else:
    				print("Error: Format non compatible nchannels!=1 ou 3")
    		else:
    			print("type d'image gérée")
    		tk_image = ImageTk.PhotoImage(pil_image)
    		try:
    			self.frame.destroy()
    			self.frame = Tk.Frame(self)
    			self.frame.pack()
    			panel1 = Tk.Label(self.frame, image=tk_image)
    			panel1.pack(side=Tk.LEFT, fill=Tk.BOTH, expand='yes')
    			panel1.image = tk_image
    		except ValueError:
    			print(ValueError)
    			pass
    Si vous avez des commentaires sur la structure de la classe (points à améliorer) merci d'avance.
    Images attachées Images attachées  

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/04/2008, 23h27
  2. [Taglibs] Utiliser les classes css ?
    Par PeteMitchell dans le forum Struts 1
    Réponses: 4
    Dernier message: 05/05/2007, 01h31
  3. utilisation de CLASS dans un formulaire
    Par lepierre dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 18/11/2004, 16h38
  4. utiliser des classes dont on n'a pas le source
    Par kocin dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 28/08/2004, 16h05
  5. [Debutant] probleme pour utiliser les classes d'un .jar
    Par pissek dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 12/05/2004, 18h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo