Pynovisao.py 7.32 KB
Newer Older
1 2 3 4 5 6 7
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
  Nome: Pynovisao.py
  Autor: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )

8
  Descricão: Classe que contem a implementacao de todas as acoes disponiveis no programa.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
"""

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
27
    dataset = None
28 29 30
    
    __image = None
    __const_image = None
31 32 33 34
    __image_name = None
    
    __current_class = None

35

36
    def __init__(self, tk, args):
37 38
        self.tk = tk
        self.segmenter = Slic.Slic()
39

40
        self.__init_dataset(args["dataset"])
41 42
        self.__init_classes(args["classes"], args["colors"])

43 44 45 46 47 48
    def __init_dataset(self, directory):
        if(directory[-1] == '/'):
            directory = directory[:-1]
            
        self.dataset = directory
        f.create_dir(self.dataset)
49
    
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
    def __init_classes(self, classes = None, colors = None):
        self.classes = []
        
        classes = sorted(f.list_dirs(self.dataset)) if classes is None else classes.split()
        colors = [] if colors is None else colors.split()

        if(len(classes) > 0):
            for i in range(0, len(classes)):
                self.add_class(dialog = False, name=classes[i], color=colors[i] if i < len(colors) else None)
        else:
            self.add_class(dialog = False, color='Green')
            self.add_class(dialog = False, color='Yellow')
            
        self.__current_class = 0
        
        
    def open_image(self, imagename = None):
67 68 69 70 71
        
        def onclick(event):
            if event.xdata != None and event.ydata != None and int(event.ydata) != 0:
                x = int(event.xdata)
                y = int(event.ydata)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
                self.tk.write_log("Coordinates: x = %d y = %d", x, y)
                
                segment, size_segment, idx_segment, run_time = self.segmenter.get_segment(x, y)
                
                if size_segment > 0:
                    self.tk.append_log("\nSegment = %d: %0.3f seconds", idx_segment, run_time)
                    
                    self.__image, run_time = self.segmenter.paint_segment(self.__image, self.classes[self.__current_class]["color"].value, x, y)
                    self.tk.append_log("Painting segment: %0.3f seconds", run_time)
                    self.tk.refresh_image(self.__image)
                    
                    filepath = f.save_image(segment, self.dataset, self.classes[self.__current_class]["name"].value, self.__image_name, idx_segment)
                    if filepath:
                        self.tk.append_log("\nSegment saved in %s", filepath)
        
        if imagename is None:
            imagename = self.tk.utils.ask_image_name()
89 90 91

        if imagename:
            self.__image = f.open_image(imagename)
92
            self.__image_name = f.get_filename(imagename)
93

94 95
            self.tk.write_log("Opening %s...", self.__image_name)
            self.tk.add_image(self.__image, self.__image_name, onclick)
96 97 98 99 100 101 102 103 104 105
            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
106 107 108


    def add_class(self, dialog = True, name = None, color = None):
109 110 111
        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)
112
                
113 114
        def edit_class(index):
            self.edit_class(index)
115 116 117
            
        def update_current_class(index):
            self.update_current_class(index)
118 119 120
        
        def process_config():
            new_class = self.tk.get_config_and_destroy()
121
            new_class["name"].value = '_'.join(new_class["name"].value.split())
122 123 124

            self.classes.append( new_class )
            self.tk.write_log("New class: %s", new_class["name"].value)
125
            self.tk.refresh_panel_classes(self.classes, self.__current_class)
126
            
127 128
        if name is None:
            name = "Class_%02d" % (n_classes+1)
129 130 131 132
        if color is None:
            color = X11Colors.Colors.random_color()
            
        class_config = OrderedDict()
133
        class_config["name"] = Config(label="Name", value=name, c_type=str)
134
        class_config["color"] = Config(label="Color (X11 Colors)", value=color, c_type='color')
135 136
        class_config["callback"] = Config(label=None, value=update_current_class, c_type=None, hidden=True)
        class_config["callback_color"] = Config(label=None, value=edit_class, c_type=None, hidden=True)
137 138 139 140 141 142 143
        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"
144 145 146
        self.tk.dialogue_config(title, class_config, process_config)        
      

147 148 149
    def edit_class(self, index):
        def process_update(index):
            updated_class = self.tk.get_config_and_destroy()
150
            updated_class["name"].value = '_'.join(updated_class["name"].value.split())
151 152 153
            
            self.classes[index] = updated_class
            self.tk.write_log("Class updated: %s", updated_class["name"].value)
154
            self.tk.refresh_panel_classes(self.classes, self.__current_class)
155 156 157 158 159 160
        
        current_config = self.classes[index]
            
        title = "Edit class %s" % current_config["name"].value
        self.tk.dialogue_config(title, current_config, lambda *_ : process_update(index))
            
161 162 163
    def update_current_class(self, index):
        self.__current_class = index

164
        
165 166 167
    def set_dataset_path(self):
        directory = self.tk.utils.ask_directory(default_dir = self.dataset)
        if directory:
168
            self.__init_dataset(directory)
169 170 171 172 173 174
            self.tk.write_log("Image dataset defined: %s", self.dataset)
            
            self.__init_classes()
            self.tk.refresh_panel_classes(self.classes)


175 176 177 178 179 180 181 182
    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()))
183 184
        self.__image, run_time = self.segmenter.run(self.__const_image)
        self.tk.append_log("Time elapsed: %0.3f seconds", run_time)
185 186 187 188 189 190 191 192 193 194 195 196 197 198
        
        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)
199
            self.tk.append_log("\nConfig updated:\n%s", str(self.segmenter.get_summary_config()))
200 201 202 203 204 205

        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.")
206