def __init__(self, master, image, name, enhancer, lo, hi): Frame.__init__(self, master) # set up the image self.tkim = ImageTk.PhotoImage(image.mode, image.size) self.enhancer = enhancer(image) self.update("1.0") # normalize # image window Label(self, image=self.tkim).pack() # scale s = Scale(self, label=name, orient=HORIZONTAL, from_=lo, to=hi, resolution=0.01, command=self.update) s.set(self.value) s.pack()
def __init__(self, master, image, image_name): Frame.__init__(self, master) self.image = image self.image_name = image_name # make a blank image for the text, initialized to transparent text color self.blank_image = Image.new('RGBA', self.image.size, (255,255,255,0)) self.fnt = ImageFont.truetype('fonts/MontereyFLF.ttf', 50) self.d = ImageDraw.Draw(self.blank_image) #default watermark self.name = "watermark" self.loc_x = 0 self.loc_y = 225 self.rgbo = (0,0,0,200) self.d.text((self.loc_x, self.loc_y), self.name, font=self.fnt, fill=self.rgbo) self.out = Image.alpha_composite(self.image, self.blank_image) self.tkim = ImageTk.PhotoImage(self.out) #display image Label(root, image=self.tkim).pack() # opacity scale s_opacity = Scale(self, label="Opacity", orient=HORIZONTAL, from_=0, to=255, resolution=1, command=self.update_opacity) s_opacity.set(200) s_opacity.pack(pady = 10) #update text self.textbox = Entry() self.textbox.pack(pady = 10) b_text = Button(master, text="update text", command=self.update_text) b_text.pack() b_color = Button(master, text="black/white", command=self.update_color) b_color.pack() b_save = Button(master, text="save image", command=self.save_image) b_save.pack()
class Gui(Frame): #============================================================================== # Metodos Basicos #============================================================================== def __init__(self, parent=None): Frame.__init__(self, parent) # Atributos GUI self.parent = parent self.file_opt = self.flopt = {} w, h = self.parent.winfo_screenwidth(), self.parent.winfo_screenheight( ) self.largura = w - 20 self.altura = h - 20 # Atributos funcionais self.img = None self.imgOld = None self.arqImg = StringVar() self.arqImg.set('') self.formatos = {} self.formatos['gif'] = 'GIF' self.formatos['jpg'] = 'JPEG' self.formatos['jpeg'] = 'JPEG' self.formatos['png'] = 'PNG' self.formatos['bmp'] = 'BMP' self.formatos['tif'] = 'TIFF' self.formatos['tiff'] = 'TIFF' self.formatos['ppm'] = 'PPM' self.formatos['pbm'] = 'PPM' self.formatos['pgm'] = 'PPM' self.tipos = [('Imagens', ('*.jpg', '*.png', '*.gif', '*.bmp', '*.ppm', '*.pgm', '*.pbm')), ('JPEG', '*.jpg'), ('PNG', '*.png'), ('GIF', '*.gif'), ('BMP', '*.bmp'), ('PPM', '*.ppm'), ('PGM', '*.pgm'), ('PBM', '*.pbm'), ('Todos arquivos', '*')] # Cria/atualiza GUI self.createWidgets() self.update_idletasks() #============================================================================== # Metodos relacionados ao comportamento da GUI #============================================================================== def createWidgets(self): self.canvas = Canvas(self.parent, width=1366, height=768) self.scroll = Scrollbar(self.parent, orient="vertical", command=self.canvas.yview) self.canvas.configure(yscrollcommand=self.scroll.set) self.scroll.pack(side="right", fill="y") self.canvas.pack(side="left", fill="both", expand=True) # Configura barra de menus self.menubar = Menu(self.parent) self.parent.config(menu=self.menubar) # Menu arquivo e suas opcoes self.menuArquivo = Menu(self.menubar) self.menuArquivo.add_command(label='Abrir', underline=0, command=self.abrir) self.menuArquivo.add_separator() self.menuArquivo.add_command(label='Salvar', underline=0, command=self.salvar) self.menuArquivo.add_command(label='Salvar Como...', underline=0, command=self.salvarComo) self.menuArquivo.add_separator() self.menuArquivo.add_command(label='Fechar imagem(ns)', underline=0, command=self.fecharArquivo) self.menuArquivo.add_command(label="Sair", underline=3, command=self.onExit) self.menubar.add_cascade(label="Arquivo", underline=0, menu=self.menuArquivo) # Menu editar e suas opcoes self.menuEditar = Menu(self.menubar) self.menuEditar.add_command(label='Desfazer', underline=0, command=self.desfazer) self.menubar.add_cascade(label="Editar", underline=0, menu=self.menuEditar) # Menu Imagem e suas opcoes self.menuImagem = Menu(self.menubar) self.submenuConverte = Menu(self.menuImagem) self.submenuConverte.add_command(label='Colorido RGB', underline=0, command=lambda: self.converte('RGB')) self.submenuConverte.add_command(label='Colorido RGBA', underline=0, command=lambda: self.converte('RGBA')) self.submenuConverte.add_command(label='Escala de cinza', underline=0, command=lambda: self.converte('L')) self.submenuConverte.add_command(label='Binario', underline=0, command=lambda: self.converte('1')) self.menuImagem.add_command(label='Informacoes gerais', underline=0, command=self.info) self.menuImagem.add_separator() self.menuImagem.add_cascade(label='Converter', underline=0, menu=self.submenuConverte) self.menubar.add_cascade(label="Imagem", underline=0, menu=self.menuImagem) # Menu de operacoes sobre cores e suas opcoes self.menuCores = Menu(self.menubar) self.submenuCinza = Menu(self.menuCores) self.submenuCinza.add_command(label='Decomposicao de Maximo', underline=18, command=self.emConstrucao) self.submenuCinza.add_command(label='Decomposicao de Minimo', underline=18, command=self.emConstrucao) self.submenuCinza.add_command(label='Average', underline=0, command=lambda: self.mudaCor('average')) self.submenuCinza.add_command(label='Lightness', underline=0, command=self.emConstrucao) self.submenuCinza.add_command(label='Luminosity', underline=0, command=self.emConstrucao) self.submenuCinza.add_command(label='Componente R', underline=11, command=lambda: self.mudaCor('r')) self.submenuCinza.add_command(label='Componente G', underline=11, command=self.emConstrucao) self.submenuCinza.add_command(label='Componente B', underline=11, command=self.emConstrucao) self.submenuCinza.add_command(label='Quantidade arbitraria de tons', underline=0, command=self.emConstrucao) self.submenuHalftone = Menu(self.menuCores) self.submenuHalftone.add_command( label='Bayer 2x2', underline=6, command=lambda: self.halftoning('bayer2')) self.submenuHalftone.add_command(label='Bayer 5x5', underline=6, command=self.emConstrucao) self.submenuHalftone.add_command(label='Atkinson', underline=0, command=self.emConstrucao) self.submenuHalftone.add_command(label='Sierra Lite', underline=0, command=self.emConstrucao) self.submenuHalftone.add_command(label='Jarvis, Judice, and Ninke', underline=0, command=self.emConstrucao) self.submenuHalftone.add_command( label='Floyd-Steinberg', underline=0, command=lambda: self.halftoning('floyd')) self.menuCores.add_cascade(label='Tons de cinza', underline=0, menu=self.submenuCinza) self.menuCores.add_command(label='Inverter', underline=0, command=lambda: self.mudaCor('inv')) self.menuCores.add_command(label='Sepia', underline=0, command=self.emConstrucao) self.menuCores.add_separator() self.menuCores.add_command(label='Pseudo Binaria', underline=0, command=self.binaria) self.menuCores.add_cascade(label='Halftoning', underline=0, menu=self.submenuHalftone) self.menuCores.add_separator() self.menuCores.add_command(label='Cisalhamento de Cor', underline=0, command=self.emConstrucao) self.menuCores.add_command(label='Balanco de cores', underline=0, command=self.balancoCor) self.menuCores.add_command(label='Quantizacao de cores', underline=0, command=self.emConstrucao) self.menubar.add_cascade(label="Cores", underline=0, menu=self.menuCores) # Menu de operacoes topologicas e suas opcoes self.menuTopologia = Menu(self.menubar) self.menuTopologia.add_command(label='Rotular Componentes', underline=0, command=self.emConstrucao) self.menuTopologia.add_command(label='Transformada da Distancia', underline=0, command=self.emConstrucao) self.menuTopologia.add_command(label='Esqueletizacao', underline=0, command=self.emConstrucao) self.menubar.add_cascade(label="Topologia", underline=0, menu=self.menuTopologia) # Menu do trabalho e suas opcoes self.trabalho = Menu(self.menubar) self.trabalho.add_command(label='Tarefa 01', underline=20, command=self.abrir) # Grupo principal, onde serao atualizados os widgets self.grupoPrincipal = Frame(self.canvas, width=self.largura, height=self.altura, bd=1, padx=10, pady=10) self.grupoPrincipal.pack() #self.grupoPrincipal.grid_propagate(False) # Faz com que o Frame nao seja redimensionado com a mudanca dos widgets self.canvas.create_window((4, 20), window=self.grupoPrincipal, anchor="nw", tags="self.grupoPrincipal") self.grupoPrincipal.bind("<Configure>", self.OnFrameConfigure) def OnFrameConfigure(self, event): '''Reset the scroll region to encompass the inner frame''' self.canvas.configure(scrollregion=self.canvas.bbox("all")) def onExit(self): self.parent.destroy() def limpaTela(self): for widget in self.grupoPrincipal.winfo_children(): widget.destroy() def emConstrucao(self): tkm.showinfo(title="Em construcao", message="Recurso em Construcao...") def load_file(self, titulo, varFile, tipos): if os.path.isfile(varFile.get()): path = os.path.dirname(varFile.get()) self.flopt['initialdir'] = path else: self.flopt['initialdir'] = os.path.curdir self.flopt['filetypes'] = tipos arquivo = tkf.askopenfilename(title=titulo, **self.flopt) if arquivo: varFile.set(arquivo) def widgetFile(self, master, titulo, texto, varFile, tuplaFiletype): esteFrame = LabelFrame(master, text=titulo, padx=5, pady=5) j = 0 varFile.set("Nenhum arquivo informado") labelRotulo = Label(esteFrame, text=texto) labelRotulo.grid(row=j, column=0, sticky=cte.E) botao = Button( esteFrame, text="Procurar", command=lambda: self.load_file(texto, varFile, tuplaFiletype), width=10) botao.grid(row=j, column=1, pady=5, sticky=cte.W) j += 1 labelArq = Label(esteFrame, textvariable=varFile, bg='white') labelArq.grid(row=j, column=0, columnspan=2) return esteFrame def refreshImg(self): try: self.grupoPrincipal.photo = ImageTk.PhotoImage(self.img.img) if hasattr(self.grupoPrincipal, 'canvas'): self.grupoPrincipal.canvas.destroy() self.grupoPrincipal.canvas = Canvas(self.grupoPrincipal) self.grupoPrincipal.canvas.create_image( 0, 0, image=self.grupoPrincipal.photo, anchor=cte.NW) self.grupoPrincipal.canvas.config(bg='white', width=self.img.altura, height=self.img.largura) #self.grupoPrincipal.canvas.place(x=self.parent.winfo_screenwidth()/2, y=self.parent.winfo_screenheight()/2, anchor=cte.CENTER) self.grupoPrincipal.canvas.place(x=0, y=0, anchor=cte.NW) self.grupoPrincipal.update_idletasks() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) #============================================================================== # Metodos relacionados ao meno Arquivo #============================================================================== def abrir(self): try: self.limpaTela() self.load_file('Arquivos de Imagem', self.arqImg, self.tipos) self.img = Imagem(self.arqImg.get()) self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def saveFile(self): try: nome, extensao = os.path.splitext(self.arqImg.get()) extensao = extensao.replace('.', '') self.img.salva(self.arqImg.get(), self.formatos[extensao.lower()]) tkm.showinfo( 'Sucesso', 'Arquivo %s salvo com sucesso' % os.path.basename(self.arqImg.get())) except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def salvar(self): if self.arqImg.get() == '': tkm.showwarning('Aviso', 'Nao ha arquivo aberto para ser salvo') else: try: self.saveFile() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def salvarComo(self): if self.arqImg.get() == '': tkm.showwarning('Aviso', 'Nao ha arquivo aberto para ser salvo') else: try: if os.path.isfile(self.arqImg.get()): path = os.path.dirname(self.arqImg.get()) self.flopt['initialdir'] = path else: self.flopt['initialdir'] = os.path.curdir self.flopt['filetypes'] = self.tipos nomeArq = tkf.asksaveasfilename(title='Salvar imagem como...', **self.flopt) if nomeArq: self.arqImg.set(nomeArq) self.saveFile() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def fecharArquivo(self): if not hasattr( self.grupoPrincipal, 'canvas') or self.grupoPrincipal.canvas.find_all() == (): tkm.showwarning('Aviso', 'Nao ha imagens abertas') else: try: self.img = self.imgOld = None self.grupoPrincipal.canvas.delete('all') self.grupoPrincipal.update_idletasks() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) #============================================================================== # Metodos relacionados ao menu Editar #============================================================================== def desfazer(self): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') elif self.imgOld is None: tkm.showwarning('Aviso', 'Impossivel Desfazer') else: try: temp = self.img self.img = self.imgOld self.imgOld = temp self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) #============================================================================== # Metodos relacionados ao menu Cores #============================================================================== def mudaCor(self, metodo): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: self.imgOld = self.img self.img = cor.mudaCor(self.imgOld, metodo) self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def binaria(self): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: self.imgOld = self.img self.img = cor.binaria(self.imgOld) self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def getFatoresBalanco(self): self.fatores = [float(self.escalaFatorR.get())] self.fatores.append(float(self.escalaFatorG.get())) self.fatores.append(float(self.escalaFatorB.get())) self.w.destroy() def formBalanco(self): self.fator = None self.fatores = None self.w = Toplevel(self) self.w.wm_title("Informar os fatores de ajuste") self.w.geometry("+%d+%d" % (self.winfo_rootx() + 50, self.winfo_rooty() + 50)) self.w.focus_set() i = 0 self.labelFatorR = Label(self.w, text='Ajuste em R', width=25) self.labelFatorR.grid(row=i, column=0) self.escalaFatorR = Scale(self.w, from_=0, to=2, resolution=0.05, length=350, orient=cte.HORIZONTAL) self.escalaFatorR.set(0.5) self.escalaFatorR.grid(row=i, column=1) i += 1 self.labelFatorG = Label(self.w, text='Ajuste em G', width=25) self.labelFatorG.grid(row=i, column=0) self.escalaFatorG = Scale(self.w, from_=0, to=2, resolution=0.05, length=350, orient=cte.HORIZONTAL) self.escalaFatorG.set(0.5) self.escalaFatorG.grid(row=i, column=1) i += 1 self.labelFatorB = Label(self.w, text='Ajuste em B', width=25) self.labelFatorB.grid(row=i, column=0) self.escalaFatorB = Scale(self.w, from_=0, to=2, resolution=0.05, length=350, orient=cte.HORIZONTAL) self.escalaFatorB.set(0.5) self.escalaFatorB.grid(row=i, column=1) i += 1 self.botaoFator = Button(self.w, text='Ok', command=self.getFatoresBalanco, width=10) self.botaoFator.grid(row=i, column=0, columnspan=2) self.w.grid() def balancoCor(self): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: self.formBalanco() self.wait_window(self.w) if self.fatores is not None: self.imgOld = self.img self.img = cor.balanco(self.imgOld, self.fatores[0], self.fatores[1], self.fatores[2]) self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def halftoning(self, metodo='bayer2'): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: self.imgOld = self.img if metodo == 'bayer2': self.img = cor.bayer(self.imgOld) elif metodo == 'floyd': self.img = cor.floyd(self.imgOld) else: raise Exception('Metodo de halftoning desconhecido') self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) #============================================================================== # Metodos relacionados ao menu Imagem #============================================================================== def converte(self, modo='RGB'): if self.arqImg.get() == '' or self.img is None: tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: self.imgOld = self.img.copia() self.img.converte(modo) self.refreshImg() except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args)) def info(self): if self.arqImg.get() == '': tkm.showwarning('Aviso', 'Nao ha arquivo aberto') else: try: texto = 'Imagem %s, modo: %s (%d x %d pixels)' % ( self.img.img.format, self.img.img.mode, self.img.img.size[0], self.img.img.size[1]) tkm.showinfo('Aviso', texto) except Exception as e: tkm.showerror('Erro', 'O seguinte erro ocorreu: %s' % str(e.args))
class TelloUI: """Wrapper class to enable the GUI.""" def __init__(self, tello, outputpath): """ Initial all the element of the GUI,support by Tkinter :param tello: class interacts with the Tello drone. Raises: RuntimeError: If the Tello rejects the attempt to enter command mode. """ self.tello = tello # videostream device self.outputPath = outputpath # the path that save pictures created by clicking the takeSnapshot button self.frame = None # frame read from h264decoder and used for pose recognition self.thread = None # thread of the Tkinter mainloop self.stopEvent = None # control variables self.distance = 0.1 # default distance for 'move' cmd self.degree = 30 # default degree for 'cw' or 'ccw' cmd # if the pose recognition mode is opened self.pose_mode = False # if the flag is TRUE,the auto-takeoff thread will stop waiting for the response from tello self.quit_waiting_flag = False # if the flag is TRUE,the pose recognition skeleton will be drawn on the GUI picture self.draw_skeleton_flag = False # pose recognition self.my_tello_pose = Tello_Pose() # record the coordinates of the nodes in the pose recognition skeleton self.points = [] #list of all the possible connections between skeleton nodes self.POSE_PAIRS = [[0, 1], [1, 2], [2, 3], [3, 4], [1, 5], [5, 6], [6, 7], [1, 14], [14, 8], [8, 9], [9, 10], [14, 11], [11, 12], [12, 13]] # initialize the root window and image panel self.root = tki.Tk() self.panel = None # self.panel_for_pose_handle_show = None # create buttons self.btn_snapshot = tki.Button(self.root, text="Snapshot!", command=self.takeSnapshot) self.btn_snapshot.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_pose = tki.Button(self.root, text="Pose Recognition Status: Off", command=self.setPoseMode) self.btn_pose.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_pause = tki.Button(self.root, text="Pause", relief="raised", command=self.pauseVideo) self.btn_pause.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_landing = tki.Button(self.root, text="Open Command Panel", relief="raised", command=self.openCmdWindow) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) # start a thread that constantly pools the video sensor for # the most recently read frame self.stopEvent = threading.Event() self.thread = threading.Thread(target=self.videoLoop, args=()) self.thread.start() # set a callback to handle when the window is closed self.root.wm_title("TELLO Controller") self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose) # the auto-takeoff thread will start if the 'takeoff' button on command window is clicked self.auto_takeoff_thread = threading.Thread(target=self._autoTakeoff) # the sending_command will send command to tello every 5 seconds self.sending_command_thread = threading.Thread( target=self._sendingCommand) self.get_GUI_Image_thread = threading.Thread(target=self._getGUIImage) def videoLoop(self): """ The mainloop thread of Tkinter Raises: RuntimeError: To get around a RunTime error that Tkinter throws due to threading. """ try: # start the thread that get GUI image and drwa skeleton time.sleep(0.5) self.get_GUI_Image_thread.start() while not self.stopEvent.is_set(): # read the frame for pose recognition self.frame = self.tello.read() if self.frame is None or self.frame.size == 0: continue # smoothing filter self.frame = cv2.bilateralFilter(self.frame, 5, 50, 100) cmd = '' self.points.append(None) # process pose-recognition if self.pose_mode: cmd, self.draw_skeleton_flag, self.points = self.my_tello_pose.detect( self.frame) # process command - map your motion to whatever Tello movement you want! if cmd == 'moveback': self.telloMoveBackward(0.50) elif cmd == 'moveforward': self.telloMoveForward(0.50) elif cmd == 'land': self.telloLanding() except RuntimeError as e: print("[INFO] caught a RuntimeError") def _getGUIImage(self): """ Main operation to read frames from h264decoder and draw skeleton on frames if the pose mode is opened """ # read the system of your computer system = platform.system() while not self.stopEvent.is_set(): # read the frame for GUI show frame = self.tello.read() if frame is None or frame.size == 0: continue if self.pose_mode: # Draw the detected skeleton points for i in range(15): if self.draw_skeleton_flag == True: cv2.circle(frame, self.points[i], 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED) cv2.putText(frame, "{}".format(i), self.points[i], cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA) # Draw Skeleton for pair in self.POSE_PAIRS: partA = pair[0] partB = pair[1] if self.points[partA] and self.points[partB]: cv2.line(frame, self.points[partA], self.points[partB], (0, 255, 255), 2) cv2.circle(frame, self.points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED) # transfer the format from frame to image image = Image.fromarray(frame) # we found compatibility problem between Tkinter,PIL and Macos,and it will # sometimes result the very long preriod of the "ImageTk.PhotoImage" function, # so for Macos,we start a new thread to execute the _updateGUIImage function. if system == "Windows" or system == "Linux": self._updateGUIImage(image) else: thread_tmp = threading.Thread(target=self._updateGUIImage, args=(image, )) thread_tmp.start() time.sleep(0.03) def _updateGUIImage(self, image): """ Main operation to initial the object of image,and update the GUI panel """ image = ImageTk.PhotoImage(image) # if the panel none ,we need to initial it if self.panel is None: self.panel = tki.Label(image=image) self.panel.image = image self.panel.pack(side="left", padx=10, pady=10) # otherwise, simply update the panel else: self.panel.configure(image=image) self.panel.image = image def _autoTakeoff(self): """ Firstly,it will waiting for the response that will be sent by Tello if Tello finish the takeoff command.If computer doesn't receive the response,it may be because tello doesn't takeoff normally,or because the UDP pack of response is lost.So in order to confirm the reason,computer will send 'height?'command to get several real-time height datas and get a average value.If the height is in normal range,tello will execute the moveup command.Otherwise,tello will land. Finally,the sending-command thread will start. """ response = None height_tmp = 0 # temp variable to content value of height height_val = 0 # average value of height cnt = 0 # effective number of height reading timeout = 6 # max waiting time of tello's response timer = threading.Timer(timeout, self._setQuitWaitingFlag) timer.start() # waiting for the response from tello while response != 'ok': if self.quit_waiting_flag is True: break response = self.tello.get_response() print("ack:%s" % response) timer.cancel() # receive the correct response if response == 'ok': self.tello.move_up(0.5) # calculate the height of tello else: for i in range(0, 50): height_tmp = self.tello.get_height() try: height_val = height_val + height_tmp cnt = cnt + 1 print(height_tmp, cnt) except: height_val = height_val height_val = height_val / cnt # if the height value is in normal range if height_val == 9 or height_val == 10 or height_val == 11: self.tello.move_up(0.5) else: self.tello.land() # start the sendingCmd thread self.sending_command_thread.start() def _sendingCommand(self): """ start a while loop that sends 'command' to tello every 5 second """ while True: self.tello.send_command('command') time.sleep(5) def _setQuitWaitingFlag(self): """ set the variable as TRUE,it will stop computer waiting for response from tello """ self.quit_waiting_flag = True def openCmdWindow(self): """ open the cmd window and initial all the button and text """ panel = Toplevel(self.root) panel.wm_title("Command Panel") # create text input entry text0 = tki.Label( panel, text= 'This Controller map keyboard inputs to Tello control commands\n' 'Adjust the trackbar to reset distance and degree parameter', font='Helvetica 10 bold') text0.pack(side='top') text1 = tki.Label( panel, text='W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n' 'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n' 'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n' 'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right', justify="left") text1.pack(side="top") self.btn_landing = tki.Button(panel, text="Land", relief="raised", command=self.telloLanding) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_takeoff = tki.Button(panel, text="Takeoff", relief="raised", command=self.telloTakeOff) self.btn_takeoff.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) # binding arrow keys to drone control self.tmp_f = tki.Frame(panel, width=100, height=2) self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w) self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s) self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a) self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d) self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up) self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down) self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left) self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right) self.tmp_f.pack(side="bottom") self.tmp_f.focus_set() self.btn_landing = tki.Button(panel, text="Flip", relief="raised", command=self.openFlipWindow) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.distance_bar = Scale(panel, from_=0.02, to=5, tickinterval=0.01, digits=3, label='Distance(m)', resolution=0.01) self.distance_bar.set(0.2) self.distance_bar.pack(side="left") self.btn_distance = tki.Button( panel, text="Reset Distance", relief="raised", command=self.updateDistancebar, ) self.btn_distance.pack(side="left", fill="both", expand="yes", padx=10, pady=5) self.degree_bar = Scale(panel, from_=1, to=360, tickinterval=10, label='Degree') self.degree_bar.set(30) self.degree_bar.pack(side="right") self.btn_distance = tki.Button(panel, text="Reset Degree", relief="raised", command=self.updateDegreebar) self.btn_distance.pack(side="right", fill="both", expand="yes", padx=10, pady=5) def openFlipWindow(self): """ open the flip window and initial all the button and text """ panel = Toplevel(self.root) panel.wm_title("Gesture Recognition") self.btn_flipl = tki.Button(panel, text="Flip Left", relief="raised", command=self.telloFlip_l) self.btn_flipl.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipr = tki.Button(panel, text="Flip Right", relief="raised", command=self.telloFlip_r) self.btn_flipr.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipf = tki.Button(panel, text="Flip Forward", relief="raised", command=self.telloFlip_f) self.btn_flipf.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipb = tki.Button(panel, text="Flip Backward", relief="raised", command=self.telloFlip_b) self.btn_flipb.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) def takeSnapshot(self): """ save the current frame of the video as a jpg file and put it into outputpath """ # grab the current timestamp and use it to construct the filename ts = datetime.datetime.now() filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) p = os.path.sep.join((self.outputPath, filename)) # save the file cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR)) print(("[INFO] saved {}".format(filename))) def setPoseMode(self): """ Toggle the open/close of pose recognition mode """ if self.pose_mode is False: self.pose_mode = True self.btn_pose.config(text='Pose Recognition Status: On') else: self.pose_mode = False self.btn_pose.config(text='Pose Recognition Status: Off') def pauseVideo(self): """ Toggle the freeze/unfreze of video """ if self.btn_pause.config('relief')[-1] == 'sunken': self.btn_pause.config(relief="raised") self.tello.video_freeze(False) else: self.btn_pause.config(relief="sunken") self.tello.video_freeze(True) def telloTakeOff(self): """ send the takeoff command to tello,and wait for the first response, if get the 'error'response,remind the "battery low" warning.Otherwise, start the auto-takeoff thread """ takeoff_response = None self.tello.takeoff() time.sleep(0.2) takeoff_response = self.tello.get_response() if takeoff_response != 'error': self.auto_takeoff_thread.start() else: print("battery low,please repalce with a new one") def telloLanding(self): return self.tello.land() def telloFlip_l(self): return self.tello.flip('l') def telloFlip_r(self): return self.tello.flip('r') def telloFlip_f(self): return self.tello.flip('f') def telloFlip_b(self): return self.tello.flip('b') def telloCW(self, degree): return self.tello.rotate_cw(degree) def telloCCW(self, degree): return self.tello.rotate_ccw(degree) def telloMoveForward(self, distance): return self.tello.move_forward(distance) def telloMoveBackward(self, distance): return self.tello.move_backward(distance) def telloMoveLeft(self, distance): return self.tello.move_left(distance) def telloMoveRight(self, distance): return self.tello.move_right(distance) def telloUp(self, dist): return self.tello.move_up(dist) def telloDown(self, dist): return self.tello.move_down(dist) def updateTrackBar(self): self.my_tello_hand.setThr(self.hand_thr_bar.get()) def updateDistancebar(self): self.distance = self.distance_bar.get() print('reset distance to %.1f' % self.distance) def updateDegreebar(self): self.degree = self.degree_bar.get() print('reset distance to %d' % self.degree) def on_keypress_w(self, event): print("up %d m" % self.distance) self.telloUp(self.distance) def on_keypress_s(self, event): print("down %d m" % self.distance) self.telloDown(self.distance) def on_keypress_a(self, event): print("ccw %d degree" % self.degree) self.tello.rotate_ccw(self.degree) def on_keypress_d(self, event): print("cw %d m" % self.degree) self.tello.rotate_cw(self.degree) def on_keypress_up(self, event): print("forward %d m" % self.distance) self.telloMoveForward(self.distance) def on_keypress_down(self, event): print("backward %d m" % self.distance) self.telloMoveBackward(self.distance) def on_keypress_left(self, event): print("left %d m" % self.distance) self.telloMoveLeft(self.distance) def on_keypress_right(self, event): print("right %d m" % self.distance) self.telloMoveRight(self.distance) def on_keypress_enter(self, event): if self.frame is not None: self.registerFace() self.tmp_f.focus_set() def onClose(self): """ set the stop event, cleanup the camera, and allow the rest of the quit process to continue """ print("[INFO] closing...") self.stopEvent.set() del self.tello self.root.quit()
class Visual(Frame): '''Class that takes a world as argument and present it graphically on a tkinter canvas.''' def __init__(self): ''' Sets up a simulation GUI in tkinter. ''' Frame.__init__(self) self.master.title("The Schelling Segregation Model in Python") self.master.wm_resizable(0, 0) self.grid() self.movement_possible = True # --------------------------------------- # # --------- FRAMES FOR GUI -------------- # # --------------------------------------- # # The pane for user values self._entryPane = Frame(self, borderwidth=5, relief='sunken') self._entryPane.grid(row=0, column=0, sticky='n') # The buttons pane self._buttonPane = Frame(self, borderwidth=5) self._buttonPane.grid(row=1, column=0, sticky='n') # A temp pane where graph is located, just for cosmetic reasons width, height = 425, 350 self._graph = Canvas(self, width=width, height=height, background="black") self._graph.configure(relief='sunken', border=2) self._graph.grid(row=3, column=0) # The pane where the canvas is located self._animationPane = Frame(self, borderwidth=5, relief='sunken') self._animationPane.grid(row=0, column=1, rowspan=4, pady=10, sticky="n") # --------------------------------------- # # --------- FILLING THE FRAMES ---------- # # --------------------------------------- # self._canvas() # Create graphics canvas self._entry() # Create entry widgets self._buttons() # Create button widgets def _plot_setup(self, time): '''Method for crudely annotating the graph window.''' time = time # Main plot width, height = 425, 350 y0 = -time/10 self._graph = Canvas(self, width=width, height=height, background="black", borderwidth=5) self._graph.grid(row=3, column=0) self.trans = Plotcoords(width, height, y0, -0.2, time, 1.3) x, y = self.trans.screen(time // 2, 1.2) x1, y1 = self.trans.screen(time // 2, 1.13) self._graph.create_text(x, y, text="% Happy", fill="green", font="bold 12") self._graph.create_text(x1, y1, text="% Unhappy", fill="red", font="bold 12") # Line x-axis x, y = self.trans.screen((-5 * (time / 100)), -0.05) x1, y = self.trans.screen(time, -0.05) self._graph.create_line(x, y, x1, y, fill="white", width=1.5) # Text x-axis x_text, y_text = self.trans.screen(time / 2, -0.15) self._graph.create_text(x_text, y_text, text="Time", fill="white", font="bold 12") # Line y-axis x, y = self.trans.screen((-0.5 * (time / 100)), -0.05) x, y1 = self.trans.screen((-5 * (time / 100)), 1) self._graph.create_line(x, y, x, y1, fill="white", width=1.5) def _entry(self): '''Method for creating widgets for collecting user input.''' # N (no of turtles) dim = 30*30 self.fill_label = Label(self._entryPane, anchor='w', justify='left', text='Fill', relief='raised', width=12, height=1, font='italic 20') self.fill_label.grid(row=0, column=1, ipady=14) self.fill = Scale(self._entryPane, from_=0, to=1, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=20) self.fill.grid(row=0, column=2) self.fill.set(0.8) self._N_label = Label(self._entryPane, anchor='w', justify='left', text="N:", relief='raised', width=12, height=1, font="italic 20") self._N_label.grid(row=1, column=1, ipady=14) self._N = Scale(self._entryPane, from_=0, to=100, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=20) self._N.set(30) self._N.grid(row=1, column=2) # Ticks (length of simulation) self._Ticks_label = Label(self._entryPane, anchor='w', justify='left', text="Time:", relief='raised', width=12, height=1, font="bold 20") self._Ticks_label.grid(row=2, column=1, ipady=14) self._Ticks = Scale(self._entryPane, from_=10, to=1000, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=990) self._Ticks.set(500) self._Ticks.grid(row=2, column=2) # % similar wanted self._Similar_label = Label(self._entryPane, anchor='w', justify='left', text="Similar wanted:", relief='raised', width=12, height=1, font="bold 20") self._Similar_label.grid(row=3, column=1, ipady=14) self._Similar = Scale(self._entryPane, from_=0.0, to=1.0, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=0.5) self._Similar.set(0.76) self._Similar.grid(row=3, column=2) # Delay between steps self._delay_label = Label(self._entryPane, anchor='w', justify='left', text="Delay (s):", relief='raised', width=12, height=1, font="bold 20") self._delay_label.grid(row=4, column=1, ipady=14) self._delay = Scale(self._entryPane, from_=0.0, to=1.0, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=0.5) self._delay.set(0.15) self._delay.grid(row=4, column=2) def _buttons(self): '''Method for creating button widgets for setting up, running and plotting results from simulation.''' width = 7 height = 1 # The 'Setup' button self._setupButton = Button(self._buttonPane, text="Setup", command=self._setup, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._setupButton.grid(row=0, column=0) # The 'Go' button self._goButton = Button(self._buttonPane, text="Go", command=self._go, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._goButton.grid(row=0, column=1) # The 'Quit' button self._quitButton = Button(self._buttonPane, text="Quit", command=self._quit, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._quitButton.grid(row=1, column=0, columnspan=2) def _canvas(self): '''Creates the canvas on which everything happens.''' # The tick counter information self._Tick_counter = Label(self._animationPane, anchor='w', justify='left', text="Time:", width=5, font="bold 20") self._Tick_counter.grid(row=0, column=0, sticky="e") self._Tick_counter1 = Label(self._animationPane, justify='center', text="", relief='raised', width=5, font="bold 20") self._Tick_counter1.grid(row=0, column=1, sticky='w') self.canvas_w, self.canvas_h = 750, 750 self.canvas = Canvas(self._animationPane, width=self.canvas_w, height=self.canvas_h, background="black") self.canvas.grid(row=1, column=0, columnspan=2) def _setup(self): '''Method for 'Setup' button.''' # Clearing the canvas and reset the go button self.canvas.delete('all') self._goButton['relief'] = 'raised' self.N = int(self._N.get()) self.Ticks = int(self._Ticks.get()) self.similar = float(self._Similar.get()) self.data = [] self.tick_counter = 0 self._Tick_counter1['text'] = str(self.tick_counter) self._plot_setup(self.Ticks) self.grid_size = self.N self.world = World(750, 750, self.grid_size) self.create_turtles() self.neighbouring_turtles() self.draw_turtles() def _go(self): '''Method for the 'Go' button, i.e. running the simulation.''' self._goButton['relief'] = 'sunken' if self.tick_counter <= self.Ticks: self._Tick_counter1['text'] = str(self.tick_counter) self.canvas.update() self._graph.update() self._graph.after(0) # Data collection turtles_unhappy = self.check_satisfaction() prop_happy, prop_unhappy = self.calc_prop_happy(self.tick_counter) self.data_collection(self.tick_counter, prop_happy, prop_unhappy) if self.tick_counter >= 1: # HAPPY values (%) x0 = self.tick_counter-1 x1 = self.tick_counter # Collecting values from stored data y0 = self.data[self.tick_counter-1][1] y1 = self.data[self.tick_counter][1] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="green", width=1.3, tag="happy") # Draw "happy lines # UNHAPPY values (%) x0 = self.tick_counter-1 x1 = self.tick_counter # Collecting values from stored data y0 = self.data[self.tick_counter-1][2] y1 = self.data[self.tick_counter][2] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="red", width=1.1, tag="unhappy") # Draw unhappy lines if prop_happy < 1: self.turtle_move(turtles_unhappy) time.sleep(self._delay.get()) self.update_neighbours() self.tick_counter += 1 self.canvas.after(0, self._go()) self._goButton['relief'] = 'raised' def _quit(self): '''Method for the 'Quit' button.''' self.master.destroy() # ------------------------------------------------------ # # ---------- FUNCTIONS CALLED AT EACH TICK ------------- # # ------------------------------------------------------ # def turtle_move(self, unhappy_turtles): '''Moves all the unhappy turtles (randomly).''' while unhappy_turtles: i = random.randint(0, len(unhappy_turtles)-1) turtle = unhappy_turtles.pop(i) turtle.move(self) def update_neighbours(self): '''Updates the turtles neigbour attributes. Called after all turtles have moved.''' for turtle in self.turtles: turtle.update_neighbours() def check_satisfaction(self): '''Checks to see if turtles are happy or not. Returns a list of unhappy turtles, i.e. turtles that should move. Called before the move method.''' for turtle in self.turtles: turtle.is_happy() unhappy_turtles = [] for element in self.turtles: if not element.happy: unhappy_turtles.append(element) return unhappy_turtles def calc_prop_happy(self, i): '''Calculates the proportion of happy turtles.''' happy = 0 unhappy = 0 for turtle in self.turtles: if turtle.happy: happy += 1 else: unhappy += 1 prop_happy = happy/len(self.turtles) prop_unhappy = unhappy/len(self.turtles) return prop_happy, prop_unhappy def data_collection(self, i, prop_happy, prop_unhappy): '''Method for collecting data at each tick.''' self.data.append((i, prop_happy, prop_unhappy)) # ------------------------------------------------------ # # ---------- INITIALISATION FUNCTIONS ------------------ # # ------------------------------------------------------ # def create_turtles(self): '''Method for creating a new list of turtles. Upon creation they are registered in the World object.''' if self.N*self.N <= self.grid_size*self.grid_size: counter = 0 self.turtles = [] while counter < self.N * self.N * self.fill.get(): s = "S"+str(counter) if counter <= int(self.N * self.N * self.fill.get() / 2): color = "green" else: color = "red" x = random.randint(0, self.grid_size-1) y = random.randint(0, self.grid_size-1) if not self.world.patch_list[x][y]: new_turtle = Schelling(world=self.world, x=x, y=y, s=s, color=color, similar_wanted=self.similar) self.world.register(new_turtle) counter += 1 self.turtles.append(new_turtle) else: print("Number of turtles exceeds world!") def draw_turtles(self): '''Method for drawing turtles on canvas. Calls each turtle's own method for drawing.''' for turtle in self.turtles: turtle.draw(self.canvas) def neighbouring_turtles(self): '''Method for updating turtles' neighbours. Calls on each turtle's own method for updating neighbours.''' for turtle in self.turtles: turtle.get_neighbouring_patches()
gain_label = Label(slider_frame, text='gain', font=('monospace')) gain_label.grid(row=1, column=0) reverb_label = Label(slider_frame, text='reverb', font=('monospace')) reverb_label.grid(row=1, column=1) chorus_label = Label(slider_frame, text='chorus', font=('monospace')) chorus_label.grid(row=1, column=2) #gain slider gain_slider = Scale(slider_frame, from_=10, to=0, width=50, length=250, command=lambda x: gain_command_change( gain_slider.get(), client_connection)) gain_slider.set(2) gain_slider.grid(row=0, column=0) #reverb slider rev_slider = Scale( slider_frame, from_=30, to=0, width=50, length=250, command=lambda x: rev_slider_change(rev_slider.get(), client_connection)) rev_slider.set(0) rev_slider.grid(row=0, column=1) chorus_slider = Scale(slider_frame, from_=30,
class OfflineVisualiser(Visualiser): """A VTK-powered offline visualiser which runs in its own thread. In addition to the functions provided by the standard visualiser, the following additional functions are provided: precache_height_quantities() - Precache all the vtkpoints structures for any dynamic height based quantities to render. """ def __init__(self, source, frameDelay=100, frameStep=1): """The source parameter is assumed to be a NetCDF sww file. The frameDelay parameter is the number of milliseconds waited between frames. """ Visualiser.__init__(self, source) self.frameNumber = 0 fin = NetCDFFile(self.source, 'r') self.maxFrameNumber = fin.variables['time'].shape[0] - 1 fin.close() #self.frameNumberTkVariable = StringVar() #self.frameNumberTkVariable.set('Frame - %05g'%self.framNumber) self.frameDelay = frameDelay self.xmin = None self.xmax = None self.ymin = None self.ymax = None self.zmin = None self.zmax = None self.frameStep = frameStep self.vtk_heightQuantityCache = [] for i in range(self.maxFrameNumber + 1): # maxFrameNumber is zero indexed. self.vtk_heightQuantityCache.append({}) self.paused = False self.movie = False def setup_grid(self): fin = NetCDFFile(self.source, 'r') self.vtk_cells = vtkCellArray() N_tri = fin.variables['volumes'].shape[0] for v in range(N_tri): self.vtk_cells.InsertNextCell(3) for i in range(3): self.vtk_cells.InsertCellPoint(fin.variables['volumes'][v][i]) fin.close() def update_height_quantity(self, quantityName, dynamic=True): polydata = self.vtk_polyData[quantityName] = vtkPolyData() if dynamic is True: #print ' - Frame',self.frameNumber,'of',self.maxFrameNumber if quantityName not in self.vtk_heightQuantityCache[ self.frameNumber]: self.vtk_heightQuantityCache[self.frameNumber][quantityName]\ = self.read_height_quantity(quantityName, True, self.frameNumber) polydata.SetPoints( self.vtk_heightQuantityCache[self.frameNumber][quantityName]) else: polydata.SetPoints(self.read_height_quantity(quantityName, False)) polydata.SetPolys(self.vtk_cells) def get_3d_bounds(self): return [ self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax ] def read_height_quantity(self, quantityName, dynamic=True, frameNumber=0): """Read in a height based quantity from the NetCDF source file and return a vtkPoints object. frameNumber is ignored if dynamic is false.""" fin = NetCDFFile(self.source, 'r') points = vtkPoints() if dynamic is True: N_vert = fin.variables[quantityName].shape[1] else: N_vert = len(fin.variables[quantityName]) x = num.ravel(num.array(fin.variables['x'], num.float)) y = num.ravel(num.array(fin.variables['y'], num.float)) if dynamic is True: q = num.array(fin.variables[quantityName][frameNumber], num.float) else: q = num.ravel(num.array(fin.variables[quantityName], num.float)) q *= self.height_zScales[quantityName] q += self.height_offset[quantityName] for v in range(N_vert): points.InsertNextPoint(x[v], y[v], q[v]) if self.xmin is None or self.xmin > x[v]: self.xmin = x[v] if self.xmax is None or self.xmax < x[v]: self.xmax = x[v] if self.ymin is None or self.ymin > y[v]: self.ymin = y[v] if self.ymax is None or self.ymax < y[v]: self.ymax = y[v] if self.zmin is None or self.zmin > q[v]: self.zmin = q[v] if self.zmax is None or self.zmax < q[v]: self.zmax = q[v] fin.close() return points def precache_height_quantities(self): """Precache any height-based quantities. Call before rendering beigns.""" for q in self.height_quantities: if self.height_dynamic[q] is True: print('Precaching %s' % q) for i in range(self.maxFrameNumber + 1): # maxFrameNumber is zero-indexed print(' - Frame %d of %d' % (i, self.maxFrameNumber)) self.vtk_heightQuantityCache[i][q]\ = self.read_height_quantity(q, True, i) def build_quantity_dict(self): quantities = {} fin = NetCDFFile(self.source, 'r') for q in [ n for n in list(fin.variables.keys()) if n != 'x' and n != 'y' and n != 'z' and n != 'time' and n != 'volumes' ]: if len(fin.variables[q].shape) == 1: # Not a time-varying quantity quantities[q] = num.ravel( num.array(fin.variables[q], num.float)) else: # Time-varying, get the current timestep data quantities[q] = num.array(fin.variables[q][self.frameNumber], num.float) fin.close() return quantities def setup_gui(self): Visualiser.setup_gui(self) self.tk_quit.grid(row=0, column=0, sticky=W + E) self.tk_movie_toggle = Button(self.tk_controlFrame, text="Movie off", command=self.movie_toggle) self.tk_movie_toggle.grid(row=0, column=6, sticky=W + E) self.tk_restart = Button(self.tk_controlFrame, text="<<<", command=self.restart, width=5) self.tk_restart.grid(row=1, column=0, sticky=W + E) self.tk_back10 = Button(self.tk_controlFrame, text="<<", command=self.back10, width=5) self.tk_back10.grid(row=1, column=1, sticky=W + E) self.tk_back = Button(self.tk_controlFrame, text="<", command=self.back, width=5) self.tk_back.grid(row=1, column=2, sticky=W + E) self.tk_pauseResume = Button(self.tk_controlFrame, text="Pause", command=self.pauseResume, width=15) self.tk_pauseResume.grid(row=1, column=3, sticky=W + E) self.tk_forward = Button(self.tk_controlFrame, text=">", command=self.forward, width=5) self.tk_forward.grid(row=1, column=4, sticky=W + E) self.tk_forward10 = Button(self.tk_controlFrame, text=">>", command=self.forward10, width=5) self.tk_forward10.grid(row=1, column=5, sticky=W + E) self.tk_forwardEnd = Button(self.tk_controlFrame, text=">>>", command=self.forwardEnd, width=5) self.tk_forwardEnd.grid(row=1, column=6, sticky=W + E) self.tk_frameNumber = Label(self.tk_controlFrame, text='Frame') self.tk_frameNumber.grid(row=2, column=0, sticky=W + E) self.tk_gotoFrame = Scale(self.tk_controlFrame, from_=0, to=self.maxFrameNumber, orient=HORIZONTAL) self.tk_gotoFrame.grid(row=2, column=1, columnspan=2, sticky=W + E) self.tk_stepLabel = Label(self.tk_controlFrame, text='Step') self.tk_stepLabel.grid(row=2, column=4, sticky=W + E) self.tk_frameStep = Scale(self.tk_controlFrame, from_=0, to=self.maxFrameNumber, orient=HORIZONTAL) self.tk_frameStep.grid(row=2, column=5, columnspan=2, sticky=W + E) # Make the buttons stretch to fill all available space for i in range(7): self.tk_controlFrame.grid_columnconfigure(i, weight=1) def run(self): self.alter_tkroot(Tk.after, (self.frameDelay, self.animateForward)) Visualiser.run(self) def restart(self): self.frameNumber = 0 self.redraw_quantities() self.update_labels() self.pause() if self.movie: self.save_image() def forwardEnd(self): self.frameNumber = self.maxFrameNumber self.redraw_quantities() self.update_labels() self.pause() def movie_toggle(self): if self.movie == True: self.movie = False self.tk_movie_toggle.config(text='Movie off') else: self.movie = True self.tk_movie_toggle.config(text='Movie on ') def save_image(self): from vtk import vtkJPEGWriter, vtkJPEGWriter, vtkPNGWriter from vtk import vtkPNMWriter, vtkWindowToImageFilter from os import path sourcebase, _ = path.splitext(self.source) fname = sourcebase + '%05g.png' % self.frameNumber #print fname extmap = { '.jpg': vtkJPEGWriter, '.jpeg': vtkJPEGWriter, '.png': vtkPNGWriter, '.pnm': vtkPNMWriter, } basename, ext = path.splitext(fname) try: Writer = extmap[ext.lower()] except KeyError: error_msg("Don't know how to handle %s files" % ext, parent=self) return renWin = self.vtk_renderer.GetRenderWindow() w2i = vtkWindowToImageFilter() writer = Writer() w2i.SetInput(renWin) w2i.Update() writer.SetInput(w2i.GetOutput()) writer.SetFileName(fname) renWin.Render() writer.Write() def back10(self): if self.frameNumber - 10 >= 0: self.frameNumber -= 10 else: self.frameNumber = 0 self.redraw_quantities() self.update_labels() self.pause() def back(self): if self.frameNumber > 0: self.frameNumber -= 1 self.redraw_quantities() self.update_labels() self.pause() def pauseResume(self): if self.paused is True: self.resume() else: self.pause() def pause(self): self.paused = True self.tk_pauseResume.config(text="Resume") def resume(self): self.paused = False self.tk_pauseResume.config(text="Pause") self.frameNumber = self.tk_gotoFrame.get() self.frameStep = self.tk_frameStep.get() self.tk_root.after(self.frameDelay, self.animateForward) def forward(self): if self.frameNumber < self.maxFrameNumber: self.frameNumber += 1 self.redraw_quantities() self.update_labels() self.pause() def forward_step(self): if self.frameNumber + self.frameStep <= self.maxFrameNumber: self.frameNumber += self.frameStep self.redraw_quantities() self.update_labels() else: self.frameNumber = self.maxFrameNumber self.redraw_quantities() self.update_labels() self.pause() if self.movie: self.save_image() def forward10(self): if self.frameNumber + 10 <= self.maxFrameNumber: self.frameNumber += 10 else: self.frameNumber = self.maxFrameNumber self.redraw_quantities() self.update_labels() self.pause() def animateForward(self): if self.paused is not True: self.forward_step() self.tk_root.after(self.frameDelay, self.animateForward) def update_labels(self): #self.tk_frameNumber.config(text='%05g of %05g'%(self.frameNumber,self.maxFrameNumber)) self.tk_gotoFrame.set(self.frameNumber) self.tk_frameStep.set(self.frameStep) def shutdown(self): #self.pause() self.tk_root.withdraw() self.tk_root.destroy()
from tkinter import Tk, Canvas, Scale, VERTICAL def setHeight(canvas, heightStr): height = 21 height = height + 21 y2 = height - 30 print(heightStr) #holds current scale pointer if y2 < 21: y2 = 21 root = Tk() root.title('Scale') canvas = Canvas(root, width=65, height=50, bd=0, highlightthickness=0) scale = Scale(root, orient=VERTICAL, length=284, from_=0, to=250, tickinterval=25, command=lambda h, c=canvas: setHeight(c, h)) scale.grid(row=0, column=0, sticky='NE') #starting point on scale scale.set(125) root.mainloop()
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind((host, port)) self.grid() self.columnconfigure(0, minsize=100) self.columnconfigure(1, minsize=200) self.columnconfigure(2, minsize=200) self.columnconfigure(3, minsize=150) self.columnconfigure(4, minsize=150) self.columnconfigure(5, minsize=150) self.columnconfigure(6, minsize=150) self.create_widgets() self.settables = self.assemble_settables() self.gui_logger = logging.getLogger('gui') self.request_update() def create_widgets(self): self.create_monitor() self.create_check_buttons() self.create_ranges() self.create_scales() self.create_radio_buttons() self.create_voices() self.quitButton = Button(self, text='Quit', command=self.quit) self.quitButton.grid(columnspan=7, sticky=E + W) def assemble_settables(self): settables = self.winfo_children() for w in settables: settables += w.winfo_children() return [w for w in settables if w.__class__.__name__ in ['Scale', 'Checkbutton']] def create_radio_buttons(self): # Scale related entries = ['DIATONIC', 'HARMONIC', 'MELODIC', 'PENTATONIC', 'PENTA_MINOR', 'GREEK_CHROMATIC', 'GREEK_ENHARMONIC'] self.scale = StringVar() self.scale.set('DIATONIC') self.rb_frame = Frame(self) for e in entries: rb = Radiobutton(self.rb_frame, value=e, text=e, anchor=W, command=self.send_scale, variable=self.scale) rb.grid(row=len(self.rb_frame.winfo_children()), sticky=W) self.rb_frame.grid(column=1, row=len(self.grid_slaves(column=1)), rowspan=3) def create_monitor(self): self.monitor_frame = LabelFrame(self, text="Monitor and Transport") this_cycle = Scale(self.monitor_frame, label='cycle_pos', orient=HORIZONTAL, from_=1, to=16, resolution=1) this_cycle.disable, this_cycle.enable = (None, None) this_cycle.ref = 'cycle_pos' this_cycle.grid(column=0, row=0, sticky=E + W) self.updateButton = Button(self.monitor_frame, text='Reload all Settings', command=self.request_update) self.updateButton.grid(row=1, sticky=E + W) self.ForceCaesuraButton = Button(self.monitor_frame, text='Force Caesura', command=self.force_caesura) self.ForceCaesuraButton.grid(row=2, sticky=E + W) self.saveBehaviourButton = Button(self.monitor_frame, text='Save current behaviour', command=self.request_saving_behaviour) self.saveBehaviourButton.grid(row=3, sticky=E + W) self.saveBehaviourNameEntry = Entry(self.monitor_frame) self.saveBehaviourNameEntry.grid(row=4, sticky=E + W) self.saveBehaviourNameEntry.bind('<KeyRelease>', self.request_saving_behaviour) self.selected_behaviour = StringVar() self.selected_behaviour.trace('w', self.new_behaviour_chosen) self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, None,) self.savedBehavioursMenu.grid(row=5, sticky=E + W) self.monitor_frame.grid(column=0, row=10, sticky=E + W) def request_update(self): self.send({'sys': 'update'}) def request_saving_behaviour(self, event=None): """callback for save behaviour button and textentry""" if event and event.widget == self.saveBehaviourNameEntry: if event.keysym == 'Return': name = self.saveBehaviourNameEntry.get() self.saveBehaviourNameEntry.delete(0, len(name)) else: return else: # button was pressed name = self.saveBehaviourNameEntry.get() if name: self.send({'sys': ['save_behaviour', name]}) def force_caesura(self): self.send({'force_caesura': True}) def create_voices(self): voice_ids = ['1', '2', '3', '4'] SCALES = OrderedDict([ ('pan_pos', {'min': -1, 'max': 1, 'start': 0.5, 'res': 0.001}), ('volume', {'min': 0, 'max': 1, 'start': 0.666, 'res': 0.001}), ('slide_duration_msecs', {'min': 0, 'max': 2000, 'start': 60, 'res': 1}), ('slide_duration_prop', {'min': 0, 'max': 2, 'start': 0.666, 'res': 0.001}), ('binaural_diff', {'min': 0, 'max': 66, 'start': 0.2, 'res': 0.01}) ]) for vid in voice_ids: counter = 0 for sca in SCALES: name = 'voice_' + vid + '_' + sca setattr(self, 'min_' + name, SCALES[sca]['min']) setattr(self, 'max_' + name, SCALES[sca]['max']) this_sca = Scale(self, label=sca, orient=HORIZONTAL, from_=getattr(self, 'min_' + name), to=getattr(self, 'max_' + name), resolution=SCALES[sca]['res']) this_sca.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) this_sca.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) this_sca.grid(column=int(2 + int(vid)), row=counter, sticky=E + W) this_sca.bind("<ButtonRelease>", self.scale_handler) this_sca.ref = name counter += 1 CHECK_BUTTONS = OrderedDict( [('mute', False), ('automate_binaural_diffs', True), ('automate_note_duration_prop', True), ('use_proportional_slide_duration', {'val': True, 'label': 'proportional slide'}), ('automate_pan', True), ('automate_wavetables', True)]) for vid in voice_ids: counter = 0 cb_frame = LabelFrame(self, text="Voice {0} - Automation".format(vid)) setattr(self, 'voice_' + vid + '_cb_frame', cb_frame) for cb in CHECK_BUTTONS: options = CHECK_BUTTONS[cb] name = 'voice_' + vid + '_' + cb if isinstance(options, dict) and 'label' in list(options.keys()): label = options['label'] else: label = cb[9:] if cb[:9] == 'automate_' else cb setattr(self, name, IntVar( value=type(options) == dict and options['val'] or options)) self.this_cb = Checkbutton(cb_frame, text=label, variable=getattr(self, name)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = None self.this_cb.grid(sticky=W, column=0, row=counter) self.this_cb.ref = name counter += 1 # add trigger wavetable-button trigWavetableButton = Button(cb_frame, text='Next Wavetable') trigWavetableButton.bind('<Button-1>', self.trigger_waveform_handler) trigWavetableButton.ref = 'voice_' + vid + "_trigger_wavetable" trigWavetableButton.grid(row=counter) cb_frame.grid(column=int(vid) + 2, row=5, sticky=E + W + N, rowspan=8) for vid in voice_ids: generation_types = ["random", "random_harmonic", "harmonic"] partial_pools = ["even", "odd", "all"] prefix = 'voice_' + vid + '_' types_name = prefix + 'wavetable_generation_type' pools_name = prefix + 'partial_pool' setattr(self, types_name, StringVar()) getattr(self, types_name).set("random") setattr(self, pools_name, StringVar()) getattr(self, pools_name).set("all") target_frame = getattr(self, 'voice_' + vid + '_cb_frame') gen_typ_frame = LabelFrame(target_frame, text="type") gen_typ_frame.grid(row=len(target_frame.winfo_children()), sticky=W) for gen_t in generation_types: gen_t_entry = Radiobutton(gen_typ_frame, value=gen_t, text=gen_t, anchor=W, variable=getattr(self, types_name)) gen_t_entry.bind('<ButtonRelease-1>', self.wt_handler) gen_t_entry.ref = types_name gen_t_entry.grid(row=len(gen_typ_frame.winfo_children()), sticky=W) pp_frame = LabelFrame(target_frame, text="harmonics") for pp in partial_pools: pp_entry = Radiobutton(pp_frame, value=pp, text=pp, anchor=W, variable=getattr(self, pools_name)) pp_entry.bind('<ButtonRelease-1>', self.wt_handler) pp_entry.ref = pools_name pp_entry.grid(row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials = Scale(pp_frame, label='number of harmonics', orient=HORIZONTAL, from_=1, to=24, resolution=1) this_num_partials.ref = prefix + 'num_partials' this_num_partials.grid(column=0, row=len(pp_frame.winfo_children()), sticky=E + W) this_num_partials.bind("<ButtonRelease>", self.scale_handler) pp_frame.grid(row=len(target_frame.winfo_children()), sticky=E + W) def wt_handler(self, event): print(event.widget.tk) ref = event.widget.ref self.send({ref: getattr(self, ref).get()}) def create_check_buttons(self): self.cb_frame = LabelFrame(self, text="Global Settings") for cb in CHECK_BUTTONS: label = cb target_parent = self.cb_frame if isinstance(CHECK_BUTTONS[cb], dict) and 'sub_frame' in list(CHECK_BUTTONS[cb].keys()): target_parent = getattr(self, CHECK_BUTTONS[cb]['sub_frame']) setattr(self, cb, IntVar(value=type(CHECK_BUTTONS[cb]) == dict and CHECK_BUTTONS[cb]['val'] or CHECK_BUTTONS[cb])) self.this_cb = Checkbutton(target_parent, text=label, variable=getattr(self, cb)) self.this_cb.bind('<Button-1>', self.check_boxes_handler) self.this_cb.disable = (type(CHECK_BUTTONS[cb]) == dict and 'disable' in list(CHECK_BUTTONS[cb].keys())) self.this_cb.grid(sticky=W, column=0, row=len(target_parent.winfo_children())) self.this_cb.ref = cb for but in GLOBAL_BUTTONS: label = but ele = GLOBAL_BUTTONS[but] this_but = Button(self.cb_frame, text=but) this_but.bind('<ButtonRelease-1>', getattr(self, ele['handler'])) this_but.ref = but this_but.grid(sticky=W, column=0, row=len(self.cb_frame.winfo_children())) self.cb_frame.grid(column=0, row=0, rowspan=10, sticky=N) def new_behaviour_chosen(self, a, b, c): self.send({'sys': ['change_behaviour', self.selected_behaviour.get()]}) def set_value(self, name, val): '''sets a widget to the specified value various different widget types need custom setting functionality''' direct = ['scale', 'wavetable_generation_type', 'partial_pool'] if [x for x in direct if match("(voice_\d_|)" + x, name)]: self.gui_logger.info("setting: '{0}' to '{1}' in GUI".format(name, val)) getattr(self, name).set(val) return if name == 'saved_behaviours' and len(val): self.savedBehavioursMenu.destroy() self.savedBehavioursMenu = OptionMenu(self.monitor_frame, self.selected_behaviour, *sorted(val)) self.savedBehavioursMenu.grid(row=5, sticky=E + W) return for w in self.settables: typ = w.__class__.__name__ if w.ref == name: # print "setting '{0}' of type: '{1}' to: {2}".format(name, typ, val) if typ == 'Scale': w.set(val) elif typ == "Checkbutton": w.select() if val else w.deselect() def check_boxes_handler(self, event): '''handles checkbox events. shows and hides gui elements according to their enable/disable fields''' # print event.__dict__ # print event.widget.__dict__ ref = event.widget.ref val = not getattr(self, ref).get() # because is read before the var is changed self.send({ref: val}) # print ref, val # handle gui elements # enable/disable functionality temporarily(?) commented on: # Wed Aug 17 09:39:54 CEST 2011 # if event.widget.disable: # for w in self.children.values(): # # # this try clause is for debugging, remove when stable # try: # w.ref # #print w.ref # except: # pass # if (w.__class__.__name__ == 'Scale' and # (w.disable or w.enable)): # if w.disable == ref: # if val: # w.grid() # else: # w.grid_remove() # elif w.enable == ref: # if val: # w.grid_remove() # else: # w.grid() # #print w.disable, w.enable def create_scales(self): counter = 0 for sca in SCALES: label = SCALES[sca]['label'] if 'label' in list(SCALES[sca].keys()) else sca setattr(self, 'min_' + sca, SCALES[sca]['min']) setattr(self, 'max_' + sca, SCALES[sca]['max']) self.this_scale = Scale(self, label=label, orient=HORIZONTAL, from_=getattr(self, 'min_' + sca), to=getattr(self, 'max_' + sca), resolution=SCALES[sca]['res']) self.this_scale.set(SCALES[sca]['start']) self.this_scale.enable = ('enable' in list(SCALES[sca].keys()) and SCALES[sca]['enable'] or None) self.this_scale.disable = ('disable' in list(SCALES[sca].keys()) and SCALES[sca]['disable'] or None) if 'pos' in list(SCALES[sca].keys()): pos = SCALES[sca]['pos'] col = pos['c'] row = pos['r'] else: row = counter col = 1 counter += 1 self.this_scale.grid(column=col, row=row, sticky=E + W) self.this_scale.ref = sca self.this_scale.bind("<ButtonRelease>", self.scale_handler) def scale_handler(self, event): self.send({event.widget.ref: event.widget.get()}) self.gui_logger.info("handling scale: {0}, with new value: {1}".format( event.widget.ref, event.widget.get())) def trigger_waveform_handler(self, event): self.send({event.widget.ref: True}) # print event.widget.ref, "- triggering wavetable" def send_scale(self): do = {'scale': self.scale.get()} self.send(do) def send(self, msg): self.gui_logger.info("sending: {0}".format(msg)) self.send_sock.sendto(json.dumps(msg), (remote_host, send_port)) def create_ranges(self): counter = 0 for ran in RANGES: setattr(self, 'min_' + ran, RANGES[ran]['min']) setattr(self, 'max_' + ran, RANGES[ran]['max']) self.this_min_scale = Scale(self, label='min ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_max_scale = Scale(self, label='max ' + ran, orient=HORIZONTAL, from_=getattr(self, 'min_' + ran), to=getattr(self, 'max_' + ran), resolution=RANGES[ran]['res']) self.this_min_scale.set(RANGES[ran]['min_start']) self.this_max_scale.set(RANGES[ran]['max_start']) self.this_min_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_min_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_max_scale.enable = ('enable' in list(RANGES[ran].keys()) and RANGES[ran]['enable'] or None) self.this_max_scale.disable = ('disable' in list(RANGES[ran].keys()) and RANGES[ran]['disable'] or None) self.this_min_scale.grid(column=2, row=counter, sticky=E + W) self.this_max_scale.grid(column=2, row=counter + 1, sticky=E + W) self.this_min_scale.ref = 'min_' + ran self.this_max_scale.ref = 'max_' + ran self.this_min_scale.bind("<ButtonRelease>", self.scale_handler) self.this_max_scale.bind("<ButtonRelease>", self.scale_handler) counter += 2 def socket_read_handler(self, file, mask): data_object = json.loads(file.recv(1024)) do = list(data_object.items())[0] self.set_value(do[0], do[1])
class SimulationPage(tk.Frame): def __init__(self, parent, controller, queue): self._dashboard = Dashboard() self.controller = controller self.simulator = Simulator(queue) self.window_closed = False tk.Frame.__init__(self, parent, bg='white') title_label = tk.Label(self, text="Project Origin Dashboard", font=LARGE_FONT, foreground='blue', bg='white') title_label.pack(pady=10, padx=10) self.s = ttk.Style() self.s.theme_use('vista') self.status_label = tk.Label(self, text="Simulator Ready.", bg='white') self.status_label.pack(pady=10, padx=10) self.sim_btn = ttk.Button( self, text="Start Simulation", command=lambda: self.on_simulation_btn_click()) self.sim_btn.pack() self.food_creature_scale = Scale( self, from_=0, to=1, orient=tk.HORIZONTAL, resolution=0.1, bg='white', command=lambda x: self.set_food_creature_ratio(x)) self.food_creature_scale.set(ConfigPhysics.FOOD_CREATURE_RATIO) self.food_creature_scale.pack() dash_fig = self._dashboard.get_figure() canvas = FigureCanvasTkAgg(dash_fig, self) canvas.draw() canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) controller.protocol("WM_DELETE_WINDOW", self.close_window_event) def close_window_event(self): self.stop_simulation() self.window_closed = True if self.simulator.status() == SimState.IDLE: self.close_window() def close_window(self): self.controller.destroy() sys.exit() def refresh_data(self, msg): if type(msg) == SimState: print(msg.value) if msg == SimState.IDLE: self.sim_btn['text'] = 'Start Simulation' self.sim_btn['state'] = tk.ACTIVE if self.window_closed: self.close_window() self.status_label['text'] = str(msg.value) else: self._dashboard.update_step_dash(msg.step_stats_df) self._dashboard.update_epoch_dash(msg.epoch_stats_df) def on_simulation_btn_click(self): if self.sim_btn['text'] == 'Start Simulation': self.start_simulation() self.sim_btn['text'] = 'Stop Simulation' else: self.stop_simulation() self.sim_btn['state'] = tk.DISABLED def stop_simulation(self): self.simulator.stop() self.status_label['text'] = "Simulation Interrupted. Stopping..." def start_simulation(self): self.simulator.run_in_thread() @staticmethod def set_food_creature_ratio(new): ConfigPhysics.FOOD_CREATURE_RATIO = float(new)
class HsvGui(tk.Frame): def __init__(self, master=None,): tk.Frame.__init__(self, master) self.root = master self.Webcam = G2.Webcamera() self.baseImage = self.Webcam.save_image(persist=False) self.baseImage = cv2.cvtColor(numpy.array(self.baseImage), cv2.COLOR_RGB2BGR) self.createWidgets() self.OnValueChange = event.Event() self.title = "Webcam" cv2.startWindowThread() cv2.namedWindow(self.title, cv2.WINDOW_NORMAL) cv2.imshow(self.title, self.baseImage) self.Funkify() def createWidgets(self): Label(self.root, text="Value:").grid(row=0, sticky=W) Label(self.root, text="H:").grid(row=1, sticky=W) Label(self.root, text="S:").grid(row=2, sticky=W) Label(self.root, text="V:").grid(row=3, sticky=W) Label(self.root, text="S:").grid(row=4, sticky=W) Label(self.root, text="V:").grid(row=5, sticky=W) Label(self.root, text="H:").grid(row=6, sticky=W) self.valueLabel = Label(self.root, text="000-000-000 to 000-000-000") self.valueLabel.grid(row=0, column=1, sticky=W) self.Hvalue = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.Hvalue.grid(row=1, column=1) self.Hvalue.set(0) self.Svalue = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.Svalue.grid( row=2, column=1) self.Svalue.set(90) self.Vvalue = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.Vvalue.grid( row=3, column=1) self.Vvalue.set(0) self.HvalueMax = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.HvalueMax.grid(row=4, column=1) self.HvalueMax.set(255) self.SvalueMax = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.SvalueMax.grid(row=5, column=1) self.SvalueMax.set(255) self.VvalueMax = Scale(self.root, from_=0, to=255, orient=HORIZONTAL, command=self.__sliderCallback) self.VvalueMax.grid(row=6, column=1) self.VvalueMax.set(120) self.Go = tk.Button(self.root, text="Go!", fg="Green", command=self.Funkify) self.Go.grid(row=7, column=0) self.QUIT = tk.Button(self.root, text="QUIT", fg="red", command=self.root.destroy) self.QUIT.grid(row=7, column=1) def Funkify(self): H = int(self.Hvalue.get()) S = int(self.Svalue.get()) V = int(self.Vvalue.get()) lower = [H, S, V] Hmax = int(self.HvalueMax.get()) Smax = int(self.SvalueMax.get()) Vmax = int(self.VvalueMax.get()) upper= [Hmax, Smax, Vmax] #self.valueLabel['text'] = '{0}-{1}-{2} to {3}-{4}-{5}'.format(H, S, V, Hmax, Smax, Vmax) output, a = self.Webcam.funkyfy(colorrange=(lower, upper)) cv2.imshow(self.title, numpy.hstack([output, a])) def __sliderCallback(self, args): print('Sliding!!')
# Etiqueta que contiene la cantidad de iteraciones realizadas para el cálculo. etiqueta = Label (ventana, text = ('Iteraciones necesarias: ' + str (iteracionesTotales))) etiqueta.config (bg = 'white', font = ('Verdana', 15)) etiqueta.place (relx=0.5, rely=0.37, anchor=CENTER) #Función que permite graficar a tiempo real. Esta ejecuta nuevamente la función Graficar para realizar nuevamente el cálculo. animation.FuncAnimation (fig, Graficar, interval = 1000) plt.close () # Se define el slider para el tamaño del lado. barraL = Scale(ventana, from_=7, to=20, tickinterval=13, length=400, bg = 'White', resolution=1, showvalue=True, orient='horizontal', label="Tamaño del Lado (Lx)", cursor = "hand1") barraL.bind ("<ButtonRelease-1>",Graficar) barraL.set(10) barraL.place (relx=0.175, rely=0.05, anchor=CENTER) # Se define el slider para el tiempo a evaluar. barraTiempos = Scale(ventana, from_=1, to=5, tickinterval=4,length=400, bg = 'White', resolution=0.5, showvalue=True, orient='horizontal', label="Tiempo (s)", cursor = "hand1") barraTiempos.bind ("<ButtonRelease-1>",Graficar) barraTiempos.set(3) barraTiempos.place (relx=0.5, rely=0.05, anchor=CENTER) # Se define el slider para el número de términos. barraPresición = Scale(ventana, from_=0.001, to=1, tickinterval=0.999,length=400, bg = 'White', resolution=0.001, showvalue=True, orient='horizontal', label="Presición", cursor = "hand1") barraPresición.bind ("<ButtonRelease-1>",Graficar)
def main(): """ основной метод - создание графического интерфейса TKinter :return: """ global params window = Tk() window.title("Отражение в параболическом зеркале") window.geometry('500x400') canv = Frame(window) setup = LabelFrame(window, text='Настройки', width=450, height=150) c = Canvas(canv, width=450, height=230, bg='black') c.pack(side=TOP, padx=10) setup1 = Frame(setup) butFrame = Frame(setup1) scal = Scale(setup1, orient=HORIZONTAL, length=200, from_=0.002, to=0.01, tickinterval=0.002, resolution=0.002) scal.set(0.002) scal.pack(side=TOP, pady=(0, 10), padx=(10, 10)) scal.bind("<ButtonRelease-1>", lambda event, draw_canv=c: redraw(event, draw_canv)) Button(butFrame, text='Очистить', width=12, command=lambda event=None, draw_canv=c, flag=True: redraw(event, draw_canv, setarrow=flag)) \ .pack(side=LEFT, padx=(10, 5), pady=(5, 10)) Button(butFrame, text='Закрыть', width=12, command=lambda flag=0: sys.exit(flag)).pack(side=LEFT, padx=(5, 10), pady=(5, 10)) butFrame.pack(side=TOP) setup1.pack(side=LEFT) columns = ('#1', '#2') params = Treeview(setup, show='headings', columns=columns) params.heading('#1', text='Параметр') params.heading('#2', text='Значение') params.column('#1', width=100, minwidth=50, stretch=NO, anchor=N) params.column('#2', width=100, minwidth=50, stretch=NO, anchor=N) params.pack(side=LEFT, padx=(5, 10), pady=(0, 10)) canv.pack(side=TOP, pady=(10, 10)) setup.pack(side=TOP, pady=(0, 10), padx=(25, 25)) draw_parabola(c) window.bind('<Button-1>', press) window.bind('<ButtonRelease-1>', lambda event, draw_canv=c: release(event, draw_canv)) window.mainloop()
#FullScreen Checkbox FullScreen_state = tk.IntVar() FullScreen_state.set(False) #set check state chk = Checkbutton(window, text='Fullscreen', var=FullScreen_state) #Volume Label Volume_lbl = tk.Label(text="Volume", fg="black", width=15, height=1, font=ConfigFont) Volume_lbl.pack(anchor=tk.W) #Background Music Volume Label BGMVolume_lbl = tk.Label(text="Background Music Volume", fg="black", width=25, height=1, font=ConfigFont) BGMVolume_lbl.pack(anchor=tk.W) #Background Music Volume Slider BGMVol_Slider = Scale(window, from_=0, to=100, orient=HORIZONTAL, font=ConfigFont) BGMVol_Slider.set(50) BGMVol_Slider.pack(anchor=tk.W) BGVolume = BGMVol_Slider.get()/10 #Sound Effects Volume Label SFXVolume_lbl = tk.Label(text="Sound Effects Volume", fg="black", width=25, height=1, font=ConfigFont) SFXVolume_lbl.pack(anchor=tk.W) #Sound Effects Volume Slider SFXVol_Slider = Scale(window, from_=0, to=100, orient=HORIZONTAL, font=ConfigFont) SFXVol_Slider.set(50) SFXVol_Slider.pack(anchor=tk.W) Sound_Output = tk.IntVar() Sound_Output.set(2)
class TLight(TObject): def __init__(self, send_func, light, master=None): super().__init__(send_func, light, master) self._power_property_label.configure(text="Power:") self.__brightness_frame = None self.__brightness_property_label = None self.__brightness_property_scale = None self.__brightness_property_status_label = None self.__brightness_property_button = None self.__set_brightness_property__() self.__color_frame = None self.__color_property_label = None self.__color_property_combobox = None self.__color_property_status_label = None self.__color_property_button = None self.__set_color_property__() def __set_brightness_property__(self): self.__brightness_frame = Frame(self) self.__brightness_frame.pack() self.__brightness_property_label = Label(self.__brightness_frame, text='Brightness:') self.__brightness_property_label.pack(side=LEFT, padx=3) self.__brightness_property_status_label = Label( self.__brightness_frame, text=f'(currently {self.obj.brightness})') self.__brightness_property_status_label.pack(side=LEFT, padx=3) self.__brightness_property_scale = Scale(self.__brightness_frame, from_=0, to=100, orient=HORIZONTAL) self.__brightness_property_scale.set(50) self.__brightness_property_scale.pack(side=LEFT, padx=3) self.__brightness_property_button = Button( self.__brightness_frame, text='Change', command=self.__brightness_button_event__) self.__brightness_property_button.pack(side=LEFT, padx=3) def __set_color_property__(self): if self.obj.colors: self.__color_frame = Frame(self) self.__color_frame.pack() self.__color_property_label = Label(self.__color_frame, text='Color:') self.__color_property_label.pack(side=LEFT, padx=3) self.__color_property_status_label = Label( self.__color_frame, text=f'(currently {self.obj.current_color})') self.__color_property_status_label.pack(side=LEFT, padx=3) self.__color_property_combobox = ttk.Combobox(self.__color_frame, state='readonly') self.__color_property_combobox['values'] = self.obj.colors self.__color_property_combobox.current(0) self.__color_property_combobox.pack(side=LEFT, padx=3, pady=5) self.__color_property_button = Button( self.__color_frame, text='Change', command=self.__color_button_event__) self.__color_property_button.pack(side=LEFT, padx=3) def __brightness_button_event__(self): self._send_func( self.obj.location, str('brightness=' + str(self.__brightness_property_scale.get()))) def __update_brightness_property__(self): self.__brightness_property_status_label.configure( text=f'(currently {self.obj.brightness})') def __color_button_event__(self): self._send_func(self.obj.location, str('color=' + self.__color_property_combobox.get())) def __update_color_property(self): self.__color_property_status_label.configure( text=f'(currently {self.obj.current_color})') def notify(self, information=None): if information is None: return elif information == 'power': self.__update_power_property__() elif information == 'brightness': self.__update_brightness_property__() elif information == 'color': self.__update_color_property()
class SliderDialog(CustomDialog): def __init__(self, root, title="Slider Dialog", init_val=0, min_val=-1, max_val=1, default_val=0, on_change=list(), resolution=1, on_confirm=list(), on_cancel=list()): self.init_val = init_val self.default_val = default_val self.on_change = on_change self.on_confirm = on_confirm self.on_cancel = on_cancel self.window = Toplevel() self.window.title(title) self.window.transient(root) self.window.grab_set() self.scale = Scale(self.window, orient='horizontal', from_=min_val, to=max_val, command=self.on_update, resolution=resolution) self.scale.set(init_val) self.scale.grid(row=0, column=0, sticky='nesw') self.cancel_button = Button(self.window, text='Cancel', command=self.cancel) self.cancel_button.grid(row=1, column=0) self.reset_button = Button(self.window, text='Reset', command=self.reset) self.reset_button.grid(row=1, column=1) self.confirm_button = Button(self.window, text='Confirm', command=self.confirm) self.confirm_button.grid(row=1, column=2) def on_update(self, value): for callback in self.on_change: callback(value) def cancel(self): for callback in self.on_cancel: callback() self.on_change[0]( self.init_val ) # hardcoded atm, so assumes the set method is first (good enough for now) self.window.destroy() def reset(self): self.scale.set(self.default_val) def confirm(self): for callback in self.on_confirm: callback() self.window.destroy()
class Slider(WidgetMixin, ScheduleMixin, DestroyMixin, EnableMixin, FocusMixin, DisplayMixin, ColorMixin, ReprMixin): def __init__(self, master, start=0, end=100, horizontal=True, command=None, grid=None, align=None): # If you specify a command to the slider, it must take one argument as it will be given # the slider's current value self._master = master self._grid = grid self._align = align self._visible = True # Description of this object (for friendly error messages) self.description = "[Slider] object from " + str(start) + " to " + str( end) # Set the direction orient = HORIZONTAL if horizontal else VERTICAL # Create a tk Scale object within this object self.tk = Scale(master.tk, from_=start, to=end, orient=orient, command=self._command_callback) self.update_command(command) # Pack this object try: utils.auto_pack(self, master, grid, align) except AttributeError: utils.error_format( self.description + "\n" + "Could not add to interface - check first argument is [App] or [Box]" ) # PROPERTIES # ---------------- # Get/set the value @property def value(self): return (self.tk.get()) @value.setter def value(self, value): self.tk.set(value) # METHODS # ---------------- # Calls the given function when the slider value is changed def _command_callback(self, value): if self._command: args_expected = utils.no_args_expected(self._command) if args_expected == 0: self._command() elif args_expected == 1: self._command(value) else: utils.error_format( "Slider command function must accept either 0 or 1 arguments.\nThe current command has {} arguments." .format(args_expected)) def update_command(self, command): if command is None: self._command = lambda: None else: self._command = command # DEPRECATED # ------------------------------------------- def add_command(self, command): self.update_command(command) utils.deprecated( "Slider add_command() is deprecated - renamed to update_command()")
class LayerViewer(ttk.LabelFrame): def __init__(self, project, width, height, *args, **kwargs): ttk.LabelFrame.__init__(self, *args, **kwargs) self.configure(text="LayerViewer") self.project = project self.width = width self.height = height self.delay = 1000 self.index = 0 self.state = PAUSED self.outer_frame = Frame(self) self.outer_frame.pack(side="top", fill="both", expand=True, padx=4, pady=4) self.outer_frame.config(width=250, height=200) self.inner_frame = Frame(self) force_aspect(self.inner_frame, self.outer_frame, float(width) / float(height)) self.canvas = Canvas(self.inner_frame, relief="sunken") self.canvas.config( width=50, #Parent frame width height=50, highlightthickness=0) self.canvas.config() self.canvas_frame = Frame(self.canvas, border=0, highlightthickness=0) self.canvas.create_window(0, 0, window=self.canvas_frame, anchor='nw') self.canvas_frame.config(width=50, height=50) self.canvas.pack(fill="both", expand=True) self.playback_scale = Scale(self, orient="horizontal", from_=0, to=30, command=self.set_delay) self.playback_scale.set(int(self.delay / 1000)) self.playback_scale.pack(fill="both", expand=False, padx=4, pady=4) self.display_loop() # def pause(self, event = None): # self.state = PAUSED # def play(self, event = None): # self.state = RUNNING def set_delay(self, fps): if float(fps) < float(1.0): self.delay = None return self.delay = int(1000.0 / float(fps)) """ Approximates an fps, milage will vary, it would be better for me to run this as a thread spawned by a timer thread that acts as the loop, so the fps would more closely match the one selected with the menu bar """ def display_loop(self): if not self.project.frames or not self.delay: self.after(100, self.display_loop) return if self.index > len(self.project.frames) - 1: self.index = 0 layer = self.project.frames[self.index] self.image = layer.export_composite_image().resize( (self.inner_frame.winfo_width(), self.inner_frame.winfo_height()), Image.BOX) self.displayed = ImageTk.PhotoImage(self.image) self.canvas.delete("all") self.canvas.create_image(0, 0, image=self.displayed, anchor="nw") self.configure(text=f"Preview: {layer.id}") self.index += 1 if self.delay < 10: delay = 10 delay = self.delay or 1000 self.after(delay, self.display_loop)
class Fenetre(Tk): def __init__(self): Tk.__init__(self) self.tilt_val_init = 110 self.pan_val_init = 75 self.pan_min = 0 self.pan_max = 105 self.tilt_min = 35 self.tilt_max = 135 self.pas = 5 # Full Screen largeur, hauteur = self.winfo_screenwidth(), self.winfo_screenheight() self.overrideredirect(0) self.geometry("%dx%d" % (largeur, hauteur)) # TILT self.tilt_bar = Scale(self, from_=self.tilt_min, to=self.tilt_max, length=250, label='Tilt', sliderlength=20, orient=HORIZONTAL, command=self.update_tilt) self.tilt_bar.set((self.tilt_max + self.tilt_min) // 2) self.tilt_bar.grid(row=1, column=2) self.tilt_angle = StringVar() self.tilt_val = self.tilt_bar.get() # PAN self.pan_bar = Scale(self, from_=self.pan_min, to=self.pan_max, length=250, label='Pan', sliderlength=20, orient=HORIZONTAL, command=self.update_pan) self.pan_bar.set((self.pan_max + self.pan_min) // 2) self.pan_bar.grid(row=2, column=2) self.pan_angle = StringVar() self.pan_val = self.pan_bar.get() # PS3 Controller self.bind("<a>", self.pan_plus) self.bind("<d>", self.pan_moins) self.bind("<s>", self.tilt_plus) self.bind("<w>", self.tilt_moins) self.bind("<p>", self.lean_left) self.bind("<m>", self.lean_right) self.bind("<q>", self.initialiser_positon) self.bind("<j>", self.forward) self.bind("<u>", self.reverse) self.bind("<h>", self.left) self.bind("<k>", self.right) self.bind("<i>", self.break_motor) self.bind("<Button-2>", self.alarm) self.bind("<Button-3>", self.beep) # Motor self.gear = 0 self.speed_init = 5 self.speed = self.speed_init self.leds = [led_1, led_2, led_3] self.bind("<e>", self.shift_down) self.bind("<r>", self.shift_up) self.pwm = gpio.PWM(enable_pin, 50) # 50 is the frequency # Infos self.pas_label = Label(self, text=str(self.pas)) self.pas_label.grid(row=3) self.buzzer_state = 0 #--------Buzzer-------- def beep(self, event, time=100): self.buzzer_on() self.after(time, self.buzzer_off) def buzzer_on(self): gpio.output(buzzer, gpio.HIGH) self.buzzer_state = 1 def buzzer_off(self): gpio.output(buzzer, gpio.LOW) self.buzzer_state = 0 def alarm(self, event): if self.buzzer_state == 0: gpio.output(buzzer, gpio.HIGH) self.buzzer_state = 1 else: gpio.output(buzzer, gpio.LOW) self.buzzer_state = 0 #-------Camera------- #-------Motor------- def shift_up(self, event): if self.gear != 3: self.gear += 1 gpio.output(self.leds[self.gear - 1], gpio.HIGH) else: self.beep(event, time=70) if self.gear == 0: self.speed = self.speed_init elif self.gear == 1: self.speed = 33 elif self.gear == 2: self.speed = 66 elif self.gear == 3: self.speed = 100 def shift_down(self, event): if self.gear != 0: gpio.output(self.leds[self.gear - 1], gpio.LOW) self.gear -= 1 if self.gear == 0: self.speed = self.speed_init elif self.gear == 1: self.speed = 33 elif self.gear == 2: self.speed = 66 elif self.gear == 3: self.speed = 100 def forward(self, event): self.go("forward") def reverse(self, event): self.go("reverse") def right(self, event): self.go("right") def left(self, event): self.go("left") def lean_left(self, event): self.go('lean left') def lean_right(self, event): self.go('lean right') def break_motor(self, event): self.go("stop") def go(self, direction): gpio_reset_motor() if direction == "forward": print("forward") gpio.output(right_forward, gpio.HIGH) gpio.output(left_forward, gpio.HIGH) elif direction == "reverse": print("reverse") gpio.output(right_reverse, gpio.HIGH) gpio.output(left_reverse, gpio.HIGH) elif direction == "right": print("right") gpio.output(left_reverse, gpio.HIGH) gpio.output(right_forward, gpio.HIGH) elif direction == "left": print("left") gpio.output(right_reverse, gpio.HIGH) gpio.output(left_forward, gpio.HIGH) elif direction == 'lean left': gpio.output(left_reverse, gpio.HIGH) elif direction == 'lean right': gpio.output(right_reverse, gpio.HIGH) elif direction == 'stop': self.pwm.stop() self.pwm = gpio.PWM(enable_pin, 50) # 50 is the frequency else: pass self.pwm.start(self.speed) # a "speed" of 50, sends power exactly every second cycle #time.sleep(1) #direction = input('Enter next direction') #-------Servos------- def tilt_plus(self, event): if verif_angle(self.tilt_val + self.pas, self.tilt_min, self.tilt_max): self.tilt_val += self.pas self.tilt_bar.set(self.tilt_val) def tilt_moins(self, event): if verif_angle(self.tilt_val - self.pas, self.tilt_min, self.tilt_max): self.tilt_val -= self.pas self.tilt_bar.set(self.tilt_val) def pan_plus(self, event): if verif_angle(self.pan_val + self.pas, self.pan_min, self.pan_max): self.pan_val += self.pas self.pan_bar.set(self.pan_val) def pan_moins(self, event): if verif_angle(self.pan_val - self.pas, self.pan_min, self.pan_max): self.pan_val -= self.pas * 2 self.pan_bar.set(self.pan_val) def pas_plus(self, event): if self.pas + 1 < 21: self.pas += 1 self.update_window() def pas_moins(self, event): if self.pas - 1 > 0: self.pas -= 1 self.update_window() def update_tilt(self, x): if x == 0: pass set_servo(int(x), 0) self.tilt_val = int(x) def update_pan(self, x): if x == 0: pass set_servo(int(x), 1) self.pan_val = int(x) def update_window(self): self.pas_label['text'] = str(self.pas) def initialiser_positon(self, event): self.tilt_bar.set(self.tilt_val_init) self.pan_bar.set(self.pan_val_init)
class vedoGUI(Frame): def __init__(self, parent): Frame.__init__(self, parent, bg="white") self.parent = parent self.filenames = [] self.noshare = BooleanVar() self.flat = BooleanVar() self.xspacing = StringVar() self.yspacing = StringVar() self.zspacing = StringVar() self.background_grad = BooleanVar() self.initUI() def initUI(self): self.parent.title("vedo") self.style = Style() self.style.theme_use("clam") self.pack(fill=BOTH, expand=True) ############import Button(self, text="Import Files", command=self._importCMD, width=15).place(x=115, y=17) ############meshes Frame(root, height=1, width=398, bg="grey").place(x=1, y=60) Label(self, text="Meshes", fg="white", bg="green", font=("Courier 11 bold")).place(x=20, y=65) # color Label(self, text="Color:", bg="white").place(x=30, y=98) colvalues = ('by scalar', 'gold', 'red', 'green', 'blue', 'coral', 'plum', 'tomato') self.colorCB = Combobox(self, state="readonly", values=colvalues, width=10) self.colorCB.current(0) self.colorCB.place(x=100, y=98) # mode modvalues = ('surface', 'surf. & edges', 'wireframe', 'point cloud') self.surfmodeCB = Combobox(self, state="readonly", values=modvalues, width=14) self.surfmodeCB.current(0) self.surfmodeCB.place(x=205, y=98) # alpha Label(self, text="Alpha:", bg="white").place(x=30, y=145) self.alphaCB = Scale( self, from_=0, to=1, resolution=0.02, bg="white", length=220, orient="horizontal", ) self.alphaCB.set(1.0) self.alphaCB.place(x=100, y=125) # lighting Label(self, text="Lighting:", bg="white").place(x=30, y=180) lightvalues = ('default', 'metallic', 'plastic', 'shiny', 'glossy') self.lightCB = Combobox(self, state="readonly", values=lightvalues, width=10) self.lightCB.current(0) self.lightCB.place(x=100, y=180) # shading phong or flat self.flatCB = Checkbutton(self, text="flat shading", var=self.flat, bg="white") #self.flatCB.select() self.flatCB.place(x=210, y=180) # rendering arrangement Label(self, text="Arrange as:", bg="white").place(x=30, y=220) schemevalues = ('superpose (default)', 'mesh browser', 'n sync-ed renderers') self.schememodeCB = Combobox(self, state="readonly", values=schemevalues, width=20) self.schememodeCB.current(0) self.schememodeCB.place(x=160, y=220) # share cam self.noshareCB = Checkbutton(self, text="independent cameras", variable=self.noshare, bg="white") self.noshareCB.place(x=160, y=245) ############volumes Frame(root, height=1, width=398, bg="grey").place(x=1, y=275) Label(self, text="Volumes", fg="white", bg="blue", font=("Courier 11 bold")).place(x=20, y=280) # mode Label(self, text="Rendering mode:", bg="white").place(x=30, y=310) modevalues = ( "isosurface (default)", "composite", "maximum proj", "lego", "slicer", "slicer2d", ) self.modeCB = Combobox(self, state="readonly", values=modevalues, width=20) self.modeCB.current(0) self.modeCB.place(x=160, y=310) Label(self, text="Spacing factors:", bg="white").place(x=30, y=335) self.xspacingCB = Entry(self, textvariable=self.xspacing, width=3) self.xspacing.set('1.0') self.xspacingCB.place(x=160, y=335) self.yspacingCB = Entry(self, textvariable=self.yspacing, width=3) self.yspacing.set('1.0') self.yspacingCB.place(x=210, y=335) self.zspacingCB = Entry(self, textvariable=self.zspacing, width=3) self.zspacing.set('1.0') self.zspacingCB.place(x=260, y=335) ############## options Frame(root, height=1, width=398, bg="grey").place(x=1, y=370) Label(self, text="Options", fg='white', bg="brown", font=("Courier 11 bold")).place(x=20, y=375) # backgr color Label(self, text="Background color:", bg="white").place(x=30, y=405) bgcolvalues = ("white", "lightyellow", "azure", "blackboard", "black") self.bgcolorCB = Combobox(self, state="readonly", values=bgcolvalues, width=9) self.bgcolorCB.current(3) self.bgcolorCB.place(x=160, y=405) # backgr color gradient self.backgroundGradCB = Checkbutton(self, text="gradient", variable=self.background_grad, bg="white") self.backgroundGradCB.place(x=255, y=405) ################ render button Frame(root, height=1, width=398, bg="grey").place(x=1, y=437) Button(self, text="Render", command=self._run, width=15).place(x=115, y=454) def _importCMD(self): ftypes = [ ("All files", "*"), ("VTK files", "*.vtk"), ("VTK files", "*.vtp"), ("VTK files", "*.vts"), ("VTK files", "*.vtu"), ("Surface Mesh", "*.ply"), ("Surface Mesh", "*.obj"), ("Surface Mesh", "*.stl"), ("Surface Mesh", "*.off"), ("Surface Mesh", "*.facet"), ("Volume files", "*.tif"), ("Volume files", "*.slc"), ("Volume files", "*.vti"), ("Volume files", "*.mhd"), ("Volume files", "*.nrrd"), ("Volume files", "*.nii"), ("Volume files", "*.dem"), ("Picture files", "*.png"), ("Picture files", "*.jpg"), ("Picture files", "*.bmp"), ("Picture files", "*.gif"), ("Picture files", "*.jpeg"), ("Geojson files", "*.geojson"), ("DOLFIN files", "*.xml.gz"), ("DOLFIN files", "*.xml"), ("DOLFIN files", "*.xdmf"), ("Neutral mesh", "*.neu*"), ("GMESH", "*.gmsh"), ("Point Cloud", "*.pcd"), ("3DS", "*.3ds"), ("Numpy scene file", "*.npy"), ("Numpy scene file", "*.npz"), ] self.filenames = tkFileDialog.askopenfilenames(parent=root, filetypes=ftypes) args.files = list(self.filenames) def _run(self): tips() args.files = list(self.filenames) if self.colorCB.get() == "by scalar": args.color = None else: if self.colorCB.get() == 'red': args.color = 'crimson' elif self.colorCB.get() == 'green': args.color = 'limegreen' elif self.colorCB.get() == 'blue': args.color = 'darkcyan' else: args.color = self.colorCB.get() args.alpha = self.alphaCB.get() args.wireframe = False args.showedges = False args.point_size = 0 if self.surfmodeCB.get() == 'point cloud': args.point_size = 2 elif self.surfmodeCB.get() == 'wireframe': args.wireframe = True elif self.surfmodeCB.get() == 'surf. & edges': args.showedges = True else: pass # normal surface mode args.lighting = self.lightCB.get() args.flat = self.flat.get() args.no_camera_share = self.noshare.get() args.background = self.bgcolorCB.get() args.background_grad = None if self.background_grad.get(): b = getColor(args.background) args.background_grad = (b[0] / 1.8, b[1] / 1.8, b[2] / 1.8) args.multirenderer_mode = False args.scrolling_mode = False if self.schememodeCB.get() == "n sync-ed renderers": args.multirenderer_mode = True elif self.schememodeCB.get() == "mesh browser": args.scrolling_mode = True args.ray_cast_mode = False args.lego = False args.slicer = False args.slicer2d = False args.lego = False args.mode = 0 if self.modeCB.get() == "composite": args.ray_cast_mode = True args.mode = 0 elif self.modeCB.get() == "maximum proj": args.ray_cast_mode = True args.mode = 1 elif self.modeCB.get() == "slicer": args.slicer = True elif self.modeCB.get() == "slicer2d": args.slicer2d = True elif self.modeCB.get() == "lego": args.lego = True args.x_spacing = 1 args.y_spacing = 1 args.z_spacing = 1 if self.xspacing.get() != '1.0': args.x_spacing = float(self.xspacing.get()) if self.yspacing.get() != '1.0': args.y_spacing = float(self.yspacing.get()) if self.zspacing.get() != '1.0': args.z_spacing = float(self.zspacing.get()) draw_scene(args) if os.name == "nt": exit() if settings.plotter_instance: settings.plotter_instance.close()
class ipGUI: def __init__(self, master): self.master = master self.master.minsize(width=800, height=600) menu = Menu(self.master) master.config(menu=menu) # ***** Main Menu ***** # *** file menu *** fileMenu = Menu(menu) menu.add_cascade(label='File', menu=fileMenu) fileMenu.add_command(label="Open", command=self.openImage) fileMenu.add_command(label="Load Blur Kernel", command=self.loadKernel) fileMenu.add_command(label="Save", command=self.saveImage) fileMenu.add_command(label="Exit", command=master.destroy) # *** edit menu *** editMenu = Menu(menu) menu.add_cascade(label='Space', menu=editMenu) editMenu.add_command(label="Histogram Equalization", command=self.histWrap) editMenu.add_command(label="Gamma Correction", command=self.gammaCorWrap) editMenu.add_command(label="Log Transform", command=self.logTranWrap) editMenu.add_command(label="Sharpen", command=self.sharpWrap) editMenu.add_command(label="Cartoonify", command=self.cartoonifyWrap) # *** blur menu *** blurMenu = Menu(editMenu) editMenu.add_cascade(label='Blur', menu=blurMenu) blurMenu.add_command(label="Box", command=self.boxBlurWrap) blurMenu.add_command(label="Gaussian", command=self.gaussianBlurWrap) blurMenu.add_command(label="Median", command=self.medianBlurWrap) # *** frequency filtering *** freqMenu = Menu(menu) menu.add_cascade(label='Frequency', menu=freqMenu) freqMenu.add_command(label="DFT", command=self.dftWrap) freqMenu.add_command(label="Load Mask", command=self.freqMaskWrap) # *** Mask Menu *** maskMenu = Menu(freqMenu) freqMenu.add_cascade(label='Create Mask', menu=maskMenu) maskMenu.add_command(label='Low Pass', command=self.lpmWrap) maskMenu.add_command(label='High Pass', command=self.hpmWrap) maskMenu.add_command(label='Band Pass', command=self.bppmWrap) maskMenu.add_command(label='Band Stop', command=self.bspmWrap) # *** frequency filtering *** restorationMenu = Menu(menu) menu.add_cascade(label='Restoration', menu=restorationMenu) restorationMenu.add_command(label="Full Inverse", command=self.fullInverseWrap) restorationMenu.add_command(label="Radially Limited Inverse", command=self.truncatedInverseWrap) restorationMenu.add_command(label="Approximate Weiner", command=self.approximateWeinerWrap) restorationMenu.add_command(label="Constrained LS", command=self.contrainedLSWrap) # ***** Toolbar ***** toolbar = Frame(master, bg="grey") undoButton = Button(toolbar, text="Undo", command=self.undoFunc) undoButton.pack(side=LEFT) origButton = Button(toolbar, text="Original", command=self.origFunc) origButton.pack(side=LEFT) toolbar.pack(side=TOP, fill=X) # ***** Image Display Area ***** self.frame = Frame(self.master) self.frame.pack() self.panel = Label(self.frame) self.panel.pack(padx=10, pady=10) self.img = None self.origImg = None self.prevImg = None # ***** Gamma Controls ***** self.gammaFrame = Frame(self.master) self.gammaSlider = Scale(self.gammaFrame, from_=0.1, to=2, orient=HORIZONTAL, resolution=0.1) self.gammaSlider.pack(side=TOP) self.gammaExitButton = Button(self.gammaFrame, text="Exit", command=self.gammaFrame.pack_forget) self.gammaExitButton.pack(side=TOP) # ***** Box Blur Controls ***** self.boxFrame = Frame(self.master) self.boxSlider = Scale(self.boxFrame, from_=1, to=5, orient=HORIZONTAL) self.boxSlider.pack(side=TOP) self.boxExitButton = Button(self.boxFrame, text="Exit", command=self.boxFrame.pack_forget) self.boxExitButton.pack(side=TOP) # ***** Truncated Inverse Controls ***** self.truncatedInverseFrame = Frame(self.master) self.truncatedInverseSlider = Scale(self.truncatedInverseFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.truncatedInverseSlider.pack(side=TOP) self.truncatedInverseExitButton = Button( self.truncatedInverseFrame, text="Exit", command=self.truncatedInverseFrame.pack_forget) self.truncatedInverseExitButton.pack(side=TOP) # ***** Weiner Controls ***** self.weinerFrame = Frame(self.master) self.weinerSlider = Scale(self.weinerFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.weinerSlider.pack(side=TOP) self.weinerExitButton = Button(self.weinerFrame, text="Exit", command=self.weinerFrame.pack_forget) self.weinerExitButton.pack(side=TOP) # ***** CLS Controls ***** self.clsFrame = Frame(self.master) self.clsSlider = Scale(self.clsFrame, from_=-3, to=2, orient=HORIZONTAL, resolution=0.1) self.clsSlider.pack(side=TOP) self.clsExitButton = Button(self.clsFrame, text="Exit", command=self.clsFrame.pack_forget) self.clsExitButton.pack(side=TOP) # ***** DFT Display Area ****** self.dftFrame = Frame(self.master) self.magPanel = Label(self.dftFrame) self.magPanel.pack(padx=10, pady=10, side=TOP) self.freqPanel = Label(self.dftFrame) self.freqPanel.pack(padx=10, pady=10, side=TOP) self.dftExitButton = Button( self.dftFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.dftExitButton.pack(side=TOP, fill=X) # ***** Low Pass Mask Creation ***** self.lpmFrame = Frame(self.master) self.lpmPanel = Label(self.lpmFrame) self.lpmPanel.pack(padx=10, pady=10, side=TOP) self.lpmSubButton = Button(self.lpmFrame, text="submit") self.lpmSubButton.pack(side=TOP) self.lpmExitButton = Button( self.lpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.lpmExitButton.pack(side=TOP) self.lpmSlider = Scale(self.lpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** High Pass Mask Creation ***** self.hpmFrame = Frame(self.master) self.hpmPanel = Label(self.hpmFrame) self.hpmPanel.pack(padx=10, pady=10, side=TOP) self.hpmSubButton = Button(self.hpmFrame, text="submit") self.hpmSubButton.pack(side=TOP) self.hpmExitButton = Button( self.hpmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.hpmExitButton.pack(side=TOP) self.hpmSlider = Scale(self.hpmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bppmFrame = Frame(self.master) self.bppmPanel = Label(self.bppmFrame) self.bppmPanel.pack(padx=10, pady=10, side=TOP) self.bppmSubButton = Button(self.bppmFrame, text="submit") self.bppmSubButton.pack(side=TOP) self.bppmExitButton = Button( self.bppmFrame, text="Exit", command=lambda: self.displayImg(np.array(self.img))) self.bppmExitButton.pack(side=TOP) self.bppmSliderLow = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bppmSliderHigh = Scale(self.bppmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) # ***** Band Pass Mask Creation ***** self.bspmFrame = Frame(self.master) self.bspmPanel = Label(self.bspmFrame) self.bspmPanel.pack(padx=10, pady=10, side=TOP) self.bspmSubButton = Button(self.bspmFrame, text="submit") self.bspmSubButton.pack(side=TOP) self.bspmExitButton = Button( self.bspmFrame, text="exit", command=lambda: self.displayImg(np.array(self.img))) self.bspmExitButton.pack(side=TOP) self.bspmSliderLow = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) self.bspmSliderHigh = Scale(self.bspmFrame, from_=1, to=2, orient=HORIZONTAL, resolution=1) def displayImg(self, img): # input image in RGB self.frame.pack() self.dftFrame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(self.img) self.panel.configure(image=imgtk) self.panel.image = imgtk def openImage(self): # can change the image path = filedialog.askopenfilename() if len(path) > 0: imgRead = cv2.imread(path) if imgRead is not None: imgRead = cv2.cvtColor(imgRead, cv2.COLOR_BGR2RGB) self.origImg = Image.fromarray(imgRead) self.prevImg = Image.fromarray(imgRead) self.displayImg(imgRead) else: raise ValueError("Not a valid image") else: raise ValueError("Not a valid path") def loadKernel(self): path = filedialog.askopenfilename() if len(path) > 0: self.filter_kernel = np.mean(cv2.imread(path), axis=-1) self.filter_kernel = self.filter_kernel / np.sum( self.filter_kernel) else: raise ValueError("Not a valid path") def saveImage(self): if self.img is not None: toSave = filedialog.asksaveasfilename() self.img.save(toSave) else: messagebox.showerror(title="Save Error", message="No image to be saved!") def histWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.histEqlFunc(img) self.displayImg(imgNew) # Gamma Correction def gammaCallback(self, event, img): gamma = self.gammaSlider.get() self.prevImg = self.img imgNew = image_utils.gammaCorFunc(img, 255.0 / (255.0**gamma), gamma) self.displayImg(imgNew) def truncatedInverseCallback(self, event, img): th = 10**self.truncatedInverseSlider.get() imgNew = self.truncatedInverseFilter(th) self.displayImg(imgNew) def weinerCallback(self, event, img): gamma = 10**self.weinerSlider.get() imgNew = self.weinerFilter(gamma) self.displayImg(imgNew) def clsCallback(self, event, img): K = 10**self.clsSlider.get() imgNew = self.clsFilter(K) self.displayImg(imgNew) def gammaCorWrap(self): img = np.array(self.img) self.gammaFrame.pack() self.gammaSlider.set(1.0) self.gammaSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.gammaCallback(event, img)) def logTranWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.logTranFunc(img, 255.0 / np.log10(256)) self.displayImg(imgNew) def sharpWrap(self): # Sharpen Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.sharpFunc(img) self.displayImg(imgNew) def boxBlurWrap(self): # Box Blur Wrapper img = np.array(self.img) self.prevImg = self.img self.boxFrame.pack() self.boxSlider.set(1) self.boxSlider.bind("<ButtonRelease-1>", lambda event, img=img: self.displayImg( image_utils.boxBlurFunc( event, img, 2 * self.boxSlider.get() + 1))) def gaussianBlurWrap(self): # Gaussian Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.gaussianBlurFunc(img) self.displayImg(imgNew) def medianBlurWrap(self): # Median Blur Wrapper img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.medianBlurFunc(img) self.displayImg(imgNew) def cartoonifyWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = image_utils.cartoonifyFunc(img) self.displayImg(imgNew) def undoFunc(self): self.img = self.prevImg self.displayImg(np.array(self.img)) def origFunc(self): self.prevImg = self.img self.img = self.origImg self.displayImg(np.array(self.img)) def displayDFT(self, x_fft): m, n = x_fft.shape[:] self.frame.pack_forget() self.dftFrame.pack() x_mag = np.log10(np.absolute(x_fft)) * 255 / np.log10(m * n * 255) x_mag = Image.fromarray(x_mag) x_mag = x_mag.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_mag = ImageTk.PhotoImage(x_mag) x_freq = (np.angle(x_fft) % 360) * 255 / 360 x_freq = Image.fromarray(x_freq) x_freq = x_freq.resize((min(256, m), min(int(256 * n / m), n)), Image.ANTIALIAS) x_freq = ImageTk.PhotoImage(x_freq) self.magPanel.configure(image=x_mag) self.magPanel.image = x_mag self.freqPanel.configure(image=x_freq) self.freqPanel.image = x_freq def dftWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) self.displayDFT(x_outp_img) def freqMaskWrap(self): m, n = np.array(self.img).shape[:2] lm, ln = np.log2(m), np.log2(m) dm, dn = int(2**np.ceil(lm)) + 1, int(2**np.ceil(ln)) + 1 messagebox.showinfo( "Mask Size", "Mask Size should be (" + str(dm) + "," + str(dn) + ")") path = filedialog.askopenfilename() if len(path) > 0: maskRead = cv2.imread(path, 0) if (maskRead.shape != (dm, dn)): messagebox.showerror( title="Shape Error", message="Shape of mask and image don't match") else: self.prevImg = self.img self.display(image_utils.freqMask(np.array(self.img), maskRead)) else: raise ValueError("Not a valid path") def maskWrap(self): img = np.array(self.img) x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) x_outp_img = fft.fft2d_img(x) x_mag = image_utils.xMagCreate(x_outp_img) return x_outp_img, x_mag def maskFinal(self, x_outp_img): self.prevImg = self.img img = np.array(self.img) img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) m = len(img) res = fft.ifft2d_img(x_outp_img) res = np.array(res * 255 / np.max(res), dtype=np.uint8) res = np.array([[[img[i][j][0], img[i][j][1], res[i][j]] for j in range(m)] for i in range(m)]) res = cv2.cvtColor(res, cv2.COLOR_HSV2RGB) self.displayImg(res) def lpmCallBack(self, event, slider, x_outp_img): m = len(x_outp_img) m2 = int((m - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(m)] for i in range(m)]) nCircle = np.where(nCircle > r**2) x_outp_copy[nCircle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag def lpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.lpmSlider.get() nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nCircle = np.where(nCircle > r**2) x_outp_img[nCircle] = 0 self.maskFinal(x_outp_img) def lpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.lpmPanel.configure(image=x_mag) self.lpmPanel.image = x_mag self.lpmSlider.configure(to=int(np.ceil(m / 2))) self.lpmSlider.set(1) self.lpmSlider.pack(side=TOP) self.lpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.lpmSlider, x_outp_img=x_outp_img: self. lpmCallBack(event, slider, x_outp_img)) self.lpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.lpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.lpmFrame.pack() def hpmCallBack(self, event, slider, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = slider.get() x_outp_copy = np.copy(x_outp_img) circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_copy[circle] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag def hpmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r = self.hpmSlider.get() circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) circle = np.where(circle <= r**2) x_outp_img[circle] = 0 self.maskFinal(x_outp_img) def hpmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.hpmPanel.configure(image=x_mag) self.hpmPanel.image = x_mag self.hpmSlider.configure(to=m // 2) self.hpmSlider.set(1) self.hpmSlider.pack(side=TOP) self.hpmSlider.bind( "<ButtonRelease-1>", lambda event, slider=self.hpmSlider, x_outp_img=x_outp_img: self. hpmCallBack(event, slider, x_outp_img)) self.hpmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.hpmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack_forget() self.hpmFrame.pack() def bppmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() assert (r1 <= r2) self.bppmSliderLow.configure(to=r2) self.bppmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_copy[nullVals] = 1 nullVals = np.where(allVals > r2**2) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag def bppmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bppmSliderLow.get() r2 = self.bppmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where(allVals < r1**2) x_outp_img[nullVals] = 0 nullVals = np.where(allVals > r2**2) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bppmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bppmPanel.configure(image=x_mag) self.bppmPanel.image = x_mag self.bppmSliderHigh.configure(from_=1) self.bppmSliderHigh.configure(to=m // 2) self.bppmSliderHigh.set(m // 2) self.bppmSliderHigh.pack(side=TOP) self.bppmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSliderLow.configure(from_=1) self.bppmSliderLow.configure(to=m // 2) self.bppmSliderLow.set(1) self.bppmSliderLow.pack(side=TOP) self.bppmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bppmCallBack(event, x_outp_img)) self.bppmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bppmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bspmFrame.pack_forget() self.bppmFrame.pack() def bspmCallBack(self, event, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() assert (r1 <= r2) self.bspmSliderLow.configure(to=r2) self.bspmSliderHigh.configure(from_=r1) x_outp_copy = np.copy(x_outp_img) allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_copy[nullVals] = 1 x_mag = image_utils.xMagCreate(x_outp_copy) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag def bspmFinal(self, x_outp_img): mx = len(x_outp_img) m2 = int((mx - 1) / 2) r1 = self.bspmSliderLow.get() r2 = self.bspmSliderHigh.get() allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)] for i in range(mx)]) nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0) x_outp_img[nullVals] = 0 self.maskFinal(x_outp_img) def bspmWrap(self): x_outp_img, x_mag = self.maskWrap() m = len(x_outp_img) self.bspmPanel.configure(image=x_mag) self.bspmPanel.image = x_mag self.bspmSliderHigh.configure(from_=1) self.bspmSliderHigh.configure(to=m // 2) self.bspmSliderHigh.set(m // 2) self.bspmSliderHigh.pack(side=TOP) self.bspmSliderHigh.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSliderLow.configure(from_=1) self.bspmSliderLow.configure(to=m // 2) self.bspmSliderLow.set(1) self.bspmSliderLow.pack(side=TOP) self.bspmSliderLow.bind("<ButtonRelease-1>", lambda event, x_outp_img=x_outp_img: self. bspmCallBack(event, x_outp_img)) self.bspmSubButton.configure( command=lambda x_outp_img=x_outp_img: self.bspmFinal(x_outp_img)) self.dftFrame.pack_forget() self.frame.pack_forget() self.lpmFrame.pack_forget() self.hpmFrame.pack_forget() self.bppmFrame.pack_forget() self.bspmFrame.pack() def fullInverseWrap(self): img = np.array(self.img) self.prevImg = self.img imgNew = filtering.inverseFilter2D(img, self.filter_kernel) self.displayImg(imgNew) def truncatedInverseWrap(self): img = np.array(self.img) self.prevImg = self.img self.truncatedInverseFilter = filtering.getTruncatedInverseFilter2D( img, self.filter_kernel) self.truncatedInverseFrame.pack() self.truncatedInverseSlider.set(1.0) self.truncatedInverseSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.truncatedInverseCallback(event, img)) def approximateWeinerWrap(self): img = np.array(self.img) self.prevImg = self.img self.weinerFilter = filtering.getApproximateWeinerFilter2D( img, self.filter_kernel) self.weinerFrame.pack() self.weinerSlider.set(1.0) self.weinerSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.weinerCallback(event, img)) def contrainedLSWrap(self): # TODO: implement img = np.array(self.img) self.prevImg = self.img self.clsFilter = filtering.getConstrainedLSFilter2D( img, self.filter_kernel) self.clsFrame.pack() self.clsSlider.set(1.0) self.clsSlider.bind( "<ButtonRelease-1>", lambda event, img=img: self.clsCallback(event, img))
cb3 = ttk.Combobox(root) cb3.grid(row=3, column=2, sticky="we") cb3['value'] = method() cb3.current(0) ## row 4 v1 = DoubleVar() s1 = Scale(root, label="Speed:", variable=v1, from_=0.25, to=4.00, orient="horizontal", resolution=0.01) s1.grid(row=4, column=1, sticky="wens") s1.set(1.00) v2 = DoubleVar() s2 = Scale(root, label="Pitch:", variable=v2, from_=-20, to=20.00, orient="horizontal", resolution=0.01) s2.grid(row=4, column=2, sticky="wens") s2.set(0) # row 5: Check and save # bt1 = Button(root, text = "SPEAK IT", font=("Helvetica", 18, "bold")) # bt1.grid(row = 5, column = 1, pady = 20, sticky = "we")
class TelloUI(object): """ Wrapper class to enable the GUI. """ def __init__(self, tello): """ Initializes all the element of the GUI, supported by Tkinter :param tello: class interacts with the Tello drone. """ self.tello = tello # videostream device self.thread = None # thread of the Tkinter mainloop self.stopEvent = None # control variables self.distance = 0.1 # default distance for 'move' cmd self.degree = 30 # default degree for 'cw' or 'ccw' cmd # if the flag is TRUE,the auto-takeoff thread will stop waiting # for the response from tello self.quit_waiting_flag = False # initialize the root window and image panel self.root = tki.Tk() self.panel = None # create buttons self.btn_landing = tki.Button(self.root, text='Open Command Panel', relief='raised', command=self.openCmdWindow) self.btn_landing.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) # start a thread that constantly pools the video sensor for # the most recently read frame self.stopEvent = threading.Event() # set a callback to handle when the window is closed self.root.wm_title('TELLO Controller') self.root.wm_protocol('WM_DELETE_WINDOW', self.on_close) # the sending_command will send command to tello every 5 seconds self.sending_command_thread = threading.Thread( target=self._sendingCommand) def _sendingCommand(self): """ Starts a while loop that sends 'command' to tello every 5 second. :return: None """ while True: self.tello.send_command('command') time.sleep(5) def _setQuitWaitingFlag(self): """ Set the variable as TRUE; it will stop computer waiting for response from tello. :return: None """ self.quit_waiting_flag = True def openCmdWindow(self): """ Open the cmd window and initial all the button and text. :return: None """ panel = Toplevel(self.root) panel.wm_title('Command Panel') # create text input entry text0 = tki.Label( panel, text= 'This Controller map keyboard inputs to Tello control commands\n' 'Adjust the trackbar to reset distance and degree parameter', font='Helvetica 10 bold') text0.pack(side='top') text1 = tki.Label( panel, text='W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n' 'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n' 'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n' 'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right', justify='left') text1.pack(side='top') self.btn_landing = tki.Button(panel, text='Land', relief='raised', command=self.telloLanding) self.btn_landing.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) self.btn_takeoff = tki.Button(panel, text='Takeoff', relief='raised', command=self.telloTakeOff) self.btn_takeoff.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) # binding arrow keys to drone control self.tmp_f = tki.Frame(panel, width=100, height=2) self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w) self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s) self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a) self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d) self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up) self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down) self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left) self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right) self.tmp_f.pack(side='bottom') self.tmp_f.focus_set() self.btn_landing = tki.Button(panel, text='Flip', relief='raised', command=self.openFlipWindow) self.btn_landing.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) self.distance_bar = Scale(panel, from_=0.02, to=5, tickinterval=0.01, digits=3, label='Distance(m)', resolution=0.01) self.distance_bar.set(0.2) self.distance_bar.pack(side='left') self.btn_distance = tki.Button( panel, text='Reset Distance', relief='raised', command=self.updateDistancebar, ) self.btn_distance.pack(side='left', fill='both', expand='yes', padx=10, pady=5) self.degree_bar = Scale(panel, from_=1, to=360, tickinterval=10, label='Degree') self.degree_bar.set(30) self.degree_bar.pack(side='right') self.btn_distance = tki.Button(panel, text='Reset Degree', relief='raised', command=self.updateDegreebar) self.btn_distance.pack(side='right', fill='both', expand='yes', padx=10, pady=5) def openFlipWindow(self): """ Open the flip window and initial all the button and text. :return: None """ panel = Toplevel(self.root) panel.wm_title('Gesture Recognition') self.btn_flipl = tki.Button(panel, text='Flip Left', relief='raised', command=self.telloFlip_l) self.btn_flipl.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) self.btn_flipr = tki.Button(panel, text='Flip Right', relief='raised', command=self.telloFlip_r) self.btn_flipr.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) self.btn_flipf = tki.Button(panel, text='Flip Forward', relief='raised', command=self.telloFlip_f) self.btn_flipf.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) self.btn_flipb = tki.Button(panel, text='Flip Backward', relief='raised', command=self.telloFlip_b) self.btn_flipb.pack(side='bottom', fill='both', expand='yes', padx=10, pady=5) def telloTakeOff(self): return self.tello.takeoff() def telloLanding(self): return self.tello.land() def telloFlip_l(self): return self.tello.flip('l') def telloFlip_r(self): return self.tello.flip('r') def telloFlip_f(self): return self.tello.flip('f') def telloFlip_b(self): return self.tello.flip('b') def telloCW(self, degree): return self.tello.rotate_cw(degree) def telloCCW(self, degree): return self.tello.rotate_ccw(degree) def telloMoveForward(self, distance): return self.tello.move_forward(distance) def telloMoveBackward(self, distance): return self.tello.move_backward(distance) def telloMoveLeft(self, distance): return self.tello.move_left(distance) def telloMoveRight(self, distance): return self.tello.move_right(distance) def telloUp(self, dist): return self.tello.move_up(dist) def telloDown(self, dist): return self.tello.move_down(dist) def updateDistancebar(self): self.distance = self.distance_bar.get() print(f'reset distance to {self.distance:.1f}') def updateDegreebar(self): self.degree = self.degree_bar.get() print(f'reset distance to {self.degree}') def on_keypress_w(self, event): print(f'up {self.distance} m') self.telloUp(self.distance) def on_keypress_s(self, event): print(f'down {self.distance} m') self.telloDown(self.distance) def on_keypress_a(self, event): print(f'ccw {self.degree} degree') self.tello.rotate_ccw(self.degree) def on_keypress_d(self, event): print(f'cw {self.degree} m') self.tello.rotate_cw(self.degree) def on_keypress_up(self, event): print(f'forward {self.distance} m') self.telloMoveForward(self.distance) def on_keypress_down(self, event): print(f'backward {self.distance} m') self.telloMoveBackward(self.distance) def on_keypress_left(self, event): print(f'left {self.distance} m') self.telloMoveLeft(self.distance) def on_keypress_right(self, event): print(f'right {self.distance} m') self.telloMoveRight(self.distance) def on_close(self): """ Sets the stop event, cleanup the camera, and allow the rest of the quit process to continue. :return: None """ print('[INFO] closing...') self.stopEvent.set() del self.tello self.root.quit()
class Application(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.pack() self.createWidgets() def generate(self): n = int(self.menu_gen.get()) seed = self.inp_seed.get() self.output = Generator.convert(seed, n) if len(self.output) > 0: self.generated = True self.butt_draw.config( state= 'normal') self.chek_fullscrn.config(state= 'normal') self.clearOutput(self.output) def draw(self, n, step=False): p1, p2 = Draw.move(n) self.curr_canvas.create_line(p1[0], p1[1], p2[0], p2[1], fill= self.color, width= self.thick) if step: self.curr_canvas.update_idletasks() def do(self, action, step, rainbow): if len(action) > 1: p = action[1] else: p = 1.0 self.timebuff += step cmd = action[0].lower() if cmd == "draw": if rainbow: self.incColor() if self.incThickYN: self.incThick(self.reverseThick, False) elif self.incThickYN: self.incThick(self.reverseThick, True) if self.timebuff > 1.0: truncate = int(self.timebuff) self.after(truncate, self.draw(float(p), True)) self.timebuff -= truncate else: self.draw(float(p)) elif cmd == "turn": Draw.turn(float(p)) elif cmd == "skip": Draw.skip(float(p)) elif cmd == "back": Draw.back(float(p)) elif cmd == "color": if not rainbow: self.color = Color.getHexString(p) elif cmd == "thick": self.thick = int(p) else: print("Unknown command " + cmd) def drawAll(self, newWindow= True): if self.generated == True: self.butt_print.config(state= 'disabled') self.timebuff = 0.0 self.color = Color.white() self.thick = 2 l = float(self.slid_linesize.get()) a = float(self.slid_angle.get()) Draw.init(self.startingPoint, l, a) if self.fullScreen.get() == 1: if newWindow: self.curr_canvas = dc.BigCanvas(self).canvas self.canvas.delete("all") else: self.curr_canvas = self.canvas self.curr_canvas.delete("all") self.curr_canvas.config(bg= Color.getHexString(self.bgColor.get())) rainbow = self.rainbowCheck.get() == 1 if rainbow or self.incThickYN: self.incStep = 1.0/float(self.getDrawCount(self.output)) self.percent = 0.0 for c in self.output: if c == '[': Draw.push() elif c == ']': Draw.pop() else: for r in Rule.getDrawings(): if c == r[0]: if len(r) > 2: params = (r[1], r[2]) else: params = (r[1],) s = float(self.slid_timer.get()) self.do(params, s, rainbow) break self.butt_print.config(state= 'normal') def incColor(self): self.color = Color.getValueByPercent(self.percent) self.percent += self.incStep def incThick(self, reverse, incYN): maxthick = 5 minthick = 1 diff = maxthick - minthick if reverse: result = maxthick - int(diff * self.percent) else: result = minthick + int(diff * self.percent) self.thick = result if incYN: self.percent += self.incStep def getDrawCount(self, s): draw_commands = [] for r in Rule.getDrawings(): if r[1].lower() == "draw": draw_commands.append(r[0]) draw_count = 0; for c in s: for d in draw_commands: if c == d: draw_count += 1 break return draw_count def clearOutput(self, replacement=None): self.text_output.config(state= 'normal') self.text_output.delete(1.0, END) if replacement: self.text_output.insert(END, replacement) self.text_output.config(state= 'disabled') def formatRules(self, rules): ret = [] for r in rules: entry = r[0] + " | " + r[1] if len(r) > 2: entry += " " + r[2] ret.append(entry) return ret def getRuleFromFormatted(self, s): if s: rule = s.split('|') rule[0] = rule[0].strip() rule[1] = rule[1].strip() prod = rule[1].split(" ") if len(prod) == 1: return (rule[0], prod[0]) else: return (rule[0], prod[0], prod[1]) def RefreshLists(self): self.list_prod.delete(0, END) self.list_draw.delete(0, END) l = self.formatRules(Rule.getProductions()) for p in l: self.list_prod.insert(END, p) l = self.formatRules(Rule.getDrawings()) for d in l: self.list_draw.insert(END, d) def AddProductionRule(self, edit=None): rule = dp.AddProductionRuleDialog(self, edit).result if rule: if edit: Rule.removeProd(edit[0]) Rule.AddProduction(rule) self.RefreshLists() def AddDrawingRule(self, edit=None): rule = dd.AddDrawingRuleDialog(self, edit).result if rule: if edit: Rule.removeDraw(edit[0]) Rule.AddDrawing(rule) self.RefreshLists() def EditProductionRule(self): s = self.list_prod.curselection() if s: idx = s[0] rule = (idx,) + self.getRuleFromFormatted(self.list_prod.get(idx)) if rule: self.AddProductionRule(rule) def EditDrawingRule(self): s = self.list_draw.curselection() if s: idx = s[0] rule = (idx,) + self.getRuleFromFormatted(self.list_draw.get(idx)) if rule: self.AddDrawingRule(rule) def DeleteProductionRule(self): s = self.list_prod.curselection() if s: Rule.removeProd(s[0]) self.RefreshLists() def DeleteDrawingRule(self): s = self.list_draw.curselection() if s: Rule.removeDraw(s[0]) self.RefreshLists() def packOutput(self): ret = "" ret += self.packAxiom() ret += self.packProdRules() ret += self.packDrawRules() return ret def packAxiom(self): return "@" + str(self.inp_seed.get()).strip() def packRules(self, rules): ret = "@" for r in rules: ret += "$" + str(r[0]) + "|" + str(r[1]) if len(r) > 2: ret += ":" + str(r[2]) return ret def packProdRules(self): return self.packRules(Rule.getProductions()) def packDrawRules(self): return self.packRules(Rule.getDrawings()) def parseProdRules(self, raw): rules = raw.split('$') for rule in rules: if rule is not "": r = rule.split('|') Rule.AddProduction((r[0], r[1])) def parseDrawRules(self, raw): rules = raw.split('$') for rule in rules: if rule is not "": r = rule.split('|') p = r[1].split(':') if len(p) == 1: tup = (r[0], p[0]) else: tup = (r[0], p[0], p[1]) Rule.AddDrawing(tup) def parseSaveFile(self, s): Rule.wipe() settings = s.split('@') self.inp_seed.set(str(settings[1])) self.parseProdRules(settings[2]) self.parseDrawRules(settings[3]) self.RefreshLists() def save(self): try: filename = filedialog.asksaveasfilename(**self.file_options['txt']) if filename: f = open(filename, 'w') f.write(self.packOutput()) f.close() except Exception as e: print("File IO error in save\n", e) def load(self): try: filename = filedialog.askopenfilename(**self.file_options['txt']) if filename: f = open(filename, 'r') self.parseSaveFile(f.read()) f.close() self.slid_linesize.set(1.0) self.slid_timer.set(0.0) self.menu_gen.set(1) self.clearOutput() except Exception as e: print("File IO error in load\n" + e) def help(self): help.HelpDialog(self) def saveImage(self): filename = filedialog.asksaveasfilename(**self.file_options['ps']) self.curr_canvas.postscript(file=filename, colormode='color') def click(self, event): self.startingPoint = (event.x, event.y) def clickAndRedraw(self, event): self.click(event) self.drawAll(False) def fileOptions(self): self.file_options = {} txt_options = {} ps_options = {} txt_options['defaultextension'] = '.txt' txt_options['filetypes'] = [('Plaintext', '.txt')] txt_options['initialdir'] = 'Patterns' ps_options['defaultextension'] = '.ps' ps_options['filetypes'] = [('Postscript Image', '.ps')] ps_options['initialdir'] = 'Images' self.file_options['txt'] = txt_options self.file_options['ps'] = ps_options def makeMenuBar(self): self.menubar = Menu(self); self.menubar.add_command(label="Save", command= self.save) self.menubar.add_command(label="Load", command= self.load) self.menubar.add_command(label="Help", command= self.help) root.config(menu= self.menubar) def makeInputFrame(self): self.inp_seed = String() self.bgColor = String() self.gen_value = Int() self.rainbowCheck = Int() self.fram_input = Frame(self, bd= 2, relief= self.style, width= input_frame_width, height= input_frame_height) self.fram_seed = Frame(self.fram_input, bd= 1, relief= self.style) self.fram_prod = Frame(self.fram_input, bd= 1, relief= self.style) self.fram_draw = Frame(self.fram_input, bd= 1, relief= self.style) self.fram_drawParams = Frame(self.fram_input, bd= 1, relief= self.style) self.fram_gen = Frame(self.fram_input, bd= 1, relief= self.style) self.fram_output = Frame(self.fram_input, bd= 1, relief= self.style) self.menu_gen = DropDown(self.fram_gen, textvariable= self.gen_value, state= 'readonly') self.entr_seed = Input(self.fram_seed, textvariable= self.inp_seed) self.text_output = Output(self.fram_output, width= 35, height= 10) self.scrl_output = Scrollbar(self.fram_output) self.list_prod = List(self.fram_prod, selectmode= BROWSE, font= "Courier 8", height= 5) self.list_draw = List(self.fram_draw, selectmode= BROWSE, font= "Courier 8", height= 5) self.slid_linesize = Slider(self.fram_drawParams, from_= 0.1, to= 10.0, orient= HORIZONTAL, resolution= 0.1, length= 180) self.slid_timer = Slider(self.fram_drawParams, from_= 0, to= 2, orient= HORIZONTAL, resolution= 0.02, length= 180) self.slid_angle = Slider(self.fram_drawParams, from_= 0, to= 359, orient= HORIZONTAL, length= 180) self.entr_bgcolor = Input (self.fram_drawParams, textvariable= self.bgColor) self.butt_prodAdd = Button(self.fram_prod, text= "Add", width=8, command= self.AddProductionRule) self.butt_prodEdit = Button(self.fram_prod, text= "Edit", width=8, command= self.EditProductionRule) self.butt_prodDelete = Button(self.fram_prod, text= "Delete", width=8, command= self.DeleteProductionRule) self.butt_drawAdd = Button(self.fram_draw, text= "Add", width=8, command= self.AddDrawingRule) self.butt_drawEdit = Button(self.fram_draw, text= "Edit", width=8, command= self.EditDrawingRule) self.butt_drawDelete = Button(self.fram_draw, text= "Delete", width=8, command= self.DeleteDrawingRule) self.chek_incColor = CheckBox(self.fram_draw, text= "Rainbow", variable= self.rainbowCheck) Label(self.fram_seed, text= "Axiom:", width=8).grid (row=0, column=0) Label(self.fram_prod, text= "Production\nRules:", width=8).grid (row=0, column=0) Label(self.fram_draw, text= "Drawing\nRules:", width=8).grid (row=0, column=0) Label(self.fram_drawParams, text= "Line Size:").grid (row=0, column=0) Label(self.fram_drawParams, text= "Delay (ms):").grid (row=1, column=0) Label(self.fram_drawParams, text= "Starting Angle:").grid (row=2, column=0) Label(self.fram_drawParams, text= "Background Color:").grid (row=3, column=0) Label(self.fram_output, text= "Output:").grid (row=0, column=0) Label(self.fram_gen, text= "Generations:").grid (row=0, column=0) self.gen_value.set(1) self.menu_gen['values'] = tuple(range(1, 13)) self.slid_linesize.set(1.0) self.bgColor.set( Color.default() ) self.text_output.config(state='disabled', yscrollcommand= self.scrl_output.set) self.scrl_output.config(command=self.text_output.yview) self.fram_input.grid (row=0, column=0) self.fram_seed.grid (row=1, column=0, sticky= 'ew') self.fram_prod.grid (row=2, column=0, sticky= 'ew') self.fram_draw.grid (row=3, column=0, sticky= 'ew') self.fram_drawParams.grid (row=4, column=0, sticky= 'ew') self.fram_gen.grid (row=5, column=0, sticky= 'ew') self.fram_output.grid (row=6, column=0, sticky= 'ew') self.entr_seed.grid (row=0, column=1, sticky= 'ew') self.list_prod.grid (row=0, column=1, sticky= 'ew') self.butt_prodAdd.grid (row=1, column=0, sticky= 'ew') self.butt_prodEdit.grid (row=1, column=1, sticky= 'ew') self.butt_prodDelete.grid (row=1, column=2, sticky= 'ew') self.list_draw.grid (row=0, column=1) self.butt_drawAdd.grid (row=1, column=0, sticky= 'ew') self.butt_drawEdit.grid (row=1, column=1, sticky= 'ew') self.butt_drawDelete.grid (row=1, column=2, sticky= 'ew') self.chek_incColor.grid (row=0, column=2) self.slid_linesize.grid (row=0, column=1, sticky= 'ew') self.slid_timer.grid (row=1, column=1, sticky= 'ew') self.slid_angle.grid (row=2, column=1, sticky= 'ew') self.entr_bgcolor.grid (row=3, column=1, sticky= 'ew') self.menu_gen.grid (row=0, column=1, sticky= 'ew') self.text_output.grid (row=1, column=0) self.scrl_output.grid (row=1, column=1, sticky= 'ns') def makeCanvasFrame(self): self.fram_canvas = Frame(self, bd=10, relief=self.style) self.canvas = Canvas(self.fram_canvas, width= canvas_width, height= canvas_height) self.fram_canvas.grid(row=0, column=1, sticky='nesw') self.canvas.grid(sticky='nesw') self.canvas.bind("<Button-1>", self.click) self.curr_canvas = self.canvas def makeIgnitionFrame(self): self.fullScreen = Int() self.fram_ignition = Frame(self, bd=4, relief=self.style, width= ignition_frame_width, height= ignition_frame_height) self.butt_generate = Button(self.fram_ignition, text= " -- GENERATE -- ", width=111, command= self.generate) self.butt_draw = Button(self.fram_ignition, text= " -- DRAW -- ", width=100, command= self.drawAll, state= 'disabled') self.butt_print = Button(self.fram_ignition, text= "Save Image", command= self.saveImage, state= 'disabled') self.chek_fullscrn = CheckBox(self.fram_ignition, text= "Fullscreen", variable= self.fullScreen, state= 'disabled') self.fram_ignition.grid(row=1, column=0, columnspan=2) self.butt_generate.grid(row=0, column=0, columnspan=2) self.butt_draw.grid( row=1, column=0) self.butt_print.grid( row=0, column=2, rowspan= 2, sticky='ns') self.chek_fullscrn.grid(row=1, column=1) def createWidgets(self): self.incThickYN = False self.reverseThick = False self.style = RIDGE self.startingPoint = (20, 20) self.generated = False self.fileOptions() self.makeMenuBar() self.makeInputFrame() self.makeCanvasFrame() self.makeIgnitionFrame()
text="Load example image", width=16, command=load_example, activebackground="#e3c3d7") load2_button = Button(save_load_frame, text="Load example2 image", width=16, command=load2_example, activebackground="#e3c3d7") curve_n_label = Label(options_frame, text="Curve Flow") curve_n = Scale(options_frame, from_=4, to=75, orient="horizontal") curve_guide_label = Label(options_frame, text="show curve guide?") curve_guide_check = Checkbutton(options_frame, variable=curve_guide) circle_guide_label = Label(options_frame, text="show circles on click?") circle_guide_check = Checkbutton(options_frame, variable=click_circle) curve_n.set(50) axis_label = Label(options_frame, text="mirror axis") x_radio = Radiobutton(options_frame, text="X", variable=mirror_axis, value='x') y_radio = Radiobutton(options_frame, text="Y", variable=mirror_axis, value='y') xy_radio = Radiobutton(options_frame, text="XY", variable=mirror_axis, value='xy') #Set in GUI load_button.pack(side="top") load2_button.pack(side="top") save_button.pack(side="bottom") bg_color_sett.pack(side="left") curve_n_label.pack(side="left") curve_n.pack(side="left")
class AuxMode(Frame): def __init__(self, root, parent): Frame.__init__(self, root, borderwidth=2, relief='groove', height=10) settings = parent.settings('aux_mode') self.parent = parent lbl_power = Label(self, text='Power:') lbl_power.grid(row=0, column=0, pady=2) self.cmb_power = ttk.Combobox(self, value=['Off', 'On']) self.cmb_power.grid(row=0, column=1, pady=2) self.cmb_power.set(settings['power']) self.cmb_power['state'] = 'readonly' self.cmb_power.bind('<<ComboboxSelected>>', self.set_power) lbl_aux_pin = Label(self, text='AUX pin:') lbl_aux_pin.grid(row=1, column=0, pady=2) self.cmb_aux_pin = ttk.Combobox(self, values=['AUX', 'CS']) self.cmb_aux_pin.grid(row=1, column=1, pady=2) self.cmb_aux_pin['state'] = 'readonly' self.cmb_aux_pin.set(settings['aux_pin']) self.cmb_aux_pin.bind('<<ComboboxSelected>>', self.select_aux_pin) lbl_aux = Label(self, text='AUX mode:') lbl_aux.grid(row=2, column=0, pady=2) self.cmb_aux_mode = ttk.Combobox( self, values=['Input', 'Output', 'Servo', 'PWM']) self.cmb_aux_mode.grid(row=2, column=1, pady=2) self.cmb_aux_mode['state'] = 'readonly' self.cmb_aux_mode.set(settings['mode']) self.cmb_aux_mode.bind('<<ComboboxSelected>>', self.select_aux_mode) self.aux_servo = Scale(self, from_=0, to=180, orient='horizontal') self.aux_servo.set(settings['servo']) self.aux_servo.bind('<ButtonRelease-1>', self.select_aux_mode) self.aux_pin_state = IntVar() self.aux_pin_state.set(settings['aux_state']) self.aux_pin_state.trace_add('write', self.select_aux_mode) self.aux_high = Radiobutton(self, text='HIGH', value=1, variable=self.aux_pin_state) self.aux_low = Radiobutton(self, text='LOW', value=0, variable=self.aux_pin_state) self.aux_pwm_lbl = Label(self, text='Frequency (KHz):') self.aux_pwm_freq = Entry(self) self.aux_pwm_freq.insert(0, settings['pwm_freq']) self.aux_pwm_freq.bind('<KeyRelease>', self.select_aux_mode) self.aux_pwm_duty_lbl = Label(self, text='Duty cycle (%):') self.aux_pwm_duty = Scale(self, from_=0, to=99, orient='horizontal') self.aux_pwm_duty.set(settings['pwm_duty']) self.aux_pwm_duty.bind('<ButtonRelease-1>', self.select_aux_mode) def __call__(self): return { 'power': self.cmb_power.get(), 'mode': self.cmb_aux_mode.get(), 'aux_state': self.aux_pin_state.get(), 'aux_pin': self.cmb_aux_pin.get(), 'servo': self.aux_servo.get(), 'pwm_freq': self.aux_pwm_freq.get(), 'pwm_duty': self.aux_pwm_duty.get() } def select_aux_mode(self, e=None, a=None, b=None): for i, widget in enumerate(self.winfo_children()): if i > 5: widget.grid_forget() mode = self.cmb_aux_mode.get() # if self.parent.console.mode == 'HiZ': return if mode == 'Input': self.parent.console.aux('Input') if mode == 'Output': self.aux_high.grid(row=3, column=1) self.aux_low.grid(row=4, column=1) self.parent.console.aux('Output', self.aux_pin_state.get()) if mode == 'Servo': self.aux_servo.grid(row=3, column=1) self.parent.console.servo(self.aux_servo.get()) if mode == 'PWM': self.aux_pwm_lbl.grid(row=3, column=0) self.aux_pwm_freq.grid(row=3, column=1) self.aux_pwm_duty_lbl.grid(row=4, column=0) self.aux_pwm_duty.grid(row=4, column=1) self.parent.console.pwm(self.aux_pwm_freq.get(), self.aux_pwm_duty.get()) if mode == 'CS': self.parent.console.cs() self.parent.settings('aux_mode', self()) def select_aux_pin(self, e=None): self.parent.console.aux_pin(self.cmb_aux_pin.get()) def set_power(self, e=None): self.parent.console.power(self.cmb_power.get()) self.parent.settings('aux_mode', self()) def disable(self): self.cmb_power['state'] = 'disabled' self.cmb_aux_mode['state'] = 'disabled' self.aux_high['state'] = 'disabled' self.aux_low['state'] = 'disabled' self.aux_servo['state'] = 'disabled' self.aux_pwm_freq['state'] = 'disabled' self.aux_pwm_duty['state'] = 'disabled' def enable(self): self.cmb_power['state'] = 'readonly' self.cmb_aux_mode['state'] = 'readonly' self.aux_high['state'] = 'normal' self.aux_low['state'] = 'normal' self.aux_servo['state'] = 'normal' self.aux_pwm_freq['state'] = 'normal' self.aux_pwm_duty['state'] = 'normal'
class Visual(Frame): '''Class that takes a world as argument and present it graphically on a tkinter canvas.''' def __init__(self): '''Sets up a simulation GUI in tkinter. ''' Frame.__init__(self) self.master.title("The Schelling Segregation Model in Python") self.master.wm_resizable(0, 0) self.grid() self.movement_possible = True # --------------------------------------- # # --------- FRAMES FOR GUI -------------- # # --------------------------------------- # # The pane for user values self._entryPane = Frame(self, borderwidth=5, relief='sunken') self._entryPane.grid(row=0, column=0, sticky='n') # The buttons pane self._buttonPane = Frame(self, borderwidth=5) self._buttonPane.grid(row=1, column=0, sticky='n') # A temp pane where graph is located, just for cosmetic reasons width, height = 425, 350 self._graph = Canvas(self, width=width, height=height, background="black") self._graph.configure(relief='sunken', border=2) self._graph.grid(row=3, column=0) # The pane where the canvas is located self._animationPane = Frame(self, borderwidth=5, relief='sunken') self._animationPane.grid(row=0, column=1, rowspan=4, pady=10, sticky="n") # --------------------------------------- # # --------- FILLING THE FRAMES ---------- # # --------------------------------------- # self._canvas() # Create graphics canvas self._entry() # Create entry widgets self._buttons() # Create button widgets def _plot_setup(self, time): '''Method for crudely annotating the graph window.''' time = time # Main plot width, height = 425, 350 y0 = -time / 10 self._graph = Canvas(self, width=width, height=height, background="black", borderwidth=5) self._graph.grid(row=3, column=0) self.trans = Plotcoords(width, height, y0, -0.2, time, 1.3) x, y = self.trans.screen(time // 2, 1.2) x1, y1 = self.trans.screen(time // 2, 1.13) self._graph.create_text(x, y, text="% Happy", fill="yellow", font="bold 12") self._graph.create_text(x1, y1, text="% Unhappy", fill="blue", font="bold 12") # Line x-axis x, y = self.trans.screen((-5 * (time / 100)), -0.05) x1, y = self.trans.screen(time, -0.05) self._graph.create_line(x, y, x1, y, fill="white", width=1.5) # Text x-axis x_text, y_text = self.trans.screen(time / 2, -0.15) self._graph.create_text(x_text, y_text, text="Time", fill="white", font="bold 12") # Liney-axis x, y = self.trans.screen((-0.5 * (time / 100)), -0.05) x, y1 = self.trans.screen((-5 * (time / 100)), 1) self._graph.create_line(x, y, x, y1, fill="white", width=1.5) def _entry(self): '''Method for creating widgets for collecting user input.''' # N (no of turtles) dim = 30 * 30 self._N_label = Label(self._entryPane, anchor='w', justify='left', text="N:", relief='raised', width=12, height=1, font="italic 20") self._N_label.grid(row=0, column=1, ipady=14) self._N = Scale(self._entryPane, from_=1, to=dim - 50, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=849) self._N.set(400) self._N.grid(row=0, column=2) # Ticks (lenght of simulation) self._Ticks_label = Label(self._entryPane, anchor='w', justify='left', text="Time:", relief='raised', width=12, height=1, font="bold 20") self._Ticks_label.grid(row=1, column=1, ipady=14) self._Ticks = Scale(self._entryPane, from_=10, to=1000, resolution=1, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=990) self._Ticks.set(500) self._Ticks.grid(row=1, column=2) # % similar wanted self._Similar_label = Label(self._entryPane, anchor='w', justify='left', text="Similar wanted:", relief='raised', width=12, height=1, font="bold 20") self._Similar_label.grid(row=2, column=1, ipady=14) self._Similar = Scale(self._entryPane, from_=0.0, to=1.0, resolution=0.01, bd=3, relief='sunken', orient='horizontal', length=235, tickinterval=1) self._Similar.set(0.76) self._Similar.grid(row=2, column=2) def _buttons(self): '''Method for creating button widgets for setting up, running and plotting results from simulation.''' width = 7 height = 1 # The 'Setup' button self._setupButton = Button(self._buttonPane, text="Setup", command=self._setup, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._setupButton.grid(row=0, column=0) # The 'Go' button self._goButton = Button(self._buttonPane, text="Go", command=self._go, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._goButton.grid(row=0, column=1) # The 'Quit' button self._quitButton = Button(self._buttonPane, text="Quit", command=self._quit, width=width, height=height, font="bold 30", relief='raised', borderwidth=5) self._quitButton.grid(row=1, column=0, columnspan=2) def _canvas(self): '''Creates the canvas on which everything happens.''' # The tick counter information self._Tick_counter = Label(self._animationPane, anchor='w', justify='left', text="Time:", width=5, font="bold 20") self._Tick_counter.grid(row=0, column=0, sticky="e") self._Tick_counter1 = Label(self._animationPane, justify='center', text="", relief='raised', width=5, font="bold 20") self._Tick_counter1.grid(row=0, column=1, sticky='w') self.canvas_w, self.canvas_h = 750, 750 self.canvas = Canvas(self._animationPane, width=self.canvas_w, height=self.canvas_h, background="black") self.canvas.grid(row=1, column=0, columnspan=2) def _setup(self): '''Method for 'Setup' button.''' ## Clearing the canvas and reset the go button self.canvas.delete('all') self._goButton['relief'] = 'raised' self.N = int(self._N.get()) self.Ticks = int(self._Ticks.get()) self.similar = float(self._Similar.get()) self.data = [] self.tick_counter = 0 self._Tick_counter1['text'] = str(self.tick_counter) self._plot_setup(self.Ticks) self.grid_size = 30 self.world = World(750, 750, self.grid_size) self.create_turtles() self.neighbouring_turtles() self.draw_turtles() def _go(self): '''Method for the 'Go' button, i.e. running the simulation.''' self._goButton['relief'] = 'sunken' if self.tick_counter <= self.Ticks: self._Tick_counter1['text'] = str(self.tick_counter) self.canvas.update() self._graph.update() self._graph.after(0) # Data collection turtles_unhappy = self.check_satisfaction() prop_happy, prop_unhappy = self.calc_prop_happy(self.tick_counter) self.data_collection(self.tick_counter, prop_happy, prop_unhappy) if self.tick_counter >= 1: # HAPPY values (%) x0 = self.tick_counter - 1 x1 = self.tick_counter # Collecting values from stoblue data y0 = self.data[self.tick_counter - 1][1] y1 = self.data[self.tick_counter][1] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="yellow", width=1.3, tag="happy") # Draw "happy lines # UNHAPPY values (%) x0 = self.tick_counter - 1 x1 = self.tick_counter # Collecting values from stored data y0 = self.data[self.tick_counter - 1][2] y1 = self.data[self.tick_counter][2] # Transforming to tkinter x1, y1 = self.trans.screen(x1, y1) x0, y0 = self.trans.screen(x0, y0) self._graph.create_line(x0, y0, x1, y1, fill="blue", width=1.1, tag="unhappy") # Draw unhappy lines if prop_happy < 1: self.turtle_move(turtles_unhappy) self.update_neighbours() self.tick_counter += 1 self.canvas.after(0, self._go()) self._goButton['relief'] = 'raised' def _quit(self): '''Method for the 'Quit' button.''' self.master.destroy() # ------------------------------------------------------ # # ---------- FUNCTIONS CALLED AT EACH TICK ------------- # # ------------------------------------------------------ # def turtle_move(self, unhappy_turtles): '''Moves all the unhappy turtles (randomly).''' while unhappy_turtles: i = random.randint(0, len(unhappy_turtles) - 1) turtle = unhappy_turtles.pop(i) turtle.move(self) def update_neighbours(self): '''Updates the turtles neigbour attributes. Called after all turtles have moved.''' for turtle in self.turtles: turtle.update_neighbours() def check_satisfaction(self): '''Checks to see if turtles are happy or not. Returns a list of unhappy turtles, i.e. turtles that should move. Called before the move method.''' for turtle in self.turtles: turtle.is_happy() unhappy_turtles = [] for element in self.turtles: if not element.happy: unhappy_turtles.append(element) return unhappy_turtles def calc_prop_happy(self, i): '''Calculates the proportion of happy turtles.''' happy = 0 unhappy = 0 for turtle in self.turtles: if turtle.happy: happy += 1 else: unhappy += 1 prop_happy = happy / len(self.turtles) prop_unhappy = unhappy / len(self.turtles) return prop_happy, prop_unhappy def data_collection(self, i, prop_happy, prop_unhappy): '''Method for collecting data at each tick.''' self.data.append((i, prop_happy, prop_unhappy)) # ------------------------------------------------------ # # ---------- INITIALISATION FUNCTIONS ------------------ # # ------------------------------------------------------ # def create_turtles(self): '''Method for creating a new list of turtles. Upon creation they are registered in the World object.''' if self.N <= self.grid_size * self.grid_size: counter = 0 self.turtles = [] while counter < self.N: s = "S" + str(counter) if counter <= int(self.N / 2): color = "yellow" else: color = "blue" x = random.randint(0, self.grid_size - 1) y = random.randint(0, self.grid_size - 1) if not self.world.patch_list[x][y]: new_turtle = Schelling(world=self.world, x=x, y=y, s=s, color=color, similar_wanted=self.similar) self.world.register(new_turtle) counter += 1 self.turtles.append(new_turtle) else: print("Number of turtles exceeds world!") def draw_turtles(self): '''Method for drawing turtles on canvas. Calls each turtle's own method for drawing.''' for turtle in self.turtles: turtle.draw(self.canvas) def neighbouring_turtles(self): '''Method for updating turtles' neighbours. Calls on each turtle's own method for updating neighbours.''' for turtle in self.turtles: turtle.get_neighbouring_patches()
class Report(Frame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.root = self.winfo_toplevel() self.root.title(" ".join((APPNAME, VERSION, "| Report"))) self.root.resizable(0, 0) self.items = None headers = ('Page', 'Rank', 'PageRank Value', 'Incoming') self.t = Scale(self, from_=0, to=1, label='n-th iteration', bd=1, width=7, orient='horizontal', command=self.__set_t) self.t.pack(fill='x') self.label = Label(self, anchor='e') self.label.pack(fill='x') self.tree = Treeview(self, columns=headers, show="headings", height=REPORT_HEIGHT) self.tree.column(0, anchor='center', width=55) self.tree.column(1, anchor='center', width=55) self.tree.column(2, width=175) self.tree.column(3, anchor='center', width=55) self.scroll = Scrollbar(self, command=self.tree.yview) self.scroll.pack(side='right', fill='y') self.tree.config(yscrollcommand=self.scroll.set) for col in headers: self.tree.heading(col, text=col.title()) self.root.master.focus_force() self.root.bind('<Key>', self.__keys) def __keys(self, event): if event.char == 'i': self.t.set(self.t.get() - 1) elif event.char == 'I': self.t.set(0) elif event.char == 'o': self.t.set(self.t.get() + 1) elif event.char == 'O': self.t.set(self.pagerank[1]) def __set_t(self, t=None): self.render(self.pagerank, self.edge_counts, self.d, self.e, t=int(t)) def render(self, pagerank, edge_counts, d, e, t=None): self.d, self.e = d, e self.edge_counts = edge_counts self.pagerank = pagerank if t is not None: pr = pagerank[0][t] else: self.t.config(command=None) self.t.config(to=self.pagerank[1]) self.t.set(self.pagerank[1]) self.t.config(command=self.__set_t) pr = pagerank[0][-1] label_text = '# of ranks:{0:>3} # of iterations:{1:>3}'.format( len(set(pr.values())), self.pagerank[1]) self.label.config(text=label_text) in_map = {k: 0 for k in pr.keys()} # incoming edges by nodes for (tail, head), n in edge_counts.items(): if tail is not head: in_map[head] += n get_rank = lambda k: sorted(pr.values())[::-1].index(pr[k]) + 1 data = tuple( (k, get_rank(k), pr[k], in_map[k]) for k in sorted(pr.keys())) if self.items: self.tree.delete(*self.items) self.items = [ self.tree.insert('', 'end', values=line) for line in data ] self.tree.pack(side='left', fill='y') #self.root.master.focus_force() def destroy(self): super().destroy() self.root.master.r_win = False self.root.master.windowsmenu.entryconfig(0, label='[ ] Report window') self.root.destroy()
class TelloUI: """Wrapper class to enable the GUI.""" def __init__(self, tello, outputpath): """ Initial all the element of the GUI,support by Tkinter :param tello: class interacts with the Tello drone. Raises: RuntimeError: If the Tello rejects the attempt to enter command mode. """ self.tello = tello # videostream device self.outputPath = outputpath # the path that save pictures created by clicking the takeSnapshot button self.frame = None # frame read from h264decoder and used for pose recognition self.thread = None # thread of the Tkinter mainloop self.stopEvent = None # control variables self.distance = 0.1 # default distance for 'move' cmd self.degree = 30 # default degree for 'cw' or 'ccw' cmd # if the flag is TRUE,the auto-takeoff thread will stop waiting for the response from tello self.quit_waiting_flag = False # initialize the root window and image panel self.root = tki.Tk() self.panel = None # create buttons self.btn_snapshot = tki.Button(self.root, text="Snapshot!", command=self.takeSnapshot) self.btn_snapshot.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_pause = tki.Button(self.root, text="Pause", relief="raised", command=self.pauseVideo) self.btn_pause.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_landing = tki.Button(self.root, text="Open Command Panel", relief="raised", command=self.openCmdWindow) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) # start a thread that constantly pools the video sensor for # the most recently read frame self.stopEvent = threading.Event() self.thread = threading.Thread(target=self.videoLoop, args=()) self.thread.start() # set a callback to handle when the window is closed self.root.wm_title("TELLO Controller") self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose) # the sending_command will send command to tello every 5 seconds self.sending_command_thread = threading.Thread( target=self._sendingCommand) def videoLoop(self): """ The mainloop thread of Tkinter Raises: RuntimeError: To get around a RunTime error that Tkinter throws due to threading. """ try: # start the thread that get GUI image and drwa skeleton time.sleep(0.5) self.sending_command_thread.start() while not self.stopEvent.is_set(): system = platform.system() # read the frame for GUI show self.frame = self.tello.read() if self.frame is None or self.frame.size == 0: continue # transfer the format from frame to image image = Image.fromarray(self.frame) # we found compatibility problem between Tkinter,PIL and Macos,and it will # sometimes result the very long preriod of the "ImageTk.PhotoImage" function, # so for Macos,we start a new thread to execute the _updateGUIImage function. if system == "Windows" or system == "Linux": self._updateGUIImage(image) else: thread_tmp = threading.Thread(target=self._updateGUIImage, args=(image, )) thread_tmp.start() time.sleep(0.03) except RuntimeError as e: print("[INFO] caught a RuntimeError") def _updateGUIImage(self, image): """ Main operation to initial the object of image,and update the GUI panel """ image = ImageTk.PhotoImage(image) # if the panel none ,we need to initial it if self.panel is None: self.panel = tki.Label(image=image) self.panel.image = image self.panel.pack(side="left", padx=10, pady=10) # otherwise, simply update the panel else: self.panel.configure(image=image) self.panel.image = image def _sendingCommand(self): """ start a while loop that sends 'command' to tello every 5 second """ while True: self.tello.send_command('command') time.sleep(5) def _setQuitWaitingFlag(self): """ set the variable as TRUE,it will stop computer waiting for response from tello """ self.quit_waiting_flag = True def openCmdWindow(self): """ open the cmd window and initial all the button and text """ panel = Toplevel(self.root) panel.wm_title("Command Panel") # create text input entry text0 = tki.Label( panel, text= 'This Controller map keyboard inputs to Tello control commands\n' 'Adjust the trackbar to reset distance and degree parameter', font='Helvetica 10 bold') text0.pack(side='top') text1 = tki.Label( panel, text='W - Move Tello Up\t\t\tArrow Up - Move Tello Forward\n' 'S - Move Tello Down\t\t\tArrow Down - Move Tello Backward\n' 'A - Rotate Tello Counter-Clockwise\tArrow Left - Move Tello Left\n' 'D - Rotate Tello Clockwise\t\tArrow Right - Move Tello Right', justify="left") text1.pack(side="top") self.btn_landing = tki.Button(panel, text="Land", relief="raised", command=self.telloLanding) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_takeoff = tki.Button(panel, text="Takeoff", relief="raised", command=self.telloTakeOff) self.btn_takeoff.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) # binding arrow keys to drone control self.tmp_f = tki.Frame(panel, width=100, height=2) self.tmp_f.bind('<KeyPress-w>', self.on_keypress_w) self.tmp_f.bind('<KeyPress-s>', self.on_keypress_s) self.tmp_f.bind('<KeyPress-a>', self.on_keypress_a) self.tmp_f.bind('<KeyPress-d>', self.on_keypress_d) self.tmp_f.bind('<KeyPress-Up>', self.on_keypress_up) self.tmp_f.bind('<KeyPress-Down>', self.on_keypress_down) self.tmp_f.bind('<KeyPress-Left>', self.on_keypress_left) self.tmp_f.bind('<KeyPress-Right>', self.on_keypress_right) self.tmp_f.pack(side="bottom") self.tmp_f.focus_set() self.btn_landing = tki.Button(panel, text="Flip", relief="raised", command=self.openFlipWindow) self.btn_landing.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.distance_bar = Scale(panel, from_=0.02, to=5, tickinterval=0.01, digits=3, label='Distance(m)', resolution=0.01) self.distance_bar.set(0.2) self.distance_bar.pack(side="left") self.btn_distance = tki.Button( panel, text="Reset Distance", relief="raised", command=self.updateDistancebar, ) self.btn_distance.pack(side="left", fill="both", expand="yes", padx=10, pady=5) self.degree_bar = Scale(panel, from_=1, to=360, tickinterval=10, label='Degree') self.degree_bar.set(30) self.degree_bar.pack(side="right") self.btn_distance = tki.Button(panel, text="Reset Degree", relief="raised", command=self.updateDegreebar) self.btn_distance.pack(side="right", fill="both", expand="yes", padx=10, pady=5) def openFlipWindow(self): """ open the flip window and initial all the button and text """ panel = Toplevel(self.root) panel.wm_title("Gesture Recognition") self.btn_flipl = tki.Button(panel, text="Flip Left", relief="raised", command=self.telloFlip_l) self.btn_flipl.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipr = tki.Button(panel, text="Flip Right", relief="raised", command=self.telloFlip_r) self.btn_flipr.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipf = tki.Button(panel, text="Flip Forward", relief="raised", command=self.telloFlip_f) self.btn_flipf.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) self.btn_flipb = tki.Button(panel, text="Flip Backward", relief="raised", command=self.telloFlip_b) self.btn_flipb.pack(side="bottom", fill="both", expand="yes", padx=10, pady=5) def takeSnapshot(self): """ save the current frame of the video as a jpg file and put it into outputpath """ # grab the current timestamp and use it to construct the filename ts = datetime.datetime.now() filename = "{}.jpg".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) p = os.path.sep.join((self.outputPath, filename)) # save the file cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR)) print("[INFO] saved {}".format(filename)) def pauseVideo(self): """ Toggle the freeze/unfreze of video """ if self.btn_pause.config('relief')[-1] == 'sunken': self.btn_pause.config(relief="raised") self.tello.video_freeze(False) else: self.btn_pause.config(relief="sunken") self.tello.video_freeze(True) def telloTakeOff(self): return self.tello.takeoff() def telloLanding(self): return self.tello.land() def telloFlip_l(self): return self.tello.flip('l') def telloFlip_r(self): return self.tello.flip('r') def telloFlip_f(self): return self.tello.flip('f') def telloFlip_b(self): return self.tello.flip('b') def telloCW(self, degree): return self.tello.rotate_cw(degree) def telloCCW(self, degree): return self.tello.rotate_ccw(degree) def telloMoveForward(self, distance): return self.tello.move_forward(distance) def telloMoveBackward(self, distance): return self.tello.move_backward(distance) def telloMoveLeft(self, distance): return self.tello.move_left(distance) def telloMoveRight(self, distance): return self.tello.move_right(distance) def telloUp(self, dist): return self.tello.move_up(dist) def telloDown(self, dist): return self.tello.move_down(dist) def updateTrackBar(self): self.my_tello_hand.setThr(self.hand_thr_bar.get()) def updateDistancebar(self): self.distance = self.distance_bar.get() print 'reset distance to %.1f' % self.distance def updateDegreebar(self): self.degree = self.degree_bar.get() print 'reset distance to %d' % self.degree def on_keypress_w(self, event): print "up %d m" % self.distance self.telloUp(self.distance) def on_keypress_s(self, event): print "down %d m" % self.distance self.telloDown(self.distance) def on_keypress_a(self, event): print "ccw %d degree" % self.degree self.tello.rotate_ccw(self.degree) def on_keypress_d(self, event): print "cw %d m" % self.degree self.tello.rotate_cw(self.degree) def on_keypress_up(self, event): print "forward %d m" % self.distance self.telloMoveForward(self.distance) def on_keypress_down(self, event): print "backward %d m" % self.distance self.telloMoveBackward(self.distance) def on_keypress_left(self, event): print "left %d m" % self.distance self.telloMoveLeft(self.distance) def on_keypress_right(self, event): print "right %d m" % self.distance self.telloMoveRight(self.distance) def on_keypress_enter(self, event): if self.frame is not None: self.registerFace() self.tmp_f.focus_set() def onClose(self): """ set the stop event, cleanup the camera, and allow the rest of the quit process to continue """ print("[INFO] closing...") self.stopEvent.set() del self.tello self.root.quit()
class Visualiser(object): ''' Generic Offline Visualiser. Subclasses need to be used that specify how to handle a data source. ''' ### Public functions ### def __init__(self, title="Visualisation", width=400, height=400, recording=False, recordPattern=None, paused=False, source=None): ''' Constructor. Params: title: string - Title of the visualisation window width: int - Width of the visualisation window height: int - Height of the visualisation window recording: boolean - Start with recording enabled? recordPattern: string - Pattern for recorded images, e.g., cylinders%05g.png paused: boolean - Start with playback paused? source:- The data source to read. What is required here varies by visualiser. ''' # Visualisation options self.vis_features = [] self.vis_frame = 0 self.vis_frameStep = 1 self.vis_jumping = False self.vis_recording = recording self.vis_recordPattern = recordPattern self.vis_paused = paused self.vis_source = source # VTK structures self.vtk_cells = vtkCellArray() self.vtk_renderer = vtkRenderer() # Tk structures self.tk_root = Tk() self.tk_root.title(title) self.tk_root.grid_rowconfigure(0, weight=1) self.tk_root.grid_columnconfigure(0, weight=3) self.tk_root.bind('<Destroy>', self.destroyed) if not self.vis_paused: self.tk_root.after(100, self.animate) self.tk_renderWidget = vtkTkRenderWidget(self.tk_root, width=width, height=height) self.tk_renderWidget.grid(row=0, column=0, sticky=N+S+E+W) self.tk_renderWidget.GetRenderWindow().AddRenderer(self.vtk_renderer) self.tk_featureFrame = Frame(self.tk_root) self.tk_featureFrame.grid(row=0, column=1, rowspan=2) Label(self.tk_featureFrame, text='Features:').grid(row=0, column=0) self.tk_controlFrame = Frame(self.tk_root) self.tk_controlFrame.grid(row=1, column=0) self.tk_quit = Button(self.tk_controlFrame, text="Quit", command=self.shutdown) self.tk_quit.grid(row=0, column=0, columnspan=2) def pause(): if self.vis_paused: self.tk_pause.config(text='Pause') self.tk_root.after(100, self.animate) else: self.tk_pause.config(text='Resume') self.vis_paused ^= True self.tk_pause = Button(self.tk_controlFrame, text="Pause", command=pause) self.tk_pause.grid(row=0, column=2, columnspan=2) if self.vis_recordPattern is not None: def record(): if self.vis_recording: self.tk_record.config(text='Start Recording') else: self.tk_record.config(text='Stop Recording') self.vis_recording ^= True self.tk_record = Button(self.tk_controlFrame, text="Start Recording", command=record) self.tk_record.grid(row=0, column=4, columnspan=2) if self.vis_recording: self.tk_record.config(text="Stop Recording") def make_seek_button(label, column, frame): def jump(): self.jumpTo(frame) b = Button(self.tk_controlFrame, text=label, command=jump) b.grid(row=1, column=column, sticky=W+E) return b self.tk_seek_start = make_seek_button("|<", 0, 0) self.tk_seek_back10 = make_seek_button("<<", 1, lambda: self.vis_frame - 10) self.tk_seek_back1 = make_seek_button("<", 2, lambda: self.vis_frame - 1) self.tk_seek_forward1 = make_seek_button(">", 3, lambda: self.vis_frame + 1) self.tk_seek_forward10 = make_seek_button(">>", 4, lambda: self.vis_frame + 10) self.tk_seek_end = make_seek_button(">|", 5, self.getMaxFrameNumber) Label(self.tk_controlFrame, text='Frame').grid(row=2, column=0, sticky=W+E) def changeFrame(frame): if not self.vis_jumping: self.vis_jumping = True self.jumpTo(self.tk_frame.get()) self.vis_jumping = False self.tk_frame = Scale(self.tk_controlFrame, command=changeFrame, from_=0, to=0, orient=HORIZONTAL) self.tk_frame.grid(row=2, column=1, columnspan=2, sticky=W+E) Label(self.tk_controlFrame, text='Step').grid(row=2, column=3, sticky=W+E) def changeFrameStep(step): self.vis_frameStep = int(step) self.tk_frameStep = Scale(self.tk_controlFrame, command=changeFrameStep, from_=1, to=1, orient=HORIZONTAL) self.tk_frameStep.grid(row=2, column=4, columnspan=2, sticky=W+E) self.setupGrid() def add_feature(self, feature): '''Add a feature to this visualiser''' self.vis_features.append(feature) feature.button(self.tk_featureFrame).grid(row=len(self.vis_features), column=0, sticky=W+E) feature.visualiser = self def run(self): '''Start the visualiser''' self.redraw() self.tk_root.mainloop() ### Private funcitions ### def resetSliders(self): ''' Recalculate the upper bound on the frame and frameStep sliders. ''' maxFrame = self.getMaxFrameNumber() self.tk_frame.config(to=maxFrame) self.tk_frameStep.config(to=maxFrame) def jumpTo(self, frame): ''' Jump to a given frame. If frame is a function, jump to the return value of frame(). ''' oldFrame = self.vis_frame if hasattr(frame, '__call__'): self.vis_frame = frame() else: self.vis_frame = frame maxFrame = self.getMaxFrameNumber() if self.vis_frame < 0: self.vis_frame = 0 elif self.vis_frame > maxFrame: self.vis_frame = maxFrame self.vis_paused = True self.tk_pause.config(text='Resume') self.tk_frame.set(self.vis_frame) self.redraw(oldFrame != self.vis_frame) def redraw(self, update=False): self.resetSliders() for feature in [ f for f in self.vis_features if not f.dynamic ]: feature.draw(self.vtk_renderer) if update: for feature in [ f for f in self.vis_features if f.dynamic]: f.redraw(self.vtk_renderer) self.tk_renderWidget.GetRenderWindow().Render() self.tk_root.update_idletasks() ### Gui events ### def destroyed(self, event): if event.widget == self.tk_root: self.shutdown() def shutdown(self): self.tk_root.withdraw() self.tk_root.destroy() def animate(self): if not self.vis_paused: self.jumpTo(self.vis_frame + self.vis_frameStep) if self.vis_recording and self.vis_recordPattern is not None: self.save_image() self.tk_root.after(100, self.animate) def save_image(self): extmap = {'.jpg' : vtkJPEGWriter, '.jpeg' : vtkJPEGWriter, '.png' : vtkPNGWriter, '.pnm' : vtkPNMWriter} _, ext = splitext(self.vis_recordPattern) try: writer = extmap[ext.lower()]() except KeyError: print('ERROR: Can\'t handle %s extension. Recording disabled.' % ext) self.vis_recordPattern = None return win = self.vtk_renderer.GetRenderWindow() w2i = vtkWindowToImageFilter() w2i.SetInput(win) w2i.Update() writer.SetInput(w2i.GetOutput()) writer.SetFileName(self.vis_recordPattern % self.vis_frame) win.Render() writer.Write() ### Things subclasses need to override ### def setupGrid(self): ''' Populate the vtkCellArray instance at self.vtk_cells. Subclasses are required to override this function to read from their source as appropriate. ''' raise NotImplementedError('Subclass needs to override Visualiser::setupGrid!') def getMaxFrameNumber(self): ''' Return the maximum frame number. This will need to be defined by a subclass. ''' raise NotImplementedError('Subclass needs to override Visualiser::getMaxFrameNumber!') def getQuantityPoints(self, quantityName, dynamic=True, frameNumber=0): ''' Return the points of a quantity at a given frame as a list [float]. Subclasses need to override this. ''' raise NotImplementedError('Subclass needs to override Visualiser::getQuantityPoints!') def getQuantityDict(self): ''' Return the values of all quantities at a given time as a dictionary. Sublclasses need to override this. ''' raise NotImplementedError('Subclass needs to override Visualiser::getQuantityDict!')
class AdjustFrame(Toplevel): def __init__(self, master=None): Toplevel.__init__(self, master=master) self.brightness_value = 0 self.previous_brightness_value = 0 self.original_image = self.master.processed_image self.processing_image = self.master.processed_image self.brightness_label = Label(self, text="Brightness") self.brightness_scale = Scale(self, from_=0, to_=2, length=250, resolution=0.1, orient=HORIZONTAL) self.r_label = Label(self, text="R") self.r_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.g_label = Label(self, text="G") self.g_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.b_label = Label(self, text="B") self.b_scale = Scale(self, from_=-100, to_=100, length=250, resolution=1, orient=HORIZONTAL) self.apply_button = Button(self, text="Apply") self.preview_button = Button(self, text="Preview") self.cancel_button = Button(self, text="Cancel") self.brightness_scale.set(1) self.apply_button.bind("<ButtonRelease>", self.apply_button_released) self.preview_button.bind("<ButtonRelease>", self.show_button_released) self.cancel_button.bind("<ButtonRelease>", self.cancel_button_released) self.brightness_label.pack() self.brightness_scale.pack() self.r_label.pack() self.r_scale.pack() self.g_label.pack() self.g_scale.pack() self.b_label.pack() self.b_scale.pack() self.cancel_button.pack(side=RIGHT) self.preview_button.pack(side=RIGHT) self.apply_button.pack() def apply_button_released(self, event): self.master.processed_image = self.processing_image self.close() def show_button_released(self, event): self.processing_image = cv2.convertScaleAbs( self.original_image, alpha=self.brightness_scale.get()) b, g, r = cv2.split(self.processing_image) for b_value in b: cv2.add(b_value, self.b_scale.get(), b_value) for g_value in g: cv2.add(g_value, self.g_scale.get(), g_value) for r_value in r: cv2.add(r_value, self.r_scale.get(), r_value) self.processing_image = cv2.merge((b, g, r)) self.show_image(self.processing_image) def cancel_button_released(self, event): self.close() def show_image(self, img=None): self.master.image_viewer.show_image(img=img) def close(self): self.show_image() self.destroy()
class ColoredBar(tk.Frame): RANGE = [0, 1000] def __init__(self, *args): super().__init__(*args) # firmware value self.firmware_value = Label( self, text="(Pad's firmware sens)", justify="center" ) self.firmware_value.pack(expand=True, fill="both") # current value self.canvas = Canvas(self, bd=1, relief="solid", width=98, height=15) self.canvas.pack(expand=True, fill="both") self.critical = 800 # frame the slider and entry together frame = tk.Frame(self, highlightthickness=3, relief=tk.RIDGE, bg="black") frame.pack(expand=True, fill="both") self.slider = Scale( frame, from_=0, to=1000, orient="horizontal", command=self.set_critical, showvalue=0, ) self.slider.pack(expand=True, fill="both") self.entry = Entry(frame, justify="center") self.entry.bind("<FocusOut>", self.set_critical_entry) self.entry.bind("<Return>", self.set_critical_entry) self.entry.pack(expand=True, fill="both") self.valid_range = self.RANGE def set_firmware_value(self, value): self.firmware_value["text"] = value def set_range(self, valid_range): """valid range for raw and cutoff""" self.valid_range = valid_range def set_critical_entry(self, *args): value = self.entry.get() try: value = int(value) value = clamp(value, *self.valid_range) except: value = self.critical raise self.set_critical(value) def set_critical(self, value): self.critical = int(value) # update entries text self.entry.delete(0, tk.END) self.entry.insert(0, str(value)) self.slider.set(value) # debug only: # self.set_value(value) def set_value(self, value): """ sets the raw value """ value = float(value) self.canvas.delete(tk.ALL) width, height = self.canvas.winfo_width(), self.canvas.winfo_height() perc = float(value) / 1000.0 x_right = lerp(SLIDER_WIDTH, width - SLIDER_WIDTH, perc) text_anchor = "w" if value < 500 else "e" if value < self.critical: fill = "yellow" else: fill = "green" self.canvas.create_rectangle(SLIDER_WIDTH, 5, x_right, height - 5, fill=fill) self.canvas.create_text( x_right + 5, height / 2, text=str(int(value)), anchor=text_anchor )
class GUI(): def __init__(self): self.root = ThemedTk(theme="radiance") INIT_WIDTH, INIT_HEIGHT = self.root.winfo_screenwidth( ), self.root.winfo_screenheight() boldStyle = ttk.Style() boldStyle.configure("Bold.TButton", font=('Sans', '12', 'bold')) #icon_loc = os.path.join(os.getcwd(),ICON_NAME) #img = ImageTk.PhotoImage(master = self.root, file=icon_loc) #self.root.wm_iconbitmap(img) #self.root.ttk.call('wm', 'iconphoto', self.root._w, img) self.root.title("Form Labeller") self.root.maxsize(INIT_WIDTH, INIT_HEIGHT) self.supported_formats = SUPPORTED_FORMATS self.left_frame = Frame(self.root, width=BUTTON_WIDTH) self.top_frame1 = Frame(self.left_frame, width=BUTTON_WIDTH, height=int(INIT_HEIGHT / 2)) self.top_frame = Frame(self.left_frame, width=BUTTON_WIDTH, height=INIT_HEIGHT - int(INIT_HEIGHT / 2)) self.bottom_frame = Frame(self.root, width=INIT_WIDTH - BUTTON_WIDTH) self.load_image_directory_button = Button(self.top_frame1, text='Open Folder', command=self.load_directory, width=int(BUTTON_WIDTH), style="Bold.TButton") self.load_image_directory_button.grid(row=OPEN_FOLDER_ROW, columnspan=2, sticky=tk.W + tk.E) self.prev_img_button = Button(self.top_frame1, text='← Prev', command=self.previous_img, state=tk.DISABLED, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.prev_img_button.grid(row=PREV_ROW, column=0, sticky=tk.W + tk.E) self.next_img_button = Button(self.top_frame1, text='Next → ', command=self.next_img, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.next_img_button.grid(row=NEXT_COL, column=1, sticky=tk.W + tk.E) self.save_image_button = Button(self.top_frame1, text='Save ', command=self.saver, width=int(BUTTON_WIDTH), style="Bold.TButton") self.save_image_button.grid(row=SAVE_ROW, columnspan=2, sticky=tk.W + tk.E) self.delete_poly_button = Button(self.top_frame, text='Delete Selected', command=self.delete_selected, width=int(BUTTON_WIDTH), style="Bold.TButton") self.delete_poly_button.grid(row=DEL_SELECTED_ROW, columnspan=2, sticky=tk.W + tk.E) self.type_choices = TYPE_CHOICES self.variable = StringVar(self.top_frame) self.variable.set(self.type_choices[0]) self.type_options = OptionMenu(self.top_frame, self.variable, *self.type_choices, style="Bold.TButton") self.type_options.config(width=int(BUTTON_WIDTH / 2)) self.type_options.grid(row=DROP_DOWN_ROW, column=0) self.save_type_button = Button(self.top_frame, text='Save Type', command=self.save_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.save_type_button.grid(row=SAVE_TYPE_ROW, column=1, sticky=tk.W + tk.E) self.deselect_all_button = Button(self.top_frame, text='Deselect All', command=self.deselect_all, width=BUTTON_WIDTH, style="Bold.TButton") self.deselect_all_button.grid(row=DESELECT_ALL_ROW, columnspan=2, sticky=tk.W + tk.E) self.select_all_button = Button(self.top_frame, text='Select All', command=self.select_all, width=BUTTON_WIDTH, style="Bold.TButton") self.select_all_button.grid(row=SELECT_ALL_ROW, columnspan=2, sticky=tk.W + tk.E) self.draw_poly_button = Button(self.top_frame, text='Draw Poly', command=self.draw_poly_func, width=BUTTON_WIDTH, style="Bold.TButton") self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.draw_rect_button = Button(self.top_frame, text='Draw Rectangle', command=self.draw_rect_func, width=BUTTON_WIDTH, style="Bold.TButton") self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) self.delete_all_button = Button(self.top_frame, text='Delete All', command=self.delete_all, width=BUTTON_WIDTH, style="Bold.TButton") self.save_poly_button = Button(self.top_frame, text='Save Poly', command=self.save_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.discard_poly_button = Button(self.top_frame, text='Discard Poly', command=self.discard_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.save_rect_button = Button(self.top_frame, text='Save Rect', command=self.save_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.discard_rect_button = Button(self.top_frame, text='Discard Rect', command=self.discard_drawing, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.show_type_button = Button(self.top_frame, text='Show Type', command=self.show_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.show_type_button.grid(row=SHOW_TYPE_ROW, column=0, columnspan=1, sticky=tk.W + tk.E) self.hide_type_button = Button(self.top_frame, text='Hide Type', command=self.hide_type, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.hide_type_button.grid(row=HIDE_TYPE_ROW, columnspan=1, column=1, sticky=tk.W + tk.E) self.make_tight_button = Button(self.top_frame, text='Make Tight', command=self.make_tight, width=int(BUTTON_WIDTH / 2), style="Bold.TButton") self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, column=0, sticky=tk.W + tk.E) self.threshold_scale = Scale(self.top_frame, from_=0, to=255, orient=HORIZONTAL, width=int(BUTTON_WIDTH / 2), label="Binary Threshold") self.threshold_scale.set(128) self.threshold_scale.grid(row=THRESHOLD_ROW, columnspan=2, column=0, sticky=tk.W + tk.E) self.tight_save_button = Button(self.top_frame, text='Accept Tight', command=self.save_tight) self.tight_discard_button = Button(self.top_frame, text='Discard Tight', command=self.discard_tight) self.canvas = Canvas(self.bottom_frame, width=INIT_WIDTH - BUTTON_WIDTH, height=INIT_HEIGHT, borderwidth=1) self.image_name = None #self.image_path = os.path.join('imgs','img1.jpg') self.image_dir = None self.images_in_dir = None self.curr_idx = None self.img_cnv = None #self.img_cnv = ImageOnCanvas(self.root,self.canvas,self.image_path) self.drawing_obj = None self.tight_box_obj = None self.left_frame.pack(side=tk.LEFT) self.top_frame1.pack(side=tk.TOP) self.top_frame.pack(side=tk.BOTTOM) self.bottom_frame.pack(side=tk.LEFT) self.canvas.pack() self.hide_buttons() self.load_image_directory_button.config(state="normal") def save_tight(self): self.tight_box_obj.save_tight_box() self.tight_save_button.grid_forget() self.tight_discard_button.grid_forget() self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, sticky=tk.W + tk.E) self.show_buttons() self.tight_box_obj = None def discard_tight(self): self.tight_box_obj.discard_tight_box() self.tight_save_button.grid_forget() self.tight_discard_button.grid_forget() self.make_tight_button.grid(row=MAKE_TIGHT_ROW, columnspan=2, sticky=tk.W + tk.E) self.show_buttons() self.tight_box_obj = None def show_type(self): for poly in self.img_cnv.polygons: if poly.select_poly: poly.show_type() def hide_type(self): for poly in self.img_cnv.polygons: poly.unshow_type() def hide_buttons(self): self.load_image_directory_button.config(state=tk.DISABLED) self.save_image_button.config(state=tk.DISABLED) self.delete_poly_button.config(state=tk.DISABLED) self.save_type_button.config(state=tk.DISABLED) self.deselect_all_button.config(state=tk.DISABLED) self.select_all_button.config(state=tk.DISABLED) self.delete_all_button.config(state=tk.DISABLED) self.show_type_button.config(state=tk.DISABLED) self.hide_type_button.config(state=tk.DISABLED) self.make_tight_button.config(state=tk.DISABLED) def show_buttons(self): self.load_image_directory_button.config(state="normal") self.save_image_button.config(state="normal") self.delete_poly_button.config(state="normal") self.save_type_button.config(state="normal") self.deselect_all_button.config(state="normal") self.select_all_button.config(state="normal") self.delete_all_button.config(state="normal") self.show_type_button.config(state="normal") self.hide_type_button.config(state="normal") self.draw_poly_button.config(state="normal") self.draw_rect_button.config(state="normal") self.make_tight_button.config(state="normal") def select_all(self): for poly in self.img_cnv.polygons: poly.select_polygon() def deselect_all(self): self.hide_type() for poly in self.img_cnv.polygons: poly.deselect_poly() def delete_all(self): result = messagebox.askyesno("Confirm Delete All", "Delete All Annotations?") if not result: return self.select_all() self.delete_selected() #self.img_cnv.polygons_mutex.acquire() #for poly in self.img_cnv.polygons: # poly.delete_self() #self.img_cnv.polygons_mutex.release() def save_type(self): selected_option = self.variable.get() self.img_cnv.polygons_mutex.acquire() for poly in self.img_cnv.polygons: if poly.select_poly == True: if selected_option == "None": poly.poly_type = None else: poly.poly_type = selected_option #poly.unshow_type() #poly.show_type() self.img_cnv.polygons_mutex.release() self.variable.set(self.type_choices[0]) #self.deselect_all() def load_new_img(self): self.canvas.delete('all') self.img_cnv = None path = os.path.join(self.image_dir, self.image_name) self.img_cnv = ImageOnCanvas(self.root, self.canvas, path) logger("LOADED: " + self.img_cnv.image_path) def load_directory(self): while True: selection = filedialog.askdirectory() if selection == () or selection == '': return self.root.directory = selection self.image_dir = self.root.directory file_names = os.listdir(self.image_dir) self.images_in_dir = [] self.curr_idx = None self.image_name = None for name in file_names: if name.split('.')[-1] in self.supported_formats: self.images_in_dir.append(name) if len(self.images_in_dir) == 0: self.pop_up("No supported images in the selected directory") else: break self.show_buttons() self.next_img() def pop_up(self, text): top = Toplevel() top.title("ERROR") msg = Message(top, text=text) msg.pack() button = Button(top, text="Dismiss", command=top.destroy) button.pack() def next_img(self): if self.curr_idx == None: self.curr_idx = -1 self.curr_idx = self.curr_idx + 1 if self.curr_idx >= len(self.images_in_dir): self.pop_up("Done with Images in this directory") self.curr_idx = self.curr_idx - 1 return if self.curr_idx > 0: self.prev_img_button.config(state="normal") self.image_name = self.images_in_dir[self.curr_idx] self.load_new_img() self.root.title("Form Labeller - " + self.image_name + "(" + str(self.curr_idx + 1) + "/" + str(len(self.images_in_dir)) + ")") def previous_img(self): if self.curr_idx == 1: self.curr_idx = -1 self.prev_img_button.config(state=tk.DISABLED) else: self.curr_idx = self.curr_idx - 2 self.next_img() def delete_selected(self): to_be_deleted = [] for i, poly in enumerate(self.img_cnv.polygons): if poly.select_poly == True: poly.delete_self() to_be_deleted.append(i) j = 0 for idx in to_be_deleted: self.img_cnv.polygons.pop(idx - j) self.img_cnv.bbs.pop(idx - j) self.img_cnv.poly_type.pop(idx - j) j = j + 1 def start_gui(self): self.root.mainloop() def saver(self): logger("Saving: " + self.img_cnv.image_path) self.save_image_button.config(state=tk.DISABLED) self.img_cnv.save_json(self.root.directory) self.save_image_button.config(state="normal") def draw_poly_func(self): self.deselect_all() self.img_cnv.drawing_polygon = True self.draw_poly_button.grid_forget() self.save_poly_button.grid(row=DRAW_POLY_ROW, column=0, sticky=tk.W + tk.E) self.discard_poly_button.grid(row=DRAW_POLY_ROW, column=1, sticky=tk.W + tk.E) self.hide_buttons() self.draw_rect_button.config(state=tk.DISABLED) self.drawing_obj = DrawPoly(self.bottom_frame, self.canvas, self.img_cnv, RADIUS) def draw_rect_func(self): self.deselect_all() self.img_cnv.drawing_polygon = True self.draw_rect_button.grid_forget() self.save_rect_button.grid(row=DRAW_RECT_ROW, column=0, sticky=tk.W + tk.E) self.discard_rect_button.grid(row=DRAW_RECT_ROW, column=1, sticky=tk.W + tk.E) self.hide_buttons() self.draw_poly_button.config(state=tk.DISABLED) self.drawing_obj = DrawRect(self.bottom_frame, self.canvas, self.img_cnv, RADIUS) def save_drawing(self): self.show_buttons() self.img_cnv.drawing_polygon = False new_poly_pts = self.drawing_obj.pt_coords print("Trying to save polygon with pts:", str(new_poly_pts)) for pt in self.drawing_obj.points: self.canvas.delete(pt) if self.img_cnv.scale_factor != None: for i in range(len(new_poly_pts)): for j in range(2): new_poly_pts[i][ j] = new_poly_pts[i][j] / self.img_cnv.scale_factor self.img_cnv.add_poly(new_poly_pts) #self.img_cnv.bbs.append(new_poly_pts) #self.img_cnv.draw_bbs([self.img_cnv.bbs[-1]]) #debug (1, str(type(self.drawing_obj))) if isinstance(self.drawing_obj, DrawRect): self.save_rect_button.grid_forget() self.discard_rect_button.grid_forget() self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) elif isinstance(self.drawing_obj, DrawPoly): self.save_poly_button.grid_forget() self.discard_poly_button.grid_forget() self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.drawing_obj.delete_self() self.drawing_obj = None def discard_drawing(self): self.show_buttons() self.img_cnv.drawing_polygon = False #for pt in self.drawing_obj.points: # self.canvas.delete(pt) self.drawing_obj.delete_self() if isinstance(self.drawing_obj, DrawRect): self.save_rect_button.grid_forget() self.discard_rect_button.grid_forget() self.draw_rect_button.grid(row=DRAW_RECT_ROW, columnspan=2, sticky=tk.W + tk.E) elif isinstance(self.drawing_obj, DrawPoly): self.save_poly_button.grid_forget() self.discard_poly_button.grid_forget() self.draw_poly_button.grid(row=DRAW_POLY_ROW, columnspan=2, sticky=tk.W + tk.E) self.drawing_obj = None def make_tight(self): self.hide_buttons() self.tight_box_obj = TightBox(self.root, self.img_cnv, self.threshold_scale.get()) self.tight_box_obj.tight_box() self.make_tight_button.grid_forget() self.tight_save_button.grid(row=MAKE_TIGHT_ROW, column=0, columnspan=1, sticky=tk.W + tk.E) self.tight_discard_button.grid(row=MAKE_TIGHT_ROW, column=1, columnspan=1, sticky=tk.W + tk.E)
for t in range(len(hsv_types)): sliders[hsv_types[t]] = [] for i in range(3): if t == 0: Label(window, text=hsv_labels[i], font=("Arial Bold", 20)).grid(column=init_col, row=current_row + i) slider = Scale(window, from_=0, to=255, orient=HORIZONTAL, command=gui.update_factory(hsv_types[t], i), cursor='hand2') slider.set(gui.params[hsv_types[t]][i]) slider.grid(column=t + init_col + 1, row=current_row + i) sliders[hsv_types[t]].append(slider) current_row += 3 # Luminosity sliders lum_types = ["lum_lower", "lum_upper"] Label(window, text="Luminosity", font=("Arial Bold", 20)).grid(column=init_col, row=current_row) for t in range(len(lum_types)): slider = Scale(window, from_=0, to=255, orient=HORIZONTAL, command=gui.update_factory(lum_types[t]), cursor='hand2')
def __init__(self, parent, data, stepname): super().__init__(parent, data, stepname) lbl1 = Label( self, text= 'Click on each scale at the point that best indicates your experience of the task' ) lbl1.grid(row=1, column=1) lbl2 = Label(self, text="(1=extremely low,5=extremely high)") lbl2.grid(row=2, column=1) ########################### lbl3 = Label( self, text= 'Mental demand: How much mental and perceptual activity was required?' ) lbl3.grid(row=3, column=1) mentalscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updatemental) mentalscale.set(5) mentalscale.grid(row=3, column=2) self.data[self.stepname]["mental demand weight"] = mentalscale.get() ########### lbl4 = Label( self, text='Physical demand: How much physical activity was required?') lbl4.grid(row=4, column=1) physicalscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updatephysical) physicalscale.set(5) physicalscale.grid(row=4, column=2) self.data[ self.stepname]["physical demand weight"] = physicalscale.get() ########### ########### lbl5 = Label( self, text= 'Temporal demand: How much time pressure did you feel due to the rate of pace at which the tasks or task elements occurred?' ) lbl5.grid(row=5, column=1) temporalscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updatetemporal) temporalscale.set(5) temporalscale.grid(row=5, column=2) self.data[ self.stepname]["temporal demand weight"] = temporalscale.get() ########### ########### lbl6 = Label( self, text= 'Performance: How successful do you think you were in accomplishing the goals?' ) lbl6.grid(row=6, column=1) perforscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updateperformance) perforscale.set(5) perforscale.grid(row=6, column=2) self.data[self.stepname]["performance weight"] = perforscale.get() ########### ########### lbl7 = Label( self, text= 'Effort: How hard did you have to work (mentally and physically) to accomplish your level of performance?' ) lbl7.grid(row=7, column=1) effortscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updateeffort) effortscale.set(5) effortscale.grid(row=7, column=2) self.data[self.stepname]["effort weight"] = effortscale.get() ########### ########### lbl8 = Label( self, text= 'Frustration: How insecure, discouraged, irritated, stressed,and annoyed were you?' ) lbl8.grid(row=8, column=1) frustrationscale = Scale(self, from_=1, to=10, length=200, tickinterval=1, orient=HORIZONTAL, command=self.updatefrustration) frustrationscale.set(5) frustrationscale.grid(row=8, column=2) self.data[self.stepname]["frustration weight"] = frustrationscale.get() ########### self.data[self.stepname]["choose mental times"] = 0 self.data[self.stepname]["choose physical times"] = 0 self.data[self.stepname]["choose temporal times"] = 0 self.data[self.stepname]["choose performance times"] = 0 self.data[self.stepname]["choose effort times"] = 0 self.data[self.stepname]["choose frustration times"] = 0
def initui(self): self.parent.title("Light pollution map") self.style = Style() self.style.theme_use("alt") self.grid(row=0, column=0) padding = {'padx':'5', 'pady':'5'} big_heading_font = ("Arial", 14, 'bold') small_heading_font = ("Arial", 10, 'bold') # Create frames. # There are three frames for settings - preprocessing, convolve, and contour. # Each also has an image frame underneath it. # Layout is as follows: # # -------------------------------------------------------------------------- # | | | | | # | | | | | # | import_body | process_body | contour_body | export_body | # | | | | | # | | | | | # -------------------------------------------------------------------------- # Settings frames top = self.winfo_toplevel() top.rowconfigure(0, weight=1) top.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=1) self.columnconfigure(3, weight=1) import_body = Frame(self, relief=RAISED, borderwidth=1) import_body.grid(row=0, column=0, sticky=N+S+E+W) process_body = Frame(self, relief=RAISED, borderwidth=1) process_body.grid(row=0, column=1, sticky=N+S+E+W) contour_body = Frame(self, relief=RAISED, borderwidth=1) contour_body.grid(row=0, column=2, sticky=N+S+E+W) export_body = Frame(self, relief=RAISED, borderwidth=1) export_body.grid(row=0, column=3, sticky=N+S+E+W) # ============================================================================================================= # # Contents of load_image_frame # # ============================================================================================================= # Heading processing_frame_header = Label(import_body, text="Import", font=big_heading_font) processing_frame_header.grid(row=0, column=0, sticky=N, **padding) filename_variable = StringVar() # Import image import_canvas = Canvas(import_body, width=canvas_size, height=canvas_size, background='black') import_canvas.grid(row=1, column=0, sticky=N, **padding) # Load file method def choosefile(): filename_variable.set(filedialog.askopenfilename(parent=import_body)) image = Image.open(filename_variable.get()) thumbnail = create_thumbnail(image, canvas_size) import_canvas.create_image(0, 0, image=thumbnail, anchor=NW) load_image_button = Button(import_body, text="Import image", command=choosefile) load_image_button.grid(row=2, column=0, columnspan=2, sticky=E+W+S, **padding) import_body.rowconfigure(2, weight=1) # ============================================================================================================= # # Contents of processing_frame # # ============================================================================================================= processing_frame_header = Label(process_body, text="Process", font=big_heading_font) processing_frame_header.grid(row=0, column=0, columnspan=2, sticky=N, **padding) clipping_variable = IntVar() constants_label = Label(process_body, text="Clipping", font=("Arial", 10, 'bold')) constants_label.grid(row=1, column=0, sticky=E, **padding) clipping_label = Label(process_body, text="Remove pixels with \n brightness under") clipping_label.grid(row=2, column=0, sticky=E, **padding) clipping_entry = Entry(process_body, textvariable=clipping_variable, width=4) clipping_entry.grid(row=2, column=1, sticky=W, **padding) clipping_variable.set(value=default_clipping_value) convolve_header = Label(process_body, text="Kernel", font=small_heading_font) convolve_header.grid(row=4, column=0, sticky=E, **padding) kernel_size_variable = IntVar() kernel_size_label = Label(process_body, text="Convolve kernel size", justify=RIGHT) kernel_size_label.grid(row=5, column=0, sticky=E, **padding) kernel_size_entry = Entry(process_body, textvariable=kernel_size_variable, width=4) kernel_size_entry.grid(row=5, column=1, sticky=W, **padding) kernel_size_variable.set(value=default_kernel_size) # Constants for convolve equation constants_label = Label(process_body, text="Falloff", font=("Arial", 10, 'bold')) constants_label.grid(row=6, column=0, sticky=E, **padding) constant_a_label = Label(process_body, text="Constant A:") constant_b_label = Label(process_body, text="Constant B:") constant_c_label = Label(process_body, text="Constant C:") constant_a_label.grid(row=7, column=0, sticky=E, **padding) constant_b_label.grid(row=8, column=0, sticky=E, **padding) constant_c_label.grid(row=9, column=0, sticky=E, **padding) constant_a_variable = DoubleVar() constant_b_variable = DoubleVar() constant_c_variable = DoubleVar() constant_a_entry = Entry(process_body, textvariable=constant_a_variable, width=4) constant_b_entry = Entry(process_body, textvariable=constant_b_variable, width=4) constant_c_entry = Entry(process_body, textvariable=constant_c_variable, width=4) constant_a_variable.set(default_constant_a) constant_b_variable.set(default_constant_b) constant_c_variable.set(default_constant_c) constant_a_entry.grid(row=7, column=1, **padding) constant_b_entry.grid(row=8, column=1, **padding) constant_c_entry.grid(row=9, column=1, **padding) constants_note = Label(process_body, text="Falloff equation is (Ax^B)-C", font=("Arial", 9)) constants_note.grid(row=10, column=0, columnspan=2, sticky=E, **padding) # Start button! def process(): print("Filename was " + filename_variable.get()) image_data = process_image(filename=filename_variable.get(), kernel_size=kernel_size_variable.get(), clipping_value=clipping_variable.get(), constant_a=constant_a_variable.get(), constant_b=constant_b_variable.get(), constant_c=constant_c_variable.get() ) image_data = Image.open("processed_image.png") thumbnail = create_thumbnail(image_data, canvas_size) export_canvas.create_image(0, 0, image=thumbnail, anchor=NW) start_button = Button(process_body, text="Process image", command=process) start_button.grid(row=11, column=0, columnspan=3, sticky=E+W+S, **padding) process_body.rowconfigure(11, weight=1) # ============================================================================================================= # # Contents of contour_frame # # ============================================================================================================= contour_header = Label(contour_body, text="Contour", font=big_heading_font) contour_header.grid(row=0, column=0, sticky=S, columnspan=2, **padding) contour_note = Label(contour_body, text="(optional)") contour_note.grid(row=1, column=0, sticky=S, columnspan=2) scale_options = {"width":"5", "length":"150"} slider_padding = {"padx":"2", "pady":"0"} scale_list = [] scale_values_list = [] default_scale_values = [5, 7, 10, 20, 30, 40, 60, 100, 200] for i in range(9): scale = Scale(contour_body, from_=0, to_=255, orient=HORIZONTAL, **scale_options) scale.grid(row=i+2, column=0, columnspan=2, sticky=S, **slider_padding) scale.set(default_scale_values[i]) scale_list.append(scale) for scale in scale_list: print(scale) print(type(scale)) #print(scale.get()) def contour(): scale_values_list.clear() for scale in scale_list: scale_values_list.append(scale.get()) contour_image(scale_values_list) image_data = Image.open("Contoured_image.png") thumbnail = create_thumbnail(image_data, canvas_size) export_canvas.create_image(0, 0, image=thumbnail, anchor=NW) contour_button = Button(contour_body, text="Contour image", command=contour) contour_button.grid(row=11, column=0, columnspan=2, sticky=E+S+W, **padding) contour_body.rowconfigure(11, weight=1) contour_body.columnconfigure(1, weight=1) # ============================================================================================================= # # Contents of export_body # # ============================================================================================================= filename_export_variable = StringVar() def export_file(): filename_options = {} filename_options['filetypes'] = [('PNG', '.png')] filename_options['initialfile'] = 'output.png' filename_options['parent'] = self filename_export_variable.set(filedialog.asksaveasfilename(**filename_options)) image_data = Image.open("Contoured_image.png") image_data.save(filename_export_variable.get()) export_header = Label(export_body, text="Export", font=big_heading_font) export_header.grid(row=0, column=0, sticky=N, **padding) export_canvas = Canvas(export_body, width=canvas_size, height=canvas_size, background='black') export_canvas.grid(row=1, column=0, **padding) export_button = Button(export_body, text="Export image", command=export_file) export_button.grid(row=2, column=0, columnspan=2, sticky=E+W+S, **padding) export_body.rowconfigure(2, weight=1)