Commit d625ee43 authored by Alessandro dos Santos Ferreira's avatar Alessandro dos Santos Ferreira
Browse files

Pynovisao - Commit Inicial

parents
*.pyc
data/*
!data/demo.jpg
A partir da pasta raiz, execute os seguintes comandos:
$ cd src
$ python pynovisao.py
É necessário que estejam instaladas todas as dependências do python-superpixel e a biblioteca Tkinter.
#minimal example...
#import matplotlib, sys
#matplotlib.use('TkAgg')
#from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
#from matplotlib import pylab as plt
#from scipy import ndimage
#if sys.version_info[0] < 3:
#import Tkinter as Tk
#else:
#import tkinter as Tk
#root = Tk.Tk()
#root.wm_title("minimal example")
#root.image = plt.imread('test.jpg')
#fig = plt.figure(figsize=(5,4))
#im = plt.imshow(root.image) # later use a.set_data(new_data)
#ax = plt.gca()
#ax.set_xticklabels([])
#ax.set_yticklabels([])
## a tk.DrawingArea
#canvas = FigureCanvasTkAgg(fig, master=root)
#canvas.show()
#canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
#def rotate(*args):
#print 'rotate button press...'
#root.image = ndimage.rotate(root.image, 90)
#im.set_data(root.image)
#canvas.draw()
#def quit(*args):
#print 'quit button press...'
#root.quit()
#root.destroy()
#button_rotate = Tk.Button(master = root, text = 'Rotate', command = rotate)
#button_quit = Tk.Button(master = root, text = 'Quit', command = quit)
#button_quit.pack(side=Tk.LEFT)
#button_rotate.pack()
#Tk.mainloop()
import Tkinter, Tkconstants, tkFileDialog
class TkFileDialogExample(Tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root)
# options for buttons
button_opt = {'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
# define buttons
Tkinter.Button(self, text='askopenfile', command=self.askopenfile).pack(**button_opt)
Tkinter.Button(self, text='askopenfilename', command=self.askopenfilename).pack(**button_opt)
Tkinter.Button(self, text='asksaveasfile', command=self.asksaveasfile).pack(**button_opt)
Tkinter.Button(self, text='asksaveasfilename', command=self.asksaveasfilename).pack(**button_opt)
Tkinter.Button(self, text='askdirectory', command=self.askdirectory).pack(**button_opt)
# define options for opening or saving a file
self.file_opt = options = {}
options['defaultextension'] = '.txt'
options['filetypes'] = [('all files', '.*'), ('text files', '.txt')]
options['initialdir'] = 'C:\\'
options['initialfile'] = 'myfile.txt'
options['parent'] = root
options['title'] = 'This is a title'
# This is only available on the Macintosh, and only when Navigation Services are installed.
#options['message'] = 'message'
# if you use the multiple file version of the module functions this option is set automatically.
#options['multiple'] = 1
# defining options for opening a directory
self.dir_opt = options = {}
options['initialdir'] = 'C:\\'
options['mustexist'] = False
options['parent'] = root
options['title'] = 'This is a title'
def askopenfile(self):
"""Returns an opened file in read mode."""
return tkFileDialog.askopenfile(mode='r', **self.file_opt)
def askopenfilename(self):
"""Returns an opened file in read mode.
This time the dialog just returns a filename and the file is opened by your own code.
"""
# get filename
filename = tkFileDialog.askopenfilename(**self.file_opt)
# open file on your own
if filename:
return open(filename, 'r')
def asksaveasfile(self):
"""Returns an opened file in write mode."""
return tkFileDialog.asksaveasfile(mode='w', **self.file_opt)
def asksaveasfilename(self):
"""Returns an opened file in write mode.
This time the dialog just returns a filename and the file is opened by your own code.
"""
# get filename
filename = tkFileDialog.asksaveasfilename(**self.file_opt)
# open file on your own
if filename:
return open(filename, 'w')
def askdirectory(self):
"""Returns a selected directoryname."""
return tkFileDialog.askdirectory(**self.dir_opt)
if __name__=='__main__':
root = Tkinter.Tk()
TkFileDialogExample(root).pack()
root.mainloop()
\ No newline at end of file
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: actions.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: TODO
"""
import sys
import traceback
from interface import *
from segmentation import *
from util import *
DEBUG = True
IException = Interface.InterfaceException
f = File.File
segmenter = Slic.Slic()
image = None
const_image = None
segments = None
def open_image(tk):
global image, const_image
def onclick(event):
if event.xdata != None and event.ydata != None and int(event.ydata) != 0:
x = int(event.xdata)
y = int(event.ydata)
tk.write_logger("Coordinates: x = %d y = %d ", x, y)
if segments is not None:
tk.append_logger("Segment = %d", segments[y, x])
imagename = tk.utils.ask_image_name()
if imagename:
image = f.open_image(imagename)
name = f.get_filename(imagename)
tk.write_logger("Opening %s...", name)
tk.add_image(image, name, onclick)
const_image = image
def rotate_image(tk):
global image, const_image
if const_image is None:
raise IException("Image not found")
image = f.rotate_image(const_image)
tk.write_logger("Rotating image 90 degrees")
tk.refresh_image(image)
const_image = image
def close_image(tk):
global const_image
if const_image is None:
raise IException("Image not found")
if tk.close_image():
tk.write_logger("Closing image...")
const_image = None
segments = None
def run_segmentation(tk):
global image, const_image, segments
if const_image is None:
raise IException("Image not found")
tk.write_logger("Running %s,,,", segmenter.get_name())
tk.append_logger("\nConfig: %s", str(segmenter.get_summary_config()))
segments, image, run_time = segmenter.run(const_image)
tk.append_logger("\nTime elapsed: %0.3f seconds", run_time)
tk.refresh_image(image)
def config_segmentation(tk):
global segmenter
title = "Configuring %s" % segmenter.get_name()
tk.write_logger(title)
current_config = segmenter.get_config()
def process_config():
new_config = tk.get_config_and_destroy()
segmenter.set_config(new_config)
tk.append_logger("\nConfig updated: %s", str(segmenter.get_summary_config()))
tk.dialogue_config(title, current_config, process_config)
def func_not_available(tk):
tk.write_logger("This functionality is not available right now.")
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: Interface.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: Classe abstrata para os modulos de interface.
"""
import traceback
from abc import ABCMeta, abstractmethod
class Interface(object):
__metaclass__ = ABCMeta
@abstractmethod
def show(self):
pass
class InterfaceException(Exception):
DEBUG = True
@staticmethod
def format_exception(message = None):
if message is not None:
return "Unexpected error:\n%s" % message.replace('%', '%%')
elif InterfaceException.DEBUG == True:
return "Unexpected error:\n%s" % traceback.format_exc().replace('%', '%%')
else:
return "Unexpected error\n"
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: TkInterface.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: Classe que implementa os modulos de interface utilizando a biblioteca TkInter.
"""
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
import tkMessageBox
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import pylab as plt
from Interface import Interface, InterfaceException as IException
from tk_interface import *
class TkInterface(Interface):
utils = TkUtils.TkUtils
title = None
__root = None
__menus = None
__configs = None
__im = None
__canvas = None
__logger = None
__dialog = None
def __init__(self, title):
self.title = title
self.__root = Tk.Tk()
self.__root.wm_title(self.title)
self.__root.geometry('%dx%d+%d+%d' % (800, 600, 0, 0))
self.__menus = []
self.__configs = []
def set_subtitle(self, subtitle):
self.__root.wm_title(self.title + ' - ' + subtitle)
def add_menu(self, label):
self.__menus.append( Menu.Menu(label) )
def add_command(self, label, action, shortcut = None):
self.__menus[-1].add_command( label = label, action = lambda *_: self.__apply( action ), shortcut = shortcut )
def add_separator(self):
self.__menus[-1].add_separator( )
def render_menu(self):
menubar = Tk.Menu(self.__root)
shortcuts = []
for menu in self.__menus:
menubar = menu.render(menubar)
shortcuts += menu.get_shorcuts()
self.__root.config(menu=menubar)
for sh in shortcuts:
self.__root.bind("<Control-Key-" + sh["shortcut"] + ">", sh["action"])
self.__root.bind("<Control-Key-" + sh["shortcut"].lower() + ">", sh["action"])
def show(self):
self.__root.protocol("WM_DELETE_WINDOW", self.quit)
self.__root.mainloop()
def add_image(self, image, title = None, onclick = None):
if self.__canvas is None:
self.__root.image = image
fig = plt.figure(facecolor='white')
self.__im = plt.imshow(self.__root.image) # later use a.set_data(new_data)
#ax = plt.gca()
#ax.set_xticklabels([])
#ax.set_yticklabels([])
# a tk.DrawingArea
self.__canvas = FigureCanvasTkAgg(fig, master=self.__root)
self.__canvas.show()
self.__canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
if onclick is not None:
fig.canvas.mpl_connect('button_press_event', func = lambda event, *_: self.__apply( onclick, event ))
if title is not None:
self.set_subtitle(title)
else:
self.refresh_image(image, title)
def refresh_image(self, image, title = 'None'):
if self.__canvas is not None:
self.__root.image = image
self.__im.set_data(self.__root.image)
self.__canvas.draw()
def close_image(self):
if self.__canvas is not None:
if tkMessageBox.askokcancel("Quit", "Do you want to close the image?"):
self.__root.image = None
#self.__im.set_data(np.zeros((0,0,3), float))
#self.__canvas.draw()
self.__canvas.get_tk_widget().pack_forget();
self.__canvas.get_tk_widget().destroy();
self.__im = None
self.__canvas = None
return True
return False
def create_logger(self):
self.__logger = Tk.Text(self.__root, width=0, height=10, bg="white", fg="black", padx=5, pady=5)
self.__logger.insert(Tk.INSERT, "$ Pynovisao is ready!\n")
self.__logger.config(state=Tk.DISABLED)
self.__logger.pack(side=Tk.BOTTOM, fill=Tk.X, expand=False)
def write_logger(self, fmt, *args):
self.clean_logger()
self.append_logger(fmt % args)
def append_logger(self, fmt, *args):
self.__logger.config(state=Tk.NORMAL)
self.__logger.insert(Tk.END, fmt % args)
self.__logger.insert(Tk.END, '\n')
self.__logger.config(state=Tk.DISABLED)
def clean_logger(self):
self.__logger.config(state=Tk.NORMAL)
self.__logger.delete('1.0', Tk.END)
self.__logger.insert('1.0', '$ ')
self.__logger.config(state=Tk.DISABLED)
def destroy_logger(self):
self.__logger.pack_forget();
self.__logger.destroy();
def popup(self):
pass
def log_and_popup(self, message):
pass
def show_error(self, fmt, *args):
tkMessageBox.showerror("Error", fmt % args)
def show_info(self, fmt, *args):
tkMessageBox.showinfo("Info", fmt % args)
def show_warning(self, fmt, *args):
tkMessageBox.showwarning("Warning", fmt % args)
def dialogue_config(self, title, configs, callback):
n_configs = len(configs)
self.__dialog = Tk.Toplevel(self.__root, padx=10, pady=10)
self.__dialog.title(title)
row = 0
self.__configs = []
for config in configs:
Tk.Label(self.__dialog, text=config.title()).grid(row=row, padx=4, pady=4, sticky=Tk.W)
entry = Tk.Entry(self.__dialog)
entry.insert(0, str(configs[config].value))
entry.grid(row=row, column=1, padx=4, pady=4, sticky=Tk.W)
if row == 0:
entry.focus_set()
self.__configs.append( TkConfig.TkConfig(config, configs[config].value, c_type=configs[config].c_type, tk_entry=entry) )
row += 1
B1 = Tk.Button(self.__dialog, text="Ok", width=5, command = lambda *_: self.__apply( callback ))
B1.grid(row=row, padx=6, pady=6, sticky=Tk.W)
self.__dialog.bind("<Return>", lambda *_: self.__apply( callback ))
B2 = Tk.Button(self.__dialog, text="Cancel", width=5, command = self.__dialog.destroy)
B2.grid(row=row, column=1, padx=6, pady=6, sticky=Tk.W)
self.__dialog.bind("<Escape>", lambda *_: self.__dialog.destroy())
self.__dialog.grab_set()
self.__dialog.protocol("WM_DELETE_WINDOW", self.__dialog.destroy)
self.__dialog.geometry("+%d+%d" % (self.__root.winfo_width()/3,
self.__root.winfo_height()/3))
def get_config_and_destroy(self):
try:
configs = {}
for config in self.__configs:
config.value = config.get_entry_val()
configs[config.label] = config
except:
self.__dialog.destroy()
raise IException("Illegal values, please try again")
self.__dialog.destroy()
return configs
def quit(self):
if tkMessageBox.askokcancel("Quit", "Do you want to quit?"):
self.__root.quit()
self.__root.destroy()
def debug(self, event):
print("DEBUG")
def __apply(self, f, *args):
try:
f(*args)
except IException as exc:
self.__log_exception( str(exc), True )
except:
self.__log_exception( IException.format_exception() )
def __log_exception(self, message, warning = False):
if warning == True:
self.show_warning( message )
elif IException.DEBUG == True:
self.append_logger( message )
else:
self.show_error( message )
__all__ = ["Interface", "TkInterface"]
\ No newline at end of file
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: ItemMenu.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: TODO
"""
from abc import ABCMeta, abstractmethod
class ItemMenu(object):
__metaclass__ = ABCMeta
@abstractmethod
def render(self, menu):
pass
@abstractmethod
def get_shortcut(self):
pass
class Command(ItemMenu):
label = None
action = None
shortcut = None
def __init__(self, label, action, shortcut = None):
self.label = label
self.action = action
if shortcut is not None:
self.shortcut = str(shortcut).upper()
def render(self, menu):
accelerator = None if self.shortcut is None else "Ctrl+" + str(self.shortcut)
underline = None if self.shortcut is None else self.label.upper().find( self.shortcut )
menu.add_command(label=self.label, command=self.action, accelerator=accelerator, underline=underline)
return menu
def get_shortcut(self):
return self.shortcut, self.action
class Separator(ItemMenu):
def __init__(self):
pass
def render(self, menu):
menu.add_separator()
return menu
def get_shortcut(self):
return None, None
#!/usr/bin/python
# -*- coding: utf-8 -*-