I made a program to capture photos from 3 web cams (with video capture).
With one or two cams, the program works perfectly.
With 3 cams, my program doesn't work.
The third window still blank (white).
This is my code (in attachement). Do you have the time to check it ?
It will be very kind of you.
Thank you in advance.
David
Belgium
Expand|Select|Wrap|Line Numbers
- cam.txt
- #coding:latin1
- """
- name: Camera Manager
- version: 2.0.1
- author: nano corp.
- """
- from tkMessageBox import askyesno
- from Tkinter import Tk,LabelFrame,Button,Entry,Label,Spinbox,Frame,StringVar,\
- Radiobutton,Checkbutton,BooleanVar,Text,END
- from time import time,sleep,gmtime
- from Image import fromstring
- import Image
- from vidcap import new_Dev
- import pymedia.video.vcodec as vcodec
- import os,sys, user
- #Réglage du nombre limite de récursion
- sys.setrecursionlimit(1024**2)
- ### Définition des constantes
- # Quelques valeurs globales #
- larg_chk = 16
- larg_btn = 16
- larg_msg = 33
- # Quelques paramètres
- default_delay = 240 #La valeur par défaut du délai (en secondes) :240
- dec_delay = 10 #La valeur unitaire du délai :10
- default_acq = 1080 #Le nombre d'acquisition par défaut :1080
- default_duree = 60 #La durée par defaut de la vidéo (en secondes) :60
- ### Défintion des fonctions ###
- def convert(tps=0):
- """converti un nombre donné de secondes
- en jours,heures,minutes,secondes"""
- sec = tps%60
- min = (tps/60)%60
- heu = (tps/3600)
- day = (heu/24)
- heu = heu%24
- return (day,heu,min,sec)
- ### Défintion des classes ###
- class Timer:
- """ Classe servant de chronomètre"""
- def __init__(self,tps=None):
- if tps==None:
- self.restant = 3*24*3600 #3 jours par défaut.
- self.init = tps
- def start(self,tps):
- """Initialise le chronomètre"""
- self.total = tps
- self.restant = tps
- self.conte = 0
- self.init = time()
- def get(self):
- """renvoie le temps restant sous forme
- jours,heures,minutes,secondes"""
- self.tps = int(self.restant-(time()-self.init))
- return convert(self.tps)
- def get_duree(self):
- """renvoie la durée écoulé"""
- return time()-self.init
- def BuildVideo ( images,output_filename,size,time=60 ):
- '''Construit une vidéo à partir de la liste d'images.
- images : liste des noms de fichiers des images
- output_filename : nom de la video (attention à l'extension)
- size : (largeur,hauteur) en pixels de la vidéo générée
- Les paramètres du codec sont ceux trouvés dans les tutoriels de pymedia.
- '''
- nb_images = 1
- if len(images)>1:
- nb_images = len(images)
- if nb_images>=20:
- frame_rate_base = 1567641600/nb_images
- frame_rate = frame_rate_base*nb_images/time
- rate = frame_rate/frame_rate_base
- params = {
- 'type' : 0,
- 'gop_size' : 12,
- # frame rate = frame_rate/frame_rate_base : ici déterminer par la duree et le nb d'images
- # attention : tous les frames rate ne sont pas supportés
- 'frame_rate' : frame_rate_base*nb_images/time,
- 'frame_rate_base' : frame_rate_base,
- 'max_b_frames' : 0,
- 'height' : size[1],
- 'width' : size[0],
- 'deinterlace' : 0,
- 'bitrate' : 2700000,
- 'id' : vcodec.getCodecID( 'mpeg1video' ) }
- #Lorsqu'il y a peu d'images cela pose quelques problèmes
- else:
- rate = 1
- params = {
- # frame rate = frame_rate/frame_rate_base : ici = 1 im/sec
- # attention : tous les frame rate ne sont pas supportés
- 'frame_rate' : 1,
- 'frame_rate_base' : 1,
- 'max_b_frames' : 0,
- 'height' : size[1],
- 'width' : size[0],
- 'deinterlace' : 0,
- 'bitrate' : 2700000,
- 'id' : vcodec.getCodecID( 'mpeg1video' ) }
- tmp = [images[0]]
- for i in range(time):
- pos = i*nb_images/time
- tmp.append(images[pos])
- images = tmp
- encoder = vcodec.Encoder( params ) # créé une instance d'encodeur
- output = open( output_filename,'wb' ) # créé le fichier de sortie
- for i,im in enumerate(images) :
- # recupère l'image sous forme d'une string raw
- bitmap = Image.open( im ).resize( size ).tostring()
- # en fait une frame rgb
- frame_rgb = vcodec.VFrame( vcodec.formats.PIX_FMT_RGB24,size,
- ( bitmap,None,None ),rate=rate,
- frame_number=i,pts=i,resync=True)
- f = frame_rgb
- # la convertit en frame yuv (l'encodeur n'accepte pas directement du rgb)
- frame_yuv = frame_rgb.convert( vcodec.formats.PIX_FMT_YUV420P )
- # encode la frame
- encoded = encoder.encode( frame_yuv )
- # ajoute la frame encodée au fichier
- output.write( encoded.data )
- # laisse 1
- sleep(0.001)
- # ferme le fichier de sortie
- output.close()
- ### nouvelle classe! ###
- class Progress(Frame):
- """Barre de progression"""
- def __init__(self,master=None,value=0,width=32,bg='gray'):
- Frame.__init__(self,master,width=width,relief='sunken',bd=2)
- self.larg =width
- width = int(value/width)
- #Le label qui représentera la partie effectuée
- self.lbl = Label(self,bg=bg)
- self.lbl.pack(side='left')
- #Le label qui représentera le reste
- self.rst = Label(self)
- self.rst.pack(side='right')
- self.set(value)
- def set(self,value=0):
- """définit la nouvelle valeur de la barre de progression"""
- width = ((value*self.larg)/100.0)%self.larg
- width = int(width)
- rest = int(round(self.larg-width-1))
- txt1 = ''
- txt2 = ''
- if value>=50:
- txt1 = str(value)+'%'
- else:
- txt2 = str(value)+'%'
- self.lbl.configure(text=txt1,width=width)
- self.rst.configure(text=txt2,width=rest)
- if value == 100:
- self.lbl.configure(width=self.larg)
- self.rst.pack_forget()
- else:
- self.rst.pack(side='right')
- ### Panneau Experiment ###
- class panneau1(LabelFrame):
- """ Eléments à accès externe
- self.txt_msg:pour le configure la premier zone de message
- self.txt_msg.configure(text=nouveau_message)
- self.sel_delay:pour la valeur de delay
- self.sel_delay.get() pour récupérer la valeur (puis
- convertir sous forme d'entier): int(val)
- self.sel_acq:pour la valeur de acq
- self.sel_acq.get() pour récupérer la valeur (puis
- convertir sour forme d'entier): int(val)
- self.txt_total: pour afficher le temps total
- self.txt_total.configure(text=nouveau_temps)
- self.chk_close: pour la valeur de la case "Close at end"
- self.chk_close.get() pour récupérer le choix de l'utilisateur
- """
- def __init__(self,parent=None,func=None):
- LabelFrame.__init__(self,parent,text='Experiment ',bd=4,padx=5,pady=5,
- width=larg_msg,relief='sunken')
- frm = Frame(self)
- frm.grid(row=1,column=1)
- ## Les labels
- #Le label qui affiche les messages en dessous de Experiment
- tps = gmtime()
- txt_msg = "L.allemnand_FC10_"+str(tps[2]).rjust(2,'0')+"_"+str(tps[1]).rjust(2,'0')+\
- "_"+str(tps[0])+"_e2"
- self.msg_var = StringVar(self)
- self.msg_var.set(txt_msg)
- frm_txt = LabelFrame(self,text="Répertoire de sauvegarde: ",relief="flat")
- self.txt_msg = Entry(frm_txt,width=larg_msg,textvariable=self.msg_var,
- relief='sunken')
- lbl_delay = Label(frm,text='Délay(s)',anchor='nw')
- lbl_acq = Label(frm,text='# Acquisition.',anchor='nw')
- lbl_res = Label(frm,text='Résolution',anchor='nw')
- lbl_duree = Label(frm,text='Durée vidéo (s)',anchor='nw')
- lbl_total = Label(frm,text='Total',anchor='nw')
- ## Les commandes
- #Le sélecteur de delay
- self.sel_delay = Spinbox(frm,from_=dec_delay,to=302400,width=larg_chk,state="readonly",
- bd=2,increment=dec_delay,repeatinterval=20)
- self.var_delay = StringVar(self.sel_delay)
- self.sel_delay.configure(textvariable=self.var_delay)
- self.sel_delay.bind("<KeyRelease>",self.change)
- #Veuillez excuser la méthode un peu violente
- for i in range(0,default_delay,dec_delay):
- self.sel_delay.invoke("buttonup")
- #Le sélecteur de acq.
- self.sel_acq = Spinbox(frm,from_=1,to=1000000,width=larg_chk,state="readonly",
- bd=2,repeatinterval=10)
- self.var_acq = StringVar(self.sel_acq)
- self.sel_acq.configure(textvariable=self.var_acq)
- self.sel_acq.bind("<KeyRelease>",self.change)
- #Veuillez excuser la méthode un peu violente
- for i in range(default_acq):
- self.sel_acq.invoke("buttonup")
- #Le sélecteur de résolution
- res = (#Résolutions pour une version future de Pymedia (trop petite taille).
- #"128 x 96 (phone)","176 x 144 (phone)",
- "320 x 200 (mobile)","320 x 240 (ipod)","352 x 288 (mobile)",
- "368 x 208 (PSP)","400 x 300 (mobile)","480 x 360 (mobile)","512 x 384 (PC)","640 x 400 (PC)",
- "640 x 480 (PC)","800 x 600 (PC)","1024 x 768 (PC)","1152 x 864 (PC)",)
- #Résolutions pour une version ultérieure de Pymedia (trop grande taille)
- #"1280 x 720 (HD)","1280 x 768 (HD)","1280 x 960 (HD)","1280 x 1024 (HD)","1600 x 900 (VHD)",
- #"1600 x 1024 (VHD)","1600 x 1200 (VHD)","1920 x 1080 (VHD)","1920 x 1200 (VHD)","1920 x 1440 (VHD)",
- #"2048 x 1536 (VHD)")
- self.sel_res = Spinbox(frm,values=res,width=larg_chk,bd=2,state="readonly")
- self.var_res = StringVar(self.sel_res)
- self.sel_res.configure(textvariable=self.var_res)
- for i in range(10):
- self.sel_res.invoke("buttonup")
- #Le sélecteur de la durée
- self.sel_duree = Spinbox(frm,width=larg_chk,bd=2,state="readonly",
- from_=10,to=3600*24,increment=10)
- self.var_duree = StringVar(self.sel_duree)
- self.sel_duree.configure(textvariable=self.var_duree)
- #Veuillez excuser la méthode un peu violente
- for i in range(0,default_duree,10):
- self.sel_duree.invoke("buttonup")
- #Le label qui affiche le temps total
- self.txt_total =Label(frm,text='3 jours 00:00:00',width=18,relief='sunken')
- #La case à cocher close_at_end
- self.bol_close = BooleanVar()
- self.bol_close.set(False)
- self.chk_close = Checkbutton(frm,text="Fermer à la fin",variable=self.bol_close)
- #Le boutton exit
- #C'est à vous de voir comment vous allez gérer la sortie!
- #le paramètre command devra être remplacé par une de vos méthodes
- self.btn_exit = Button(frm,text='Quitter',command=func,
- width=larg_btn)
- ## Affichage des widgets
- frm_txt.grid(row=0,column=1)
- self.txt_msg.pack()
- lbl_delay.grid(row=1,column=1,sticky='w')
- lbl_acq.grid(row=2,column=1,sticky='w')
- self.sel_delay.grid(row=1,column=2,sticky='e')
- self.sel_acq.grid(row=2,column=2,sticky='e')
- lbl_res.grid(row=3,column=1,sticky='w')
- self.sel_res.grid(row=3,column=2,sticky='e')
- lbl_duree.grid(row=4,column=1,sticky='w')
- self.sel_duree.grid(row=4,column=2,sticky='e')
- lbl_total.grid(row=5,column=1,sticky='w')
- self.txt_total.grid(row=5,column=2,sticky='e')
- self.chk_close.grid(row=6,column=1,sticky='w')
- self.btn_exit.grid(row=6,column=2,sticky='e')
- self.sel_delay.configure(command=self.change)
- self.sel_acq.configure(command=self.change)
- self.change()
- def change(self,event=None):
- """Met à jour le temps le nécessaire
- en fonction du nombre de photos et du délai
- unitaire des photos"""
- delay = int(self.sel_delay.get())
- acq = int(self.sel_acq.get())
- self.tps = delay*acq
- self.sel_acq.max = 378432000/delay
- tps = convert(self.tps)
- txt = str(tps[0])+' jours '+str(tps[1]).rjust(2,'0')+':'+\
- str(tps[2]).rjust(2,'0')+':'+str(tps[3]).rjust(2,'0')
- self.txt_total.configure(text=txt)
- ### Panneau Acquisition ###
- class panneau2(LabelFrame):
- """Eléments externes
- self.cpt1: La première barre de progression
- self.cpt1.set(valeur) pour changer la valeur du compteur
- self.txt_acq: pour changer le rapport '331/1030'
- self.txt_acq.configure(text=nouvelle_valeur)
- self.cpt2: La deuxième barre de progression
- self.cpt2.set(valeur) pour changer la valeur du compte
- self.txt_time: Pour changer le texte de temps
- self.txt_time.configure(text=nouveau_temps)
- """
- def __init__(self,parent=None,rec=None,stop=None,cancel=None):
- LabelFrame.__init__(self,master=parent,text='Acquisition',bd=4,relief='sunken')
- frm = Frame(self)
- # La bare de progession n°1
- self.cpt1 = Progress(frm,width=17,bg="gray70")
- # Le label qui afffiche le rapport de acq
- self.txt_acq = Label(frm,text='0/0',relief='sunken',bd=2,
- width=16)
- #La barre de progression n°2
- self.cpt2 = Progress(self,width=34,bg="gray45")
- #La barre de progression n°3
- self.cpt3 = Progress(self,width=34,bg="gray")
- #Le label qui affiche la durée
- self.txt_time = Label(self,text='0 jours 00:00:00',width=19,bd=2,
- relief='sunken',font = "{MS Sans Serif} 14")
- self.txt_time.grid(row=3,sticky='w')
- frm1 = Frame(self)
- #Le boutton d'enregistrement
- #le paramètre command devra être remplacé
- self.btn_rec = Button(frm1,text='REC',bg='red',width=larg_btn,
- activebackground='red',command=rec)
- #Le bouton d'arrêt
- #le paramètre command devra être remplacé
- self.btn_stop = Button(frm1,text='STOP',width=larg_btn,command=stop)
- #Le bouton d'annulation
- self.btn_cancel = Button(self,text='CANCEL',width=larg_btn*2+2,command=cancel)
- ## Affichage des widgets
- self.cpt1.grid(row=1,column=1,sticky='w')
- self.txt_acq.grid(row=1,column=2,sticky='e')
- self.cpt2.grid(row=2,sticky='w')
- self.cpt3.grid(row=4,sticky='w')
- frm.grid(row=1,sticky='w')
- self.btn_rec.grid(row=1,column=1,sticky='w')
- self.btn_stop.grid(row=1,column=2,sticky='e')
- self.btn_cancel.grid(row=6,sticky='w')
- frm1.grid(row=5)
- ### classe Manager ###
- class projet(Tk):
- """ Fenêtre principale
- devnum: l'indice de la caméra à utiliser 0..n
- Eléments externes:
- self.time: le timer il prend un argument facultatif,le temps de décompte
- exprimé en secondes
- self.pan_exp: le panneau Experiment
- self.pan_acq: le panneau d'Acquisition
- """
- nb_instance = [0]
- def __init__(self,devnum=0):
- Tk.__init__(self)
- self.title("Gestionnaire Cam. "+str(devnum))
- self .resizable(False,False)
- self.wm_protocol("WM_DELETE_WINDOW",self.term)
- self.iconbitmap("my_icon.ico")
- self.numero = devnum
- #Le panneau Experiment
- self.pan_exp = panneau1(self,self.term)
- #Le panneau Acquisition
- self.pan_acq = panneau2(self,self.start_rec,self.stop_rec,self.abort_rec)
- ## Affichage des widgets
- self.pan_exp.pack()
- self.pan_acq.pack()
- txt = """
- http://www.lib.ac.be.polytech/USA\t
- copyright 2010\t\t\t
- """
- Label(self,text=txt).pack()
- self.timer = Timer()
- self.rec = False
- self.alive = True
- self.started_rec = False
- self.nb_instance[0] +=1
- #Création de la Caméra
- try:
- self.cam = new_Dev(self.numero,1)
- #Initialisation du visualisateur
- self.getImage()
- except:
- #IL n'y a pas de cam avec cet indice disponible
- #Arrêt du programme!
- #self.term()
- pass
- def open_rep(self):
- """ ouvre le dossier contenant les enregistrement. """
- try:
- me = self.rep
- cmd = "start explorer "+self.rep
- os.system(cmd)
- except:
- pass
- def getImage(self):
- """Renvoie l'image contenue dans la mémoire tempon
- de a caméram"""
- if self.alive:
- buf,w,h = self.cam.getbuffer()
- return fromstring('RGB',(w,h),buf,'raw','BGR',0,-1)
- def BuildVideo (self,images,output_filename,size,time=60 ):
- '''Construit une vidéo à partir de la liste d'images.
- images : liste des noms de fichiers des images
- output_filename : nom de la video (attention à l'extension)
- size : (largeur,hauteur) en pixels de la vidéo générée
- Les paramètres du codec sont ceux trouvés dans les tutoriels de pymedia.
- '''
- nb_images = 1
- if len(images)>1:
- nb_images = len(images)
- if nb_images>=20:
- frame_rate_base = 1567641600/nb_images
- frame_rate = frame_rate_base*nb_images/time
- rate = frame_rate/frame_rate_base
- params = {
- 'type' : 0,
- 'gop_size' : 12,
- # frame rate = frame_rate/frame_rate_base : ici déterminer par la duree et le nb d'images
- # attention : tous les frames rate ne sont pas supportés
- 'frame_rate' : frame_rate_base*nb_images/time,
- 'frame_rate_base' : frame_rate_base,
- 'max_b_frames' : 0,
- 'height' : size[1],
- 'width' : size[0],
- 'deinterlace' : 0,
- 'bitrate' : 2700000,
- 'id' : vcodec.getCodecID( 'mpeg1video' ) }
- #Lorsqu'il y a peu d'images cela pose quelques problèmes
- else:
- rate = 1
- params = {
- # frame rate = frame_rate/frame_rate_base : ici = 1 im/sec
- # attention : tous les frame rate ne sont pas supportés
- 'frame_rate' : 1,
- 'frame_rate_base' : 1,
- 'max_b_frames' : 0,
- 'height' : size[1],
- 'width' : size[0],
- 'deinterlace' : 0,
- 'bitrate' : 2700000,
- 'id' : vcodec.getCodecID( 'mpeg1video' ) }
- tmp = [images[0]]
- for i in range(time):
- pos = i*nb_images/time
- tmp.append(images[pos])
- images = tmp
- nb_images = len(images)
- encoder = vcodec.Encoder( params ) # créé une instance d'encodeur
- output = open( output_filename,'wb' ) # créé le fichier de sortie
- for i,im in enumerate(images) :
- # recupère l'image sous forme d'une string raw
- bitmap = Image.open( im ).resize( size ).tostring()
- # en fait une frame rgb
- frame_rgb = vcodec.VFrame( vcodec.formats.PIX_FMT_RGB24,size,
- ( bitmap,None,None ),rate=rate,
- frame_number=i,pts=i,resync=True)
- f = frame_rgb
- # la convertit en frame yuv (l'encodeur n'accepte pas directement du rgb)
- frame_yuv = frame_rgb.convert( vcodec.formats.PIX_FMT_YUV420P )
- # encode la frame
- encoded = encoder.encode( frame_yuv )
- # ajoute la frame encodée au fichier
- output.write( encoded.data )
- # laisse 1ms au CPU pour les autres programmes en cours
- sleep(0.001)
- # mise à jour de la barre de progression
- self.pan_acq.cpt3.set(i*100/nb_images)
- self.pan_acq.update()
- # ferme le fichier de sortie
- output.close()
- def start_rec(self,event=None):
- """Lance le début de l'enregistrement"""
- if not self.started_rec:
- #récupération du nombre de photos
- self.nb_photos = int(self.pan_exp.var_acq.get())
- #Délai de repétition des photos
- self.tps_repeat = int(self.pan_exp.var_delay.get())
- #Index de départ des photos
- self.index = 0
- ## Création du répertoire de sauvegarde des photos
- #Récupération du nom saisi par l'utilisateur
- self.rep = self.pan_exp.msg_var.get()
- #Liste des caractères invalides pour un nom de dossier
- chars = ('"|:\/*?')
- #Suppression des caractères invalides
- for char in chars:
- self.rep = self.rep.replace(char,'')
- #Utilisation d'un répertoire par défaut au cas où le
- #nouveau nom est NULL
- if not self.rep:
- #Récupération de la date pour le nom du répertoire
- date = gmtime()
- self.rep = "Images_"+str(date[2]).rjust(2,"0")+"_"\
- +str(date[1]).rjust(2,"0")+"_"+str(date[0])
- #On limite le nom du répertoire à 100 caractères
- self.rep = self.rep[0:100]
- join = os.path.join
- if os.path.isdir(join(user.home,"Mes Documents")):
- mesdoc = join(user.home,"Mes Documents")
- elif os.path.isdir(join(user.home,"My Documents")):
- mesdoc = join(user.home,"My Documents")
- else:
- mesdoc = join(user.home,"Documents")
- path = join(mesdoc,"Camera Manager")
- path += os.path.sep
- if not os.path.isdir(path):
- try:
- os.mkdir(path)
- except:
- pass
- #On affiche à l'utilisateur le nom qui sera utilisé
- self.pan_exp.msg_var.set(self.rep)
- self.rep = path+self.rep
- suffix = "_cam_%s"%self.numero
- suffix = suffix.upper()
- if not (self.rep[:6].upper() == suffix):
- self.rep += "_Cam_%s"%self.numero
- #Si le répertoire n'existe pas encore, on le crée
- if not (os.path.isdir(self.rep)):
- try:
- os.mkdir(self.rep)
- except:
- pass
- else:
- create = askyesno("Ce Dossier existe déjà!",
- """Un dossier de même nom existe déjà.
- Si vous continuez,les anciennes données
- de ce dossier seront écrasées.
- Voulez vous continuer?""",master=self)
- #Si l'utilisateur décide de ne pas continuer, on met
- #une valeur d'arrêt dans tps_repeat pour stopper l'
- #enregistrement.
- if create:
- lst = os.listdir(self.rep)
- try: #mesure au cas où un fichier est ouvert.
- for i in lst:
- if os.path.isfile(join(self.rep,i)):
- os.remove(join(self.rep,i))
- except:
- pass
- else :
- self.tps_repeat = -1
- #Récupération de la résolution
- res = self.pan_exp.var_res.get()
- res = res.split(" ")
- self.resolution = int(res[0]),int(res[2])
- #Récupération de la durée de la Vidéo
- self.duree = int(self.pan_exp.var_duree.get())
- ## Désactivation des commandes à présent inutiles ##
- self.pan_exp.txt_msg.configure(state='readonly')
- self.pan_exp.sel_delay.configure(state='disable')
- self.pan_exp.sel_acq.configure(state='disable')
- self.pan_exp.sel_res.configure(state='disable')
- self.pan_exp.sel_duree.configure(state='disable')
- self.pan_acq.btn_rec.configure(state='disable')
- self.pan_exp.btn_exit.configure(state='disable')
- self.pan_acq.cpt3.set(0)
- if self.tps_repeat>0:
- ## Activation des booléens
- self.started_rec = True
- self.rec = True
- #Initialisation du timer
- self.timer.start(self.pan_exp.tps)
- #Initialisation de l'entier de capture
- self.next_int = 1
- #Lancement de la classe!
- self.after(149,self.update_time)
- else:
- self.stop_rec(abort=False)
- def stop_rec(self,event=None,abort=True):
- """Stoppe l'enregistrement"""
- self.rec = False
- if abort and self.started_rec:
- if self.index>0: #On vérifief qu'on a au moins 1 image
- self.mi_action()
- ## Activation des commandes désactivées plus tôt
- self.pan_exp.txt_msg.configure(state='normal')
- self.pan_exp.sel_delay.configure(state='readonly')
- self.pan_exp.sel_acq.configure(state='readonly')
- self.pan_exp.sel_res.configure(state='readonly')
- self.pan_exp.sel_duree.configure(state='readonly')
- self.pan_acq.btn_rec.configure(state='normal')
- self.pan_exp.btn_exit.configure(state='normal')
- ## Désactivation des booléen
- if self.started_rec:
- self.started_rec = False
- self.pan_acq.txt_time.configure(text="Enregistrement Arrêté")
- def abort_rec(self,event=None):
- self.rec = False
- """Stoppe l'enregistrement"""
- ## Activation des commandes désactivées plus tôt
- self.pan_exp.txt_msg.configure(state='normal')
- self.pan_exp.sel_delay.configure(state='readonly')
- self.pan_exp.sel_acq.configure(state='readonly')
- self.pan_exp.sel_res.configure(state='readonly')
- self.pan_exp.sel_duree.configure(state='readonly')
- self.pan_acq.btn_rec.configure(state='normal')
- self.pan_exp.btn_exit.configure(state='normal')
- ## Désactivation des booléen
- if self.started_rec:
- self.started_rec = False
- self.pan_acq.txt_time.configure(text="Enregistrement Annulé")
- def action(self):
- """Produit la vidéo lorsque toutes les photos ont été prises."""
- self.rec = False
- self.pan_acq.cpt1.set(100)
- self.pan_acq.cpt2.set(100)
- self.pan_acq.txt_time.configure(text="Production de la vidéo")
- self.pan_acq.btn_stop.configure(state="disable")
- self.update()
- images = filter( lambda f : f[-4:] in ['.jpg','.bmp','.png'] , os.listdir(self.rep))
- for i,img in enumerate(images):
- images[i] = os.path.join(self.rep,img)
- fic = os.path.join(self.rep,"movie_"+str(self.numero)+".avi")
- self.BuildVideo( images , fic,self.resolution,self.duree)
- self.pan_acq.cpt3.set(100)
- #Si on a pris toutes les photos
- #Et que la case <close at the end> est cochée
- #alors on arrête le programme
- self.pan_acq.btn_stop.configure(state="normal")
- self.pan_acq.txt_time.configure(text="Fin de l'enregistrement")
- self.open_rep()
- if self.pan_exp.bol_close.get():
- self.alive = False
- self.term()
- self.started_rec = False
- self.stop_rec()
- def mi_action(self):
- """Produit la vidéo avec une partie des photos"""
- self.rec = False
- self.pan_acq.txt_time.configure(text="Production de la vidéo")
- self.pan_acq.btn_stop.configure(state="disable")
- self.update()
- images = filter( lambda f : f[-4:] in ['.jpg','.bmp','.png'] , os.listdir(self.rep))
- for i,img in enumerate(images):
- images[i] = os.path.join(self.rep,img)
- fic = os.path.join(self.rep,"movie_"+str(self.numero)+".avi")
- self.BuildVideo( images , fic,self.resolution,self.duree)
- self.pan_acq.cpt3.set(100)
- #Si on a pris toutes les photos
- #Et que la case <close at the end> est cochée
- #alors on arrête le programme
- self.pan_acq.btn_stop.configure(state="normal")
- self.pan_acq.txt_time.configure(text="Fin de l'enregistrement")
- self.open_rep()
- if self.pan_exp.bol_close.get():
- self.alive = False
- self.term()
- self.started_rec = False
- self.stop_rec()
- def capture(self):
- """Sauvegarde l'image contenue dans la mémoire tempon de la cam
- sur le disque dur"""
- fic = os.path.join(self.rep,"Capture_cam"+str(self.numero)+"_"+str(self.index).rjust(4,'0')+".jpg")
- #Récupération de l'image dans la mémoire tempon de la caméra
- try:
- img = self.getImage()
- except:
- img = Image.new("RGB",(640,480))
- img = img.resize(self.resolution)
- #Sauvegarde de l'image sur le disque dur
- img.save(fic)
- if self.nb_photos-1==self.index:
- self.action()
- #Mise à jour de l'index des photos prises(nombre)
- self.index+=1
- def update_time(self):
- """Met à jour les différents affichages du manager de caméra
- #moteur de manager#"""
- if self.alive and self.rec:
- # Le timer est réglé sur 100 ms
- self.after(100,self.update_part)
- #Récupération du temps restant en jours/heures/min/secs
- tps = self.timer.get()
- txt = str(tps[0])+' jours '+str(tps[1]).rjust(2,'0')+':'+\
- str(tps[2]).rjust(2,'0')+':'+str(tps[3]).rjust(2,'0')
- for i in tps:
- if i<0:
- txt = "Patientez un instant."
- self.pan_acq.txt_time.configure(text=txt)
- #Récupération du temps écoulé
- tps = self.timer.get_duree()
- # mise à jour de la barre de progression n°1
- pourcent = ((tps+0.5)%self.tps_repeat)*100/self.tps_repeat
- pourcent = round(pourcent,2)
- self.pan_acq.cpt1.set(pourcent)
- # mise à jour de la barre de progressoin n°2
- pourcent = round((tps)*100/self.timer.total,3)
- if pourcent>100:
- pourcent = 100
- self.pan_acq.cpt2.set(pourcent)
- # Test puis prise de la photo si le timing est exact!
- # On utilise une plage de temps ce qui permet d'éviter les
- # sauts de photos lorsque le CPU est en surutilisation
- if int((tps+0.5)/self.tps_repeat)==self.next_int:
- self.capture()
- self.next_int+=1
- # On prévoit tout de même qu'il puisse y avoir un saut de photos
- # alors on permet au programme de continuer à photographier
- elif int((tps+0.5)/self.tps_repeat)>self.next_int:
- self.next_int = int((tps+0.5)/self.tps_repeat)
- # Mise à jour du nombre de photos prises
- txt = str(self.index)+' / '+str(self.nb_photos)
- self.pan_acq.txt_acq.configure(text=txt)
- self.update()
- def update_part(self):
- """juste pour une double récursion,meilleure que la directe"""
- self.update_time()
- def update_cam(self,event=None):
- """renouvelle la caméra ou la fait réapparâitre au cas où elle
- a été accidentellement détruite!"""
- self.cam = None
- self.cam = new_Dev(self.numero,1)
- self.getImage()
- def term(self,event=None):
- """met terme aux activités et ferme le visualisateur
- et le manager de la caméra"""
- if not self.started_rec:
- self.alive = False
- self.cam = None
- self.after(20,self.destroy)
- self.nb_instance[0]-=1
- if self.nb_instance[0] ==0:
- self.quit()
- def main():
- """Fonction main commen en C """
- nb_cam = 3
- def validate():
- """Démarre les gestionnaire de Caméras"""
- nb_cam = get_value()
- root.destroy()
- for i in range(nb_cam):
- self = projet(i)
- #Petit problème de binding sous Python24
- #Je fais donc le bind à l'extérieur de la classe
- self.bind("<Escape>",self.stop_rec)
- self.bind("<Return>",self.start_rec)
- self.bind("<Control U>",self.update_cam)
- self.bind("<Control u>",self.update_cam)
- self.bind("<Alt x>",self.term)
- self.bind("<Alt X>",self.term)
- def get_value():
- """Récupère le nombre d'instances de voulu (de caméras)"""
- global nb_cam
- nb_cam = int(var_nb.get())
- return nb_cam
- def terminate():
- """Ferme le programme"""
- root.destroy()
- root.quit()
- root = Tk()
- root.resizable(False,False)
- root.title("Camera Manager")
- root.iconbitmap("my_icon.ico")
- root.wm_protocol("WM_DELETE_WINDOW",terminate)
- txt = "\n\tCAMERA MANAGER v2.0.1\n\nLes raccourcis sont les suivants:\n- Entrer : lancer un enregistrement\n- Echap : arrêter l'enregistrement en cours\n- Control + U : Actualiser manuellement la caméra\nou l'afficher si elle a été fermée accidentellement\n- Alt + X : Quitter le Programme\n\nLes boutons Fermer (X) et Exit ne sont pas actifs\nlors de l'enregistrement il faut d'abord arrêter\nl'enregistrement pour quitter le programme\n\nLes photos sont sauvegardez dans le dossier\n'Camera Manager\Le_nom_de_votre_dossier' du\nrépertoire 'Mes Documents' ou 'My Documents'\nLe suffixe '_Cam_X' est ajouté au nom du dossier\npour différencier les caméras (X est le numero de\nla caméra)\n\nmerci de reporter les bugs à\n"
- emails = "\t\tddubois2@gmail.com\n\t"
- lbl = Text(root,state="normal",bg=root.cget("bg"),width=40,cursor="")
- lbl.tag_add("email",0.0)
- lbl.tag_config("email",foreground="blue",u=True)
- lbl.insert(END,txt)
- lbl.insert(END,emails,"email")
- lbl.configure(state="disable")
- lbl.pack()
- lfrm = LabelFrame(root,text="Nombre de Caméras",relief="flat")
- lfrm.pack()
- sel_nb = Spinbox(lfrm,from_=1,to=5,state="readonly",command=get_value,width=8)
- var_nb = StringVar(sel_nb)
- sel_nb.configure(textvariable=var_nb)
- for i in range(nb_cam):
- sel_nb.invoke("buttonup")
- sel_nb.pack()
- Button(root,text="Valider",width=larg_btn,command=validate).pack(side="right",padx=5,pady=5)
- Button(root,text="Quitter",width=larg_btn,command=terminate).pack(side="left",padx=5,pady=5)
- root.mainloop()
- if __name__ == "__main__":
- main()