pynovisao.py 9.09 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

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

class Act(object):
24

25

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

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

66
    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
                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)
                    
79
                    self._image, run_time = self.segmenter.paint_segment(self._image, self.classes[self._current_class]["color"].value, x, y)
80
                    self.tk.append_log("Painting segment: %0.3f seconds", run_time)
81
                    self.tk.refresh_image(self._image)
82
                    
83
                    filepath = f.save_image(segment, self.dataset, self.classes[self._current_class]["name"].value, self._image_name, idx_segment)
84 85 86 87 88
                    if filepath:
                        self.tk.append_log("\nSegment saved in %s", filepath)
        
        if imagename is None:
            imagename = self.tk.utils.ask_image_name()
89 90

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

94 95 96
            self.tk.write_log("Opening %s...", self._image_name)
            self.tk.add_image(self._image, self._image_name, onclick)
            self._const_image = self._image
97 98 99
        
    def close_image(self):
        
100
        if self._const_image is None:
101 102 103 104
            raise IException("Image not found")
        
        if self.tk.close_image():
            self.tk.write_log("Closing image...")
105
            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
        if color is None:
130
            color = util.X11Colors.random_color()
131 132
            
        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
    def update_current_class(self, index):
162
        self._current_class = index
163

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
            self.tk.write_log("Image dataset defined: %s", self.dataset)
            
171
            self._init_classes()
172 173
            self.tk.refresh_panel_classes(self.classes)

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

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

185 186 187 188 189 190 191 192 193
            self.segmenter = [new_config[segmenter].meta for segmenter in new_config
                                if new_config[segmenter].value == True ][0]()

            self.tk.append_log("\nConfig updated:\nSegmenter: %s", str(self.segmenter.get_name()))
            segmentation.set_segmenter_config(new_config)

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

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

        self.tk.dialogue_config(title, current_config, process_config)
207 208 209 210 211 212 213 214 215 216 217 218 219
        
    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)
220 221


222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    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 ]

            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)

        
243 244
    def func_not_available(self):
        self.tk.write_log("This functionality is not available right now.")
245