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

Pynovisao - Configuracao de classes

parent 75eca498
......@@ -15,7 +15,7 @@ Pacote de Visão Computacional do Inovisão.
```
```
$ python pynovisao.py
$ python main.py
```
......
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Nome: Pynovisao.py
Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
Descricão: TODO
"""
from collections import OrderedDict
from interface import *
from interface.Interface import InterfaceException as IException
from segmentation import *
from util import *
from util.Config import Config
from util.File import File as f
class Act(object):
tk = None
segmenter = None
classes = None
__image = None
__const_image = None
__segments = None
def __init__(self, tk):
self.tk = tk
self.segmenter = Slic.Slic()
self.classes = []
self.add_class(dialog = False, color='green')
self.add_class(dialog = False, color='yellow')
def open_image(self):
def onclick(event):
if event.xdata != None and event.ydata != None and int(event.ydata) != 0:
x = int(event.xdata)
y = int(event.ydata)
self.tk.write_log("Coordinates: x = %d y = %d ", x, y)
if self.__segments is not None:
self.tk.append_log("Segment = %d", segments[y, x])
imagename = self.tk.utils.ask_image_name()
if imagename:
self.__image = f.open_image(imagename)
name = f.get_filename(imagename)
self.tk.write_log("Opening %s...", name)
self.tk.add_image(self.__image, name, onclick)
self.__const_image = self.__image
def rotate_image(self):
if self.__const_image is None:
raise IException("Image not found")
image = self.f.rotate_image(self.__const_image)
self.tk.write_log("Rotating image 90 degrees")
self.tk.refresh_image(self.__image)
self.__const_image = self.__image
def close_image(self):
if self.__const_image is None:
raise IException("Image not found")
if self.tk.close_image():
self.tk.write_log("Closing image...")
self.__const_image = None
self.__segments = None
def add_class(self, dialog = True, color = None):
n_classes = len(self.classes)
if n_classes >= self.tk.MAX_CLASSES:
raise IException("You have reached the limite of %d classes" % self.tk.MAX_CLASSES)
def edit_class(index):
self.edit_class(index)
def process_config():
new_class = self.tk.get_config_and_destroy()
self.classes.append( new_class )
self.tk.write_log("New class: %s", new_class["name"].value)
self.tk.refresh_panel_classes(self.classes)
if color is None:
color = X11Colors.Colors.random_color()
class_config = OrderedDict()
class_config["name"] = Config(label="Name", value="Class %02d" % (n_classes+1), c_type=str)
class_config["color"] = Config(label="Color (X11 Colors)", value=color, c_type='color')
class_config["callback"] = Config(label=None, value=edit_class, c_type=None, hidden=True)
class_config["args"] = Config(label=None, value=n_classes, c_type=int, hidden=True)
if dialog == False:
self.classes.append( class_config )
return
title = "Add a new classe"
self.tk.dialogue_config(title, class_config, process_config)
def edit_class(self, index):
def process_update(index):
updated_class = self.tk.get_config_and_destroy()
self.classes[index] = updated_class
self.tk.write_log("Class updated: %s", updated_class["name"].value)
self.tk.refresh_panel_classes(self.classes)
current_config = self.classes[index]
title = "Edit class %s" % current_config["name"].value
self.tk.dialogue_config(title, current_config, lambda *_ : process_update(index))
def run_segmentation(self):
if self.__const_image is None:
raise IException("Image not found")
self.tk.write_log("Running %s,,,", self.segmenter.get_name())
self.tk.append_log("\nConfig: %s", str(self.segmenter.get_summary_config()))
self.__segments, self.__image, run_time = self.segmenter.run(self.__const_image)
self.tk.append_log("\nTime elapsed: %0.3f seconds", run_time)
self.tk.refresh_image(self.__image)
def config_segmentation(self):
title = "Configuring %s" % self.segmenter.get_name()
self.tk.write_log(title)
current_config = self.segmenter.get_config()
def process_config():
new_config = self.tk.get_config_and_destroy()
self.segmenter.set_config(new_config)
self.tk.append_log("\nConfig updated: %s", str(self.segmenter.get_summary_config()))
self.tk.dialogue_config(title, current_config, process_config)
def func_not_available(self):
self.tk.write_log("This functionality is not available right now.")
#!/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_log("Coordinates: x = %d y = %d ", x, y)
if segments is not None:
tk.append_log("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_log("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_log("Rotating image 90 degrees")
tk.refresh_image(image)
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_log("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_log("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_log("Running %s,,,", segmenter.get_name())
tk.append_log("\nConfig: %s", str(segmenter.get_summary_config()))
segments, image, run_time = segmenter.run(const_image)
tk.append_log("\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_log(title)
current_config = segmenter.get_config()
def process_config():
new_config = tk.get_config_and_destroy()
segmenter.set_config(new_config)
tk.append_log("\nConfig updated: %s", str(segmenter.get_summary_config()))
tk.dialogue_config(title, current_config, process_config)
def refresh_classes(tk):
tk.write_log("Refreshing classes...")
tk.add_panel_classes()
def func_not_available(tk):
tk.write_log("This functionality is not available right now.")
......@@ -19,6 +19,8 @@ from tk import *
class TkInterface(Interface):
MAX_CLASSES = 20
utils = TkUtils.Utils
title = None
......@@ -27,6 +29,7 @@ class TkInterface(Interface):
__menus = None
__image = None
__grid = None
__logger = None
def __init__(self, title):
......@@ -37,7 +40,6 @@ class TkInterface(Interface):
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)
......@@ -51,6 +53,9 @@ class TkInterface(Interface):
def add_separator(self):
self.__menus[-1].add_separator( )
def add_check_button(self, label, action, shortcut = None):
self.__menus[-1].add_check_button(label = label, action = lambda *_: self.__apply( action ), shortcut = shortcut)
def render_menu(self):
menubar = Tk.Menu(self.__root)
......@@ -62,10 +67,10 @@ class TkInterface(Interface):
def add_image(self, image, title = None, onclick = None):
if self.__image is None:
self.__image = TkCanvas.Image(self.__root, image, lambda event, *_: self.__apply( onclick, event ))
else:
self.__image.refresh(image)
if self.__image is not None:
self.__image.close()
self.__image = TkCanvas.Image(self.__root, image, lambda event, *_: self.__apply( onclick, event ))
if title is not None:
self.set_subtitle(title)
......@@ -103,10 +108,17 @@ class TkInterface(Interface):
def clear_log(self):
if self.__logger:
self.__logger.clear_logger()
def toogle_log(self):
if self.__logger:
self.close_log()
else:
self.open_log()
def close_log(self):
if self.__logger:
self.__logger.destroy_logger()
self.__logger = None
def add_panel(self, left = True):
......@@ -118,24 +130,30 @@ class TkInterface(Interface):
def add_panel_classes(self, classes = None):
if self.__grid is None:
self.__grid = TkCustomFrame.CustomGrid(self.__root)
else:
self.clear_panel_classes()
from random import randint as r
length = r(2, 16)
self.__grid.add_cell_label("Classes ", 0, 0, 12, 4)
for i in range(1, length):
self.__grid.add_cell_radio_button("Classe " + str(i), i, i, 0, 12, selected=False if i > 1 else True)
self.__grid.add_cell_button_color("", i, 1, 2, bg='#%02X%02X%02X' % (r(23, 212), r(50, 214), r(0, 255)))
self.__grid.add_cell_label("", i, 2, 2)
classes = classes if classes is not None else []
self.__grid.add_cell_label("", 0, 0, 1, 4)
self.__grid.add_cell_label("Classes ", 0, 1, 12, 4)
self.__grid.add_cell_label("", 0, 3, 2, 4)
length = len(classes)
for i in range(1, length+1):
self.__grid.add_cell_radio_button(classes[i-1]["name"].value[:12], i, i, 1, 12, selected=False if i > 1 else True)
self.__grid.add_cell_button_color("", i, 2, 2, bg=classes[i-1]["color"].value,
command=classes[i-1]["callback"].value, command_args=classes[i-1]["args"].value )
self.__grid.pack(side=Tk.LEFT, fill=Tk.Y, expand=False)
def refresh_panel_classes(self, classes = None):
self.clear_panel_classes()
self.add_panel_classes(classes)
def clear_panel_classes(self):
for i in range(1, 20):
self.__grid.add_cell_label("", i, 0, 12)
self.__grid.add_cell_label("", i, 1, 2)
for i in range(1, self.MAX_CLASSES+1):
self.__grid.add_cell_label("", i, 1, 15)
self.__grid.add_cell_label("", i, 2, 2)
def close_panel(self):
if self.__grid is not None:
......@@ -158,18 +176,17 @@ class TkInterface(Interface):
return None
try:
configs = {}
for config in self.__conf_dialog.get_configs():
config.value = config.get_entry_val()
configs[config.label] = config
self.__conf_dialog.update_and_validate_configs()
configs = self.__conf_dialog.get_configs()
self.__conf_dialog.destroy()
self.__conf_dialog = None
return configs
except:
self.__conf_dialog.destroy()
raise IException("Illegal values, please try again")
self.__conf_dialog.destroy()
self.__conf_dialog = None
return configs
def show_error(self, fmt, *args):
......
......@@ -32,7 +32,7 @@ class Image(object):
self.parent.image = image
fig = plt.figure(facecolor='white')
fig = plt.figure(facecolor='white', edgecolor='black', linewidth=1)
self.__im = plt.imshow(self.parent.image) # later use a.set_data(new_data)
#ax = plt.gca()
#ax.set_xticklabels([])
......
......@@ -14,10 +14,11 @@ class TkConfig(Config):
tk_entry = None
def __init__(self, label, value, c_type, tk_entry, min_value = None, max_value = None):
super(self.__class__, self).__init__(label, value, c_type, min_value, max_value)
def __init__(self, label, value, c_type, tk_entry = None, hidden = False, min_value = None, max_value = None):
super(self.__class__, self).__init__(label, value, c_type, hidden, min_value, max_value)
self.tk_entry = tk_entry
def get_entry_val(self):
return (self.c_type)(self.tk_entry.get())
if self.tk_entry is not None:
self.value = self.tk_entry.get()
return self.get_cast_val()
......@@ -13,15 +13,15 @@ if sys.version_info[0] < 3:
else:
import tkinter as Tk
from collections import OrderedDict
from TkConfig import TkConfig
class ConfigDialog(Tk.Toplevel):
class SimpleDialog(Tk.Toplevel):
parent = None
__configs = None
def __init__(self, parent, title = None, configs = None, command_ok = None):
def __init__(self, parent, title = None, command_ok = None):
self.parent = parent
Tk.Toplevel.__init__(self, self.parent, padx=10, pady=10)
......@@ -32,29 +32,40 @@ class ConfigDialog(Tk.Toplevel):
self.grab_set()
if configs is not None:
self.add_configs(configs, command_ok)
self.geometry("+%d+%d" % (parent.winfo_width()/3,
parent.winfo_height()/3))
self.protocol("WM_DELETE_WINDOW", self.destroy)
class ConfigDialog(SimpleDialog):
__configs = None
def __init__(self, parent, title = None, configs = None, command_ok = None):
SimpleDialog.__init__(self, parent, title, command_ok)
if configs is not None:
self.add_configs(configs, command_ok)
def add_configs(self, configs, command_ok):
row = 0
self.__configs = []
for config in configs:
Tk.Label(self, text=config.title()).grid(row=row, padx=4, pady=4, sticky=Tk.W)
entry = Tk.Entry(self)
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 = OrderedDict()
for key in configs:
if configs[key].hidden == False:
Tk.Label(self, text=configs[key].label).grid(row=row, padx=4, pady=4, sticky=Tk.W)
entry = Tk.Entry(self)
entry.insert(0, str(configs[key].value))
entry.grid(row=row, column=1, padx=4, pady=4, sticky=Tk.W)
if row == 0:
entry.focus_set()
row += 1
self.__configs.append( TkConfig(config, configs[config].value, c_type=configs[config].c_type, tk_entry=entry) )
row += 1
self.__configs[key] = TkConfig(configs[key].label, configs[key].value, c_type=configs[key].c_type, tk_entry=entry, hidden=configs[key].hidden)
else:
self.__configs[key] = TkConfig(configs[key].label, configs[key].value, c_type=configs[key].c_type, hidden=configs[key].hidden )
B1 = Tk.Button(self, text="Ok", width=5, command = command_ok)
B1.grid(row=row, padx=6, pady=6, sticky=Tk.W)
......@@ -67,6 +78,9 @@ class ConfigDialog(Tk.Toplevel):
self.bind("<Escape>", lambda *_: self.destroy())
def update_and_validate_configs(self):
for key in self.__configs:
self.__configs[key].value = self.__configs[key].get_entry_val()
def get_configs(self):
return self.__configs
......@@ -14,6 +14,8 @@ else:
import tkinter as Tk
from TkUtils import Utils
from util.X11Colors import Colors
class CustomGrid(Tk.Frame):
parent = None
......@@ -32,16 +34,19 @@ class CustomGrid(Tk.Frame):
Tk.Label(self, text=text, width=width, height=height, bg=bg, fg=fg, padx=4, pady=4).grid(row=row, column=column)
def add_cell_button_color(self, text, row, column, width=0, height=0, bg='white', fg="black", command=None):
def add_cell_button_color(self, text, row, column, width=0, height=0, bg='white', fg="black", command=None, command_args=None):
bg_color = Colors.get_color_hex(bg)
Tk.Button(self, text=text, width=width, height=height, bg=bg, fg=fg, padx=0, pady=0,
command = lambda *_: Utils.ask_color_choose(default_color = bg)).grid(row=row, column=column)
bt = Tk.Button(self, text=text, width=width, height=height, bg=bg_color, fg=fg, padx=0, pady=0, cursor="hand1",
command=lambda *_: command(command_args))
bt.grid(row=row, column=column)
def add_cell_radio_button(self, text, value, row, column, width=0, height=0, bg='white', fg="black", selected=False, command=None):
radio = Tk.Radiobutton(self, text=text, variable=self.v, value=value,
width=width, height=height, bg=bg, fg=fg, padx=4, pady=4,
indicatoron=1,
indicatoron=1, anchor=Tk.W,
activebackground='#404040', highlightbackground='white')
radio.grid(row=row, column=column)
......
......@@ -7,6 +7,11 @@
Descricão: TODO
"""
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
from abc import ABCMeta, abstractmethod
......@@ -51,3 +56,27 @@ class Separator(ItemMenu):
def render(self, menu):
menu.add_separator()
class CheckButton(ItemMenu):
label = None
default_state = None
def __init__(self, parent, label, action, shortcut = None, default_state = True):
super(self.__class__, self).__init__(parent)
self.label = label
self.action = action
if shortcut is not None:
self.shortcut = str(shortcut).upper()
self.default_state = default_state
<