Commit 2f27cdb9 authored by Alessandro dos Santos Ferreira's avatar Alessandro dos Santos Ferreira
Browse files

Adicionando opcao Ground Truth

parent 31f30bd4
...@@ -38,7 +38,7 @@ class Menu(object): ...@@ -38,7 +38,7 @@ class Menu(object):
self._items_menu = [] self._items_menu = []
def add_command(self, label, action, shortcut): def add_command(self, label, action, shortcut = None):
"""Add a new option to menu. """Add a new option to menu.
Parameters Parameters
...@@ -66,7 +66,7 @@ class Menu(object): ...@@ -66,7 +66,7 @@ class Menu(object):
""" """
self._items_menu.append( Separator(self) ) self._items_menu.append( Separator(self) )
def add_check_button(self, label, action, shortcut): def add_check_button(self, label, action, shortcut = None, default_state = True):
"""Add a new check button to menu. """Add a new check button to menu.
Parameters Parameters
...@@ -77,8 +77,10 @@ class Menu(object): ...@@ -77,8 +77,10 @@ class Menu(object):
Callback to be executed on check button click. Callback to be executed on check button click.
shortcut : string, optional, default = None shortcut : string, optional, default = None
Check button shortcut number ou letter. Not case sensitive. Check button shortcut number ou letter. Not case sensitive.
default_state : boolean, optional, default = True
Initial state of check button. If true set to on.
""" """
self._items_menu.append( CheckButton(self, label, action, shortcut) ) self._items_menu.append( CheckButton(self, label, action, shortcut, default_state) )
def render(self, menubar): def render(self, menubar):
"""Render the menu in GUI. """Render the menu in GUI.
......
...@@ -87,7 +87,7 @@ class TkInterface(Interface): ...@@ -87,7 +87,7 @@ class TkInterface(Interface):
""" """
self._menus[-1].add_separator( ) self._menus[-1].add_separator( )
def add_check_button(self, label, action, shortcut = None): def add_check_button(self, label, action, shortcut = None, default_state = True):
"""Add a check button to last menu added. """Add a check button to last menu added.
Parameters Parameters
...@@ -96,10 +96,12 @@ class TkInterface(Interface): ...@@ -96,10 +96,12 @@ class TkInterface(Interface):
Check button option label. Check button option label.
action : function action : function
Callback to be executed on check button click. Callback to be executed on check button click.
shortcut : string shortcut : string, optional, default = None
Check button shortcut number ou letter. Not case sensitive. Check button shortcut number ou letter. Not case sensitive.
default_state : boolean, optional, default = True
Initial state of check button. If true set to on.
""" """
self._menus[-1].add_check_button(label = label, action = lambda *_: self._apply( action ), shortcut = shortcut) self._menus[-1].add_check_button(label = label, action = lambda *_: self._apply( action ), shortcut = shortcut, default_state = default_state)
def render_menu(self): def render_menu(self):
"""Add to window GUI the last menu added. """Add to window GUI the last menu added.
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
This file is the main code of Pynovisao. This file is the main code of Pynovisao.
To add a new action ( functionality ) to this software, you must implement the method body of action in file pynovisao.py To add a new action ( functionality ) to this software, you must implement the method body of action in file pynovisao.py
and bind the method to menu, using the call tk.add_command. and bind the method to menu, using the call tk.add_command or tk.add_check_button.
To add a new Feature Extractor, Segmenter or Classifier, place it in correct directory and extend its abstract class. To add a new Feature Extractor, Segmenter or Classifier, place it in correct directory and extend its abstract class.
...@@ -63,7 +63,7 @@ if __name__ == "__main__": ...@@ -63,7 +63,7 @@ if __name__ == "__main__":
tk.add_command("Add new class", act.add_class, 'A') tk.add_command("Add new class", act.add_class, 'A')
tk.add_command("Set dataset path", act.set_dataset_path, 'd') tk.add_command("Set dataset path", act.set_dataset_path, 'd')
tk.add_separator() tk.add_separator()
tk.add_check_button("Dataset generator", act.toggle_dataset_generator, 't') tk.add_check_button("Dataset generator", act.toggle_dataset_generator)
tk.add_menu("Segmentation") tk.add_menu("Segmentation")
tk.add_command("Choose segmenter", act.select_segmenter) tk.add_command("Choose segmenter", act.select_segmenter)
...@@ -80,6 +80,8 @@ if __name__ == "__main__": ...@@ -80,6 +80,8 @@ if __name__ == "__main__":
tk.add_command("Choose classifier", act.select_classifier) tk.add_command("Choose classifier", act.select_classifier)
tk.add_command("Configure", act.configure_classifier) tk.add_command("Configure", act.configure_classifier)
tk.add_separator() tk.add_separator()
tk.add_check_button("Ground Truth", act.toggle_ground_truth, default_state = False)
tk.add_separator()
tk.add_command("Cross Validation", act.cross_validation, 'X') tk.add_command("Cross Validation", act.cross_validation, 'X')
tk.add_command("Experimenter All", act.experimenter_all, 'p') tk.add_command("Experimenter All", act.experimenter_all, 'p')
tk.add_separator() tk.add_separator()
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
""" """
from collections import OrderedDict from collections import OrderedDict
import numpy as np
import interface import interface
from interface.interface import InterfaceException as IException from interface.interface import InterfaceException as IException
...@@ -17,6 +18,7 @@ import segmentation ...@@ -17,6 +18,7 @@ import segmentation
import extraction import extraction
from extraction import FeatureExtractor from extraction import FeatureExtractor
import classification import classification
from classification import Classifier
import util import util
from util.config import Config from util.config import Config
...@@ -58,6 +60,8 @@ class Act(object): ...@@ -58,6 +60,8 @@ class Act(object):
self._init_classes(args["classes"], args["colors"]) self._init_classes(args["classes"], args["colors"])
self._dataset_generator = True self._dataset_generator = True
self._ground_truth = False
self._gt_segments = None
def _init_dataset(self, directory): def _init_dataset(self, directory):
...@@ -125,6 +129,10 @@ class Act(object): ...@@ -125,6 +129,10 @@ class Act(object):
self.tk.append_log("Painting segment: %0.3f seconds", run_time) self.tk.append_log("Painting segment: %0.3f seconds", run_time)
self.tk.refresh_image(self._image) self.tk.refresh_image(self._image)
if self._ground_truth == True:
self._gt_segments[idx_segment] = self.classes[self._current_class]["name"].value
elif self._dataset_generator == True:
filepath = f.save_class_image(segment, self.dataset, self.classes[self._current_class]["name"].value, self._image_name, idx_segment) filepath = f.save_class_image(segment, self.dataset, self.classes[self._current_class]["name"].value, self._image_name, idx_segment)
if filepath: if filepath:
self.tk.append_log("\nSegment saved in %s", filepath) self.tk.append_log("\nSegment saved in %s", filepath)
...@@ -141,6 +149,7 @@ class Act(object): ...@@ -141,6 +149,7 @@ class Act(object):
self._const_image = self._image self._const_image = self._image
self.segmenter.reset() self.segmenter.reset()
self._gt_segments = None
def restore_image(self): def restore_image(self):
...@@ -151,6 +160,7 @@ class Act(object): ...@@ -151,6 +160,7 @@ class Act(object):
self.tk.refresh_image(self._const_image) self.tk.refresh_image(self._const_image)
self.segmenter.reset() self.segmenter.reset()
self._gt_segments = None
def close_image(self): def close_image(self):
"""Close the image. """Close the image.
...@@ -354,6 +364,8 @@ class Act(object): ...@@ -354,6 +364,8 @@ class Act(object):
self._image, run_time = self.segmenter.run(self._const_image) self._image, run_time = self.segmenter.run(self._const_image)
self.tk.append_log("Time elapsed: %0.3f seconds", run_time) self.tk.append_log("Time elapsed: %0.3f seconds", run_time)
self._gt_segments = [None]*(max(self.segmenter.get_list_segments())+1)
self.tk.refresh_image(self._image) self.tk.refresh_image(self._image)
...@@ -488,6 +500,7 @@ class Act(object): ...@@ -488,6 +500,7 @@ class Act(object):
self._image, _ = self.segmenter.run(self._const_image) self._image, _ = self.segmenter.run(self._const_image)
self.tk.refresh_image(self._image) self.tk.refresh_image(self._image)
list_segments = self.segmenter.get_list_segments() list_segments = self.segmenter.get_list_segments()
self._gt_segments = [None]*(max(list_segments)+1)
# Train the classifier ( this program does not perform the training of ConvNets ). # Train the classifier ( this program does not perform the training of ConvNets ).
if self.classifier.must_train(): if self.classifier.must_train():
...@@ -530,6 +543,9 @@ class Act(object): ...@@ -530,6 +543,9 @@ class Act(object):
self.tk.append_log("Painting segments... (%0.3f seconds)", (TimeUtils.get_time() - start_time)) self.tk.append_log("Painting segments... (%0.3f seconds)", (TimeUtils.get_time() - start_time))
# If ground truth mode, show alternative results
if self._ground_truth == True:
return self._show_ground_truth(list_segments, len_segments, labels, start_time)
# Create a popup with results of classification. # Create a popup with results of classification.
popup_info = "%s\n" % str(self.classifier.get_summary_config()) popup_info = "%s\n" % str(self.classifier.get_summary_config())
...@@ -556,6 +572,58 @@ class Act(object): ...@@ -556,6 +572,58 @@ class Act(object):
self.tk.append_log("Time elapsed: %0.3f seconds", (end_time - start_time)) self.tk.append_log("Time elapsed: %0.3f seconds", (end_time - start_time))
def _show_ground_truth(self, list_segments, len_segments, labels, start_time):
"""Paint only wrong classified segments and show ground truth confusion matrix.
Parameters
----------
list_segments : list of integer
List of index segments.
len_segments : list of integer
List of segments sizes.
labels : list of string
List of predicted class name for each segment.
start_time : floating point
Start time of classification.
"""
classes = list(set(labels))
classes.sort()
n_segments = len(labels)
spx_matrix = np.zeros((len(classes), len(classes)), np.int)
px_matrix = np.zeros((len(classes), len(classes)), np.int)
# Create the confusion matrix and paint wrong classified segments individually.
for idx_segment in list_segments:
if self._gt_segments[idx_segment] is not None:
gt_class = classes.index(self._gt_segments[idx_segment])
predicted_class = classes.index(labels[idx_segment])
spx_matrix[ gt_class ][ predicted_class ] += 1
px_matrix[ gt_class ][ predicted_class ] += len_segments[idx_segment]
if gt_class != predicted_class:
self._image, _ = self.segmenter.paint_segment(self._image, self.get_class_by_name(labels[idx_segment])["color"].value, idx_segment=[idx_segment], border=False)
# Create a popup with results of classification.
popup_info = "%s\n" % str(self.classifier.get_summary_config())
popup_info += Classifier.confusion_matrix(classes, spx_matrix, "Superpixels")
popup_info += Classifier.confusion_matrix(classes, px_matrix, "PixelSum")
self.tk.refresh_image(self._image)
self.tk.popup(popup_info)
end_time = TimeUtils.get_time()
self.tk.append_log("\nClassification finished")
self.tk.append_log("Time elapsed: %0.3f seconds", (end_time - start_time))
def toggle_ground_truth(self):
"""Enable/disable ground truth mode.
"""
self._ground_truth = not self._ground_truth
def cross_validation(self): def cross_validation(self):
"""Run a cross validation on all generated segments in image dataset. """Run a cross validation on all generated segments in image dataset.
......
...@@ -157,7 +157,7 @@ class SkimageSegmenter(object): ...@@ -157,7 +157,7 @@ class SkimageSegmenter(object):
idx_segment = [self._segments[py, px]] idx_segment = [self._segments[py, px]]
height, width, channels = self._original_image.shape height, width, channels = self._original_image.shape
# Create a mask, painting black all pixels outside of segment and white the pixels inside # Create a mask, painting black all pixels outside of segments and white the pixels inside
mask_segment = np.zeros(self._original_image.shape[:2], dtype="uint8") mask_segment = np.zeros(self._original_image.shape[:2], dtype="uint8")
for idx in idx_segment: for idx in idx_segment:
mask_segment[self._segments == idx] = 255 mask_segment[self._segments == idx] = 255
...@@ -172,7 +172,7 @@ class SkimageSegmenter(object): ...@@ -172,7 +172,7 @@ class SkimageSegmenter(object):
colored_image = cv2.addWeighted(image, 0.7, class_color, 0.3, 0) colored_image = cv2.addWeighted(image, 0.7, class_color, 0.3, 0)
colored_image = cv2.bitwise_and(colored_image, colored_image, mask=mask_segment) colored_image = cv2.bitwise_and(colored_image, colored_image, mask=mask_segment)
# Create a new image keeping the painting only in pixels inside of segment # Create a new image keeping the painting only in pixels inside of segments
new_image = image if clear == False else self._original_image new_image = image if clear == False else self._original_image
new_image = cv2.bitwise_and(new_image, new_image, mask=mask_inv) new_image = cv2.bitwise_and(new_image, new_image, mask=mask_inv)
mask_segment[:] = 255 mask_segment[:] = 255
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment