pynovisao.py 10.4 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
        self._image = None
        self._const_image = None
        self._image_name = None
                            
        self._init_dataset(args["dataset"])
        self._init_classes(args["classes"], args["colors"])
42 43
        
        self._dataset_generator = True
44
    
45

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

68

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

        if imagename:
94 95
            self._image = f.open_image(imagename)
            self._image_name = f.get_filename(imagename)
96

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

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

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

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

167
        
168 169 170
    def set_dataset_path(self):
        directory = self.tk.utils.ask_directory(default_dir = self.dataset)
        if directory:
171
            self._init_dataset(directory)
172 173
            self.tk.write_log("Image dataset defined: %s", self.dataset)
            
174
            self._init_classes()
175
            self.tk.refresh_panel_classes(self.classes)
176 177 178
            
    def toggle_dataset_generator(self):
        self._dataset_generator = not self._dataset_generator
179

180 181
            
    def select_segmenter(self):
182
        
183 184
        title = "Choosing a segmenter"
        self.tk.write_log(title)
185

186
        current_config = segmentation.get_segmenter_config()
187
        
188 189
        def process_config():
            new_config = self.tk.get_config_and_destroy()
190

191 192 193
            self.segmenter = [new_config[segmenter].meta for segmenter in new_config
                                if new_config[segmenter].value == True ][0]()

194
            self.tk.append_log("\nSegmenter: %s\n%s", str(self.segmenter.get_name()), str(self.segmenter.get_summary_config()))
195 196 197 198 199
            segmentation.set_segmenter_config(new_config)

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

    def config_segmenter(self):
200 201 202 203 204 205 206 207 208 209
        
        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)
210
            self.tk.append_log("\nConfig updated:\n%s", str(self.segmenter.get_summary_config()))
211 212

        self.tk.dialogue_config(title, current_config, process_config)
213 214 215 216 217 218
        
    def run_segmenter(self):
        
        if self._const_image is None:
            raise IException("Image not found")
        
219
        self.tk.write_log("Running %s...", self.segmenter.get_name())
220 221 222 223 224 225

        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)
226 227 228 229 230
        
    def clean_segmentation(self):
        if self._const_image is not None:
            self.tk.write_log("Removing %s segmentation...", self.segmenter.get_name())
            self.tk.refresh_image(self._const_image)
231 232


233 234 235 236 237 238 239 240 241 242 243 244
    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 ]
245 246 247
                                
            if len(self.extractors) == 0:
                raise IException("Please select at least one extractor")
248 249 250 251 252 253 254

            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)
255 256 257 258
        
    def run_extractors(self):
        
        self.tk.write_log("Running extractors on all images in %s", self.dataset)
259

260 261 262
        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 ]))
263
        
264 265 266 267 268
        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)


269 270
    def func_not_available(self):
        self.tk.write_log("This functionality is not available right now.")
271