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

Pynovisao - Adicionando segmentadores Felzenszwalb e Quickshift

parent b1450a8c
...@@ -96,9 +96,9 @@ Pacote de Visão Computacional do Inovisão. ...@@ -96,9 +96,9 @@ Pacote de Visão Computacional do Inovisão.
### Ubuntu ### Ubuntu
``` ```
$ sudo apt-get install tk tk-dev $ sudo apt-get install tk tk-dev
``` ```
Na ocorrência do erro 'cannot import name _tkagg', tentar os seguintes comandos: Na ocorrência do erro 'cannot import name _tkagg', tentar os seguintes comandos:
......
from extractor import Extractor from .extractor import Extractor
from feature_extraction import FeatureExtractor from .feature_extraction import FeatureExtractor
from color_summarizer import ColorStats from .color_summarizer import ColorStats
from glcm import GLCM from .glcm import GLCM
from hog import HOG from .hog import HOG
from image_moments import ImageMoments from .image_moments import RawCentralMoments, HuMoments
from lbp import LBP from .lbp import LBP
__all__ = ["extractor", __all__ = ["extractor",
"color_summarizer", "color_summarizer",
...@@ -18,13 +18,14 @@ from collections import OrderedDict ...@@ -18,13 +18,14 @@ from collections import OrderedDict
from util.config import Config from util.config import Config
_extractor_list = OrderedDict( { _extractor_list = OrderedDict( [
"color_summarizer" : Config("Color Statistics", True, bool, meta=ColorStats), ["color_summarizer", Config("Color Statistics", True, bool, meta=ColorStats)],
"hog" : Config("Histogram of Oriented Gradients", True, bool, meta=HOG), ["glcm", Config("Gray-Level Co-Occurrence Matrix", True, bool, meta=GLCM)],
"glcm" : Config("Gray-Level Co-Occurrence Matrix", True, bool, meta=GLCM), ["hog", Config("Histogram of Oriented Gradients", True, bool, meta=HOG)],
"image_moments" : Config("Image Moments (Hu)", True, bool, meta=ImageMoments), ["hu_moments", Config("Hu Image Moments", True, bool, meta=HuMoments)],
"lbp" : Config("Local Binary Patterns", True, bool, meta=LBP) ["rc_moments", Config("Image Moments (Raw/Central)", False, bool, meta=RawCentralMoments)],
} ) ["lbp", Config("Local Binary Patterns", True, bool, meta=LBP)]
] )
def get_extractor_config(): def get_extractor_config():
return _extractor_list return _extractor_list
...@@ -33,5 +34,6 @@ def set_extractor_config(configs): ...@@ -33,5 +34,6 @@ def set_extractor_config(configs):
_extractor_list["color_summarizer"] = Config.nvl_config(configs["color_summarizer"], _extractor_list["color_summarizer"]) _extractor_list["color_summarizer"] = Config.nvl_config(configs["color_summarizer"], _extractor_list["color_summarizer"])
_extractor_list["glcm"] = Config.nvl_config(configs["glcm"], _extractor_list["glcm"]) _extractor_list["glcm"] = Config.nvl_config(configs["glcm"], _extractor_list["glcm"])
_extractor_list["hog"] = Config.nvl_config(configs["hog"], _extractor_list["hog"]) _extractor_list["hog"] = Config.nvl_config(configs["hog"], _extractor_list["hog"])
_extractor_list["image_moments"] = Config.nvl_config(configs["image_moments"], _extractor_list["image_moments"]) _extractor_list["hu_moments"] = Config.nvl_config(configs["hu_moments"], _extractor_list["hu_moments"])
_extractor_list["rc_moments"] = Config.nvl_config(configs["rc_moments"], _extractor_list["rc_moments"])
_extractor_list["lbp"] = Config.nvl_config(configs["lbp"], _extractor_list["lbp"]) _extractor_list["lbp"] = Config.nvl_config(configs["lbp"], _extractor_list["lbp"])
...@@ -80,7 +80,7 @@ class FeatureExtractor(object): ...@@ -80,7 +80,7 @@ class FeatureExtractor(object):
arff.write("%s %s\n\n" % ('@relation ', relation)) arff.write("%s %s\n\n" % ('@relation ', relation))
for label, t in zip(labels,types): for label, t in zip(labels, types):
arff.write("%s %s %s\n" % ('@attribute', label, t)) arff.write("%s %s %s\n" % ('@attribute', label, t))
arff.write("%s %s {%s}\n\n" % ('@attribute','classe',', '.join(classes))) arff.write("%s %s {%s}\n\n" % ('@attribute','classe',', '.join(classes)))
......
...@@ -13,7 +13,7 @@ from util.utils import ImageUtils ...@@ -13,7 +13,7 @@ from util.utils import ImageUtils
from extractor import Extractor from extractor import Extractor
class ImageMoments(Extractor): class RawCentralMoments(Extractor):
def __init__(self): def __init__(self):
...@@ -37,15 +37,40 @@ class ImageMoments(Extractor): ...@@ -37,15 +37,40 @@ class ImageMoments(Extractor):
values_mu = [mu[p, q] for (p, q) in self._moments_order] values_mu = [mu[p, q] for (p, q) in self._moments_order]
labels_mu = [M+str(p)+str(q) for M,(p,q) in zip(['Mu_'] * len(self._moments_order), self._moments_order)] labels_mu = [M+str(p)+str(q) for M,(p,q) in zip(['Mu_'] * len(self._moments_order), self._moments_order)]
labels = labels_m + labels_mu
types = [Extractor.NUMERIC] * len(labels)
values = values_m + values_mu
return labels, types, values
class HuMoments(Extractor):
def __init__(self):
pass
def run(self, image):
image_grayscale = ImageUtils.image_grayscale(image, bgr = True)
m = measure.moments(image_grayscale)
row = m[0, 1] / m[0, 0]
col = m[1, 0] / m[0, 0]
mu = measure.moments_central(image_grayscale, row, col)
nu = measure.moments_normalized(mu) nu = measure.moments_normalized(mu)
hu = measure.moments_hu(nu) hu = measure.moments_hu(nu)
values_hu = list(hu) values_hu = list(hu)
labels_hu = [m+n for m,n in zip(['Hu_'] * len(values_hu),map(str,range(0,len(values_hu))))] labels_hu = [m+n for m,n in zip(['Hu_'] * len(values_hu),map(str,range(0,len(values_hu))))]
labels = labels_m + labels_mu + labels_hu labels = labels_hu
types = [Extractor.NUMERIC] * len(labels) types = [Extractor.NUMERIC] * len(labels)
values = values_m + values_mu + values_hu values = values_hu
return labels, types, values return labels, types, values
from interface import Interface, InterfaceException from .interface import Interface, InterfaceException
from tk_interface import TkInterface from .tk_interface import TkInterface
__all__ = ["interface", __all__ = ["interface",
"tk_interface"] "tk_interface"]
\ No newline at end of file
from tk_canvas import Image from .tk_canvas import Image
from tk_config import TkConfig from .tk_config import TkConfig
from tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog, SelectDialog from .tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog, SelectDialog
from tk_customframe import CustomGrid from .tk_customframe import CustomGrid
from tk_logger import Log from .tk_logger import Log
from tk_menu import Menu from .tk_menu import Menu
from tk_itemmenu import ItemMenu, Command, Separator, CheckButton from .tk_itemmenu import ItemMenu, Command, Separator, CheckButton
from tk_utils import Utils from .tk_utils import Utils
__all__ = ["tk_canvas", __all__ = ["tk_canvas",
"tk_config", "tk_config",
......
...@@ -186,7 +186,7 @@ class Act(object): ...@@ -186,7 +186,7 @@ class Act(object):
self.segmenter = [new_config[segmenter].meta for segmenter in new_config self.segmenter = [new_config[segmenter].meta for segmenter in new_config
if new_config[segmenter].value == True ][0]() if new_config[segmenter].value == True ][0]()
self.tk.append_log("\nConfig updated:\nSegmenter: %s", str(self.segmenter.get_name())) self.tk.append_log("\nSegmenter: %s\n%s", str(self.segmenter.get_name()), str(self.segmenter.get_summary_config()))
segmentation.set_segmenter_config(new_config) segmentation.set_segmenter_config(new_config)
self.tk.dialogue_choose_one(title, current_config, process_config) self.tk.dialogue_choose_one(title, current_config, process_config)
......
from segmenter import Segmenter from .segmenter import Segmenter
from slic import Slic from .felzenszwalb import Felzenszwalb
from .quickshift import Quickshift
from .slic import Slic
__all__ = ["segmenter", __all__ = ["segmenter",
"felzenszwalb"
"quickshift"
"slic"] "slic"]
...@@ -9,13 +13,17 @@ from collections import OrderedDict ...@@ -9,13 +13,17 @@ from collections import OrderedDict
from util.config import Config from util.config import Config
_segmenter_list = OrderedDict( { _segmenter_list = OrderedDict( [
"slic" : Config(Slic().get_name(), True, bool, meta=Slic), ["felzenszwalb", Config(Felzenszwalb().get_name(), False, bool, meta=Felzenszwalb)],
"invalid" : Config("Invalid", False, bool, meta=None, hidden=True) ["quickshift", Config(Quickshift().get_name(), False, bool, meta=Quickshift)],
} ) ["slic", Config(Slic().get_name(), True, bool, meta=Slic)],
["invalid", Config("Invalid", False, bool, meta=None, hidden=True)]
] )
def get_segmenter_config(): def get_segmenter_config():
return _segmenter_list return _segmenter_list
def set_segmenter_config(configs): def set_segmenter_config(configs):
_segmenter_list["felzenszwalb"] = Config.nvl_config(configs["felzenszwalb"], _segmenter_list["felzenszwalb"])
_segmenter_list["quickshift"] = Config.nvl_config(configs["quickshift"], _segmenter_list["quickshift"])
_segmenter_list["slic"] = Config.nvl_config(configs["slic"], _segmenter_list["slic"]) _segmenter_list["slic"] = Config.nvl_config(configs["slic"], _segmenter_list["slic"])
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Runs Segmenter Felzenszwalb's method implemented in skimage.segmentation.
Efficient graph-based image segmentation, Felzenszwalb, P.F. and Huttenlocher, D.P. International Journal of Computer Vision, 2004
Name: felzenszwalb.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from skimage.segmentation import felzenszwalb
from collections import OrderedDict
from util.config import Config
from segmenter import Segmenter
from skimage_segmenter import SkimageSegmenter
class Felzenszwalb(Segmenter, SkimageSegmenter):
def __init__(self, scale = 100.0, sigma = 1.0, min_size = 20, border_color = 'Yellow', border_outline = 'No'):
super(self.__class__, self).__init__(border_color, border_outline)
self.scale = Config("Scale", scale, float)
self.sigma = Config("Sigma", sigma, float)
self.min_size = Config("Min Size", min_size, int)
def get_config(self):
felzenszwalb_config = OrderedDict()
felzenszwalb_config["scale"] = self.scale
felzenszwalb_config["sigma"] = self.sigma
felzenszwalb_config["min_size"] = self.min_size
felzenszwalb_config["border_color"] = self.border_color
felzenszwalb_config["border_outline"] = self.border_outline
return felzenszwalb_config
def set_config(self, configs):
self.scale = Config.nvl_config(configs["scale"], self.scale)
self.sigma = Config.nvl_config(configs["sigma"], self.sigma)
self.min_size = Config.nvl_config(configs["min_size"], self.min_size)
self.border_color = Config.nvl_config(configs["border_color"], self.border_color)
self.border_outline = Config.nvl_config(configs["border_outline"], self.border_outline)
self.border_outline.value = self.border_outline.value if self.border_outline.value == 'Yes' else 'No'
def get_summary_config(self):
felzenszwalb_config = OrderedDict()
felzenszwalb_config[self.scale.label] = self.scale.value
felzenszwalb_config[self.sigma.label] = self.sigma.value
felzenszwalb_config[self.min_size.label] = self.min_size.value
felzenszwalb_config[self.border_color.label] = self.border_color.value
felzenszwalb_config[self.border_outline.label] = self.border_outline.value
summary = ''
for config in felzenszwalb_config:
summary += "%s: %s\n" % (config, str(felzenszwalb_config[config]))
return summary
def get_segment(self, px = 0, py = 0, idx_segment = None):
return self.get_segment_skimage(px, py, idx_segment)
def paint_segment(self, image, color, px = 0, py = 0, idx_segment = None, border = True, clear = False):
return self.paint_segment_skimage(image, color, px, py, idx_segment, border, clear)
def run(self, image):
args = { "scale": self.scale.get_cast_val(),
"sigma": self.sigma.get_cast_val(),
"min_size": self.min_size.get_cast_val()
}
return self.run_skimage(image, felzenszwalb, **args)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Runs Segmenter Quickshift implemented in skimage.segmentation.
Quick shift and kernel methods for mode seeking, Vedaldi, A. and Soatto, S. European Conference on Computer Vision, 2008
Name: quickshift.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from skimage.segmentation import quickshift
from collections import OrderedDict
from util.config import Config
from segmenter import Segmenter
from skimage_segmenter import SkimageSegmenter
class Quickshift(Segmenter, SkimageSegmenter):
def __init__(self, ratio = 0.5, kernel_size = 2.0, max_dist = 10.0, border_color = 'Yellow', border_outline = 'No'):
super(self.__class__, self).__init__(border_color, border_outline)
self.ratio = Config("Ratio [0-1]", ratio, float)
self.kernel_size = Config("Kernel Size", kernel_size, float)
#self.sigma = Config("Sigma", sigma, float)
self.max_dist = Config("Max Dist", max_dist, float)
def get_config(self):
quickshift_config = OrderedDict()
quickshift_config["ratio"] = self.ratio
quickshift_config["kernel_size"] = self.kernel_size
#quickshift_config["sigma"] = self.sigma
quickshift_config["max_dist"] = self.max_dist
quickshift_config["border_color"] = self.border_color
quickshift_config["border_outline"] = self.border_outline
return quickshift_config
def set_config(self, configs):
self.ratio = Config.nvl_config(configs["ratio"], self.ratio)
self.kernel_size = Config.nvl_config(configs["kernel_size"], self.kernel_size)
#self.sigma = Config.nvl_config(configs["sigma"], self.sigma)
self.max_dist = Config.nvl_config(configs["max_dist"], self.max_dist)
self.border_color = Config.nvl_config(configs["border_color"], self.border_color)
self.border_outline = Config.nvl_config(configs["border_outline"], self.border_outline)
self.ratio.value = self.ratio.value if self.ratio.value <= 1 else 1
self.border_outline.value = self.border_outline.value if self.border_outline.value == 'Yes' else 'No'
def get_summary_config(self):
quickshift_config = OrderedDict()
quickshift_config[self.ratio.label] = self.ratio.value
quickshift_config[self.kernel_size.label] = self.kernel_size.value
#quickshift_config[self.sigma.label] = self.sigma.value
quickshift_config[self.max_dist.label] = self.max_dist.value
quickshift_config[self.border_color.label] = self.border_color.value
quickshift_config[self.border_outline.label] = self.border_outline.value
summary = ''
for config in quickshift_config:
summary += "%s: %s\n" % (config, str(quickshift_config[config]))
return summary
def get_segment(self, px = 0, py = 0, idx_segment = None):
return self.get_segment_skimage(px, py, idx_segment)
def paint_segment(self, image, color, px = 0, py = 0, idx_segment = None, border = True, clear = False):
return self.paint_segment_skimage(image, color, px, py, idx_segment, border, clear)
def run(self, image):
args = { "ratio": self.ratio.get_cast_val(),
"kernel_size": self.kernel_size.get_cast_val(),
#"sigma": self.sigma.get_cast_val(),
"max_dist": self.max_dist.get_cast_val()
}
return self.run_skimage(image, quickshift, **args)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Abstract class for segmenters implemented in skimage.segmentation.
Name: skimage_segmenter.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
import cv2
import numpy as np
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float, img_as_ubyte
from util.config import Config
from util.utils import TimeUtils
from util.x11_colors import X11Colors
from abc import ABCMeta, abstractmethod
class SkimageSegmenter(object):
__metaclass__ = ABCMeta
def __init__(self, border_color = 'Yellow', border_outline = 'No'):
self.border_color = Config("Border Color", border_color, 'color')
self.border_outline = Config("Border Outline", border_outline, str)
self._segments = None
self._original_image = None
def get_segment_skimage(self, px = 0, py = 0, idx_segment = None):
if self._segments is None:
return None, 0, -1, 0
start_time = TimeUtils.get_time()
if idx_segment is None:
idx_segment = self._segments[py, px]
mask_segment = np.zeros(self._original_image.shape[:2], dtype="uint8")
mask_segment[self._segments == idx_segment] = 255
size_segment = mask_segment[self._segments == idx_segment].size
segment = self._original_image.copy()
segment = cv2.bitwise_and(segment, segment, mask=mask_segment)
contours, _ = cv2.findContours(mask_segment,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2:]
m = -1
max_contour = None
for cnt in contours:
if (len(cnt) > m):
m = len(cnt)
max_contour = cnt
x,y,w,h = cv2.boundingRect(max_contour)
segment = segment[y:y+h, x:x+w]
end_time = TimeUtils.get_time()
return segment, size_segment, idx_segment, (end_time - start_time)
def paint_segment_skimage(self, image, color, px = 0, py = 0, idx_segment = None, border = True, clear = False):
if self._segments is None:
return image, 0
start_time = TimeUtils.get_time()
if idx_segment is None:
idx_segment = self._segments[py, px]
height, width, channels = self._original_image.shape
mask_segment = np.zeros(self._original_image.shape[:2], dtype="uint8")
mask_segment[self._segments == idx_segment] = 255
mask_inv = cv2.bitwise_not(mask_segment)
class_color = np.zeros((height,width,3), np.uint8)
class_color[:, :] = X11Colors.get_color(color)
if clear == False:
colored_image = cv2.addWeighted(self._original_image, 0.7, class_color, 0.3, 0)
else:
colored_image = self._original_image
colored_image = cv2.bitwise_and(colored_image, colored_image, mask=mask_segment)
new_image = cv2.bitwise_and(image, image, mask=mask_inv)
mask_segment[:] = 255
new_image = cv2.bitwise_or(new_image, colored_image, mask=mask_segment)
if border == True:
color = X11Colors.get_color_zero_one(self.border_color.get_cast_val())
outline_color = color if self.border_outline.value == 'Yes' else None
new_image = img_as_ubyte( mark_boundaries(img_as_float(new_image), self._segments.astype(np.int8), color=color, outline_color=outline_color) )
end_time = TimeUtils.get_time()
return new_image, (end_time - start_time)
def run_skimage(self, image, method, **kwargs):
self._original_image = image
start_time = TimeUtils.get_time()
self._segments = method(img_as_float(image), **kwargs)
end_time = TimeUtils.get_time()
color = X11Colors.get_color_zero_one(self.border_color.get_cast_val())
outline_color = color if self.border_outline.value == 'Yes' else None
# Ignore UserWarning: Possible precision loss when converting from float64 to uint8
# because the returned image is used just for visualization
# The original image, without loss, is stored in self._original_image
return img_as_ubyte( mark_boundaries(image, self._segments.astype(np.int8), color=color, outline_color=outline_color) ), (end_time - start_time)
...@@ -4,15 +4,13 @@ ...@@ -4,15 +4,13 @@
""" """
Runs Segmenter SLIC (Simple Linear Iterative Clustering) implemented in skimage.segmentation. Runs Segmenter SLIC (Simple Linear Iterative Clustering) implemented in skimage.segmentation.
Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Suesstrunk, SLIC Superpixels Compared to State-of-the-art Superpixel Methods, TPAMI, May 2012.
Name: slic.py Name: slic.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com ) Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
""" """
import cv2
import numpy as np
from skimage.segmentation import slic from skimage.segmentation import slic
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float, img_as_ubyte
from collections import OrderedDict from collections import OrderedDict
from util.config import Config from util.config import Config
...@@ -20,20 +18,16 @@ from util.utils import TimeUtils ...@@ -20,20 +18,16 @@ from util.utils import TimeUtils
from util.x11_colors import X11Colors from util.x11_colors import X11Colors
from segmenter import Segmenter from segmenter import Segmenter
from skimage_segmenter import SkimageSegmenter
class Slic(Segmenter): class Slic(Segmenter, SkimageSegmenter):
def __init__(self, n_segments = 250, sigma = 5.0, compactness = 10.0, border_color = 'Yellow', border_outline = 'No'):
super(self.__class__, self).__init__(border_color, border_outline)
def __init__(self, n_segments = 100, sigma = 5.0, compactness = 10.0, border_color = 'Yellow', border_outline = 'No'):
self.n_segments = Config("Segments", n_segments, int) self.n_segments = Config("Segments", n_segments, int)
self.sigma = Config("Sigma", sigma, float) self.sigma = Config("Sigma", sigma, float)
self.compactness = Config("Compactness", compactness, float) self.compactness = Config("Compactness", compactness, float)
self.border_color = Config("Border Color", border_color, 'color')
self.border_outline = Config("Border Outline", border_outline, str)
self._segments = None
self._original_image = None
def get_config(self): def get_config(self):
...@@ -73,92 +67,18 @@ class Slic(Segmenter): ...@@ -73,92 +67,18 @@ class Slic(Segmenter):