pynovisao.py 9.93 KB
Newer Older
1 2 3 4
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
5 6 7 8
    This file must contain the implementation code for all actions of pynovisao.
    
    Name: pynovisao.py
    Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
9 10 11 12
"""

from collections import OrderedDict

13 14
import interface
from interface.interface import InterfaceException as IException
15

16
import segmentation
17
import extraction
18
from extraction import FeatureExtractor
19

20 21 22 23 24
import util
from util.config import Config
from util.file_utils import File as f

class Act(object):
25

26

27
    def __init__(self, tk, args):
28
        self.tk = tk
29 30 31
        
        self.segmenter = [segmentation._segmenter_list[segmenter].meta for segmenter in segmentation._segmenter_list
                            if segmentation._segmenter_list[segmenter].value == True ][0]()
32 33 34
        
        self.extractors = [extraction._extractor_list[extractor].meta for extractor in extraction._extractor_list
                            if extraction._extractor_list[extractor].value == True ]
35

36 37 38 39 40 41 42
        self._image = None
        self._const_image = None
        self._image_name = None
                            
        self._init_dataset(args["dataset"])
        self._init_classes(args["classes"], args["colors"])
    
43

44
    def _init_dataset(self, directory):
45 46 47 48 49
        if(directory[-1] == '/'):
            directory = directory[:-1]
            
        self.dataset = directory
        f.create_dir(self.dataset)
50
    
51
    def _init_classes(self, classes = None, colors = None):
52 53 54 55 56 57 58 59 60 61 62 63
        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')
            
64
        self._current_class = 0
65
        
66

67
    def open_image(self, imagename = None):
68 69 70 71 72
        
        def onclick(event):
            if event.xdata != None and event.ydata != None and int(event.ydata) != 0:
                x = int(event.xdata)
                y = int(event.ydata)
73 74 75 76 77 78 79
                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)
                    
80
                    self._image, run_time = self.segmenter.paint_segment(self._image, self.classes[self._current_class]["color"].value, x, y)
81
                    self.tk.append_log("Painting segment: %0.3f seconds", run_time)
82
                    self.tk.refresh_image(self._image)
83
                    
84
                    filepath = f.save_image(segment, self.dataset, self.classes[self._current_class]["name"].value, self._image_name, idx_segment)
85 86 87 88 89
                    if filepath:
                        self.tk.append_log("\nSegment saved in %s", filepath)
        
        if imagename is None:
            imagename = self.tk.utils.ask_image_name()
90 91

        if imagename:
92 93
            self._image = f.open_image(imagename)
            self._image_name = f.get_filename(imagename)
94

95 96 97
            self.tk.write_log("Opening %s...", self._image_name)
            self.tk.add_image(self._image, self._image_name, onclick)
            self._const_image = self._image
98 99 100
        
    def close_image(self):
        
101
        if self._const_image is None:
102 103 104 105
            raise IException("Image not found")
        
        if self.tk.close_image():
            self.tk.write_log("Closing image...")
106
            self._const_image = None
107 108 109


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

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

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

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

175 176
            
    def select_segmenter(self):
177
        
178 179
        title = "Choosing a segmenter"
        self.tk.write_log(title)
180

181
        current_config = segmentation.get_segmenter_config()
182
        
183 184
        def process_config():
            new_config = self.tk.get_config_and_destroy()
185

186 187 188
            self.segmenter = [new_config[segmenter].meta for segmenter in new_config
                                if new_config[segmenter].value == True ][0]()

189
            self.tk.append_log("\nSegmenter: %s\n%s", str(self.segmenter.get_name()), str(self.segmenter.get_summary_config()))
190 191 192 193 194
            segmentation.set_segmenter_config(new_config)

        self.tk.dialogue_choose_one(title, current_config, process_config)

    def config_segmenter(self):
195 196 197 198 199 200 201 202 203 204
        
        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)
205
            self.tk.append_log("\nConfig updated:\n%s", str(self.segmenter.get_summary_config()))
206 207

        self.tk.dialogue_config(title, current_config, process_config)
208 209 210 211 212 213 214 215 216 217 218 219 220
        
    def run_segmenter(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._image, run_time = self.segmenter.run(self._const_image)
        self.tk.append_log("Time elapsed: %0.3f seconds", run_time)
        
        self.tk.refresh_image(self._image)
221 222


223 224 225 226 227 228 229 230 231 232 233 234
    def select_extractors(self):
        
        title = "Selecting extractors"
        self.tk.write_log(title)

        current_config = extraction.get_extractor_config()
        
        def process_config():
            new_config = self.tk.get_config_and_destroy()

            self.extractors = [new_config[extractor].meta for extractor in new_config
                                if new_config[extractor].value == True ]
235 236 237
                                
            if len(self.extractors) == 0:
                raise IException("Please select at least one extractor")
238 239 240 241 242 243 244

            self.tk.append_log("\nConfig updated:\n%s", 
                                '\n'.join(["%s: %s" % (new_config[extractor].label, "on" if new_config[extractor].value==True else "off")
                                            for extractor in new_config]))
            extraction.set_extractor_config(new_config)

        self.tk.dialogue_select(title, current_config, process_config)
245 246 247 248
        
    def run_extractors(self):
        
        self.tk.write_log("Running extractors on all images in %s", self.dataset)
249

250 251 252
        fextractor = FeatureExtractor(self.extractors)
        self.tk.append_log("%s", '\n'.join([extraction._extractor_list[extractor].label for extractor in extraction._extractor_list
                                                if extraction._extractor_list[extractor].value == True ]))
253
        
254 255 256 257 258
        output_file, run_time = fextractor.extract_all(self.dataset, "trainning")
        self.tk.append_log("\nOutput file saved in %s", output_file)
        self.tk.append_log("Time elapsed: %0.3f seconds", run_time)


259 260
    def func_not_available(self):
        self.tk.write_log("This functionality is not available right now.")
261