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

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

class Act(object):
23

24

25
    def __init__(self, tk, args):
26
        self.tk = tk
27 28 29
        
        self.segmenter = [segmentation._segmenter_list[segmenter].meta for segmenter in segmentation._segmenter_list
                            if segmentation._segmenter_list[segmenter].value == True ][0]()
30

31 32 33 34 35 36 37
        self._image = None
        self._const_image = None
        self._image_name = None
                            
        self._init_dataset(args["dataset"])
        self._init_classes(args["classes"], args["colors"])
    
38

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

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

        if imagename:
87 88
            self._image = f.open_image(imagename)
            self._image_name = f.get_filename(imagename)
89

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


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

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

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

160
        
161 162 163
    def set_dataset_path(self):
        directory = self.tk.utils.ask_directory(default_dir = self.dataset)
        if directory:
164
            self._init_dataset(directory)
165 166
            self.tk.write_log("Image dataset defined: %s", self.dataset)
            
167
            self._init_classes()
168 169
            self.tk.refresh_panel_classes(self.classes)

170 171
            
    def select_segmenter(self):
172
        
173 174
        title = "Choosing a segmenter"
        self.tk.write_log(title)
175

176
        current_config = segmentation.get_segmenter_config()
177
        
178 179
        def process_config():
            new_config = self.tk.get_config_and_destroy()
180

181 182 183 184 185 186 187 188 189
            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):
190 191 192 193 194 195 196 197 198 199
        
        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)
200
            self.tk.append_log("\nConfig updated:\n%s", str(self.segmenter.get_summary_config()))
201 202

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


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