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.
### 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:
......
from extractor import Extractor
from feature_extraction import FeatureExtractor
from color_summarizer import ColorStats
from glcm import GLCM
from hog import HOG
from image_moments import ImageMoments
from lbp import LBP
from .extractor import Extractor
from .feature_extraction import FeatureExtractor
from .color_summarizer import ColorStats
from .glcm import GLCM
from .hog import HOG
from .image_moments import RawCentralMoments, HuMoments
from .lbp import LBP
__all__ = ["extractor",
"color_summarizer",
......@@ -18,13 +18,14 @@ from collections import OrderedDict
from util.config import Config
_extractor_list = OrderedDict( {
"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),
"image_moments" : Config("Image Moments (Hu)", True, bool, meta=ImageMoments),
"lbp" : Config("Local Binary Patterns", True, bool, meta=LBP)
} )
_extractor_list = OrderedDict( [
["color_summarizer", Config("Color Statistics", True, bool, meta=ColorStats)],
["glcm", Config("Gray-Level Co-Occurrence Matrix", True, bool, meta=GLCM)],
["hog", Config("Histogram of Oriented Gradients", True, bool, meta=HOG)],
["hu_moments", Config("Hu Image Moments", True, bool, meta=HuMoments)],
["rc_moments", Config("Image Moments (Raw/Central)", False, bool, meta=RawCentralMoments)],
["lbp", Config("Local Binary Patterns", True, bool, meta=LBP)]
] )
def get_extractor_config():
return _extractor_list
......@@ -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["glcm"] = Config.nvl_config(configs["glcm"], _extractor_list["glcm"])
_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"])
......@@ -80,7 +80,7 @@ class FeatureExtractor(object):
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\n" % ('@attribute','classe',', '.join(classes)))
......
......@@ -13,7 +13,7 @@ from util.utils import ImageUtils
from extractor import Extractor
class ImageMoments(Extractor):
class RawCentralMoments(Extractor):
def __init__(self):
......@@ -37,15 +37,40 @@ class ImageMoments(Extractor):
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 = 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)
hu = measure.moments_hu(nu)
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 = labels_m + labels_mu + labels_hu
labels = labels_hu
types = [Extractor.NUMERIC] * len(labels)
values = values_m + values_mu + values_hu
values = values_hu
return labels, types, values
from interface import Interface, InterfaceException
from tk_interface import TkInterface
from .interface import Interface, InterfaceException
from .tk_interface import TkInterface
__all__ = ["interface",
"tk_interface"]
\ No newline at end of file
from tk_canvas import Image
from tk_config import TkConfig
from tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog, SelectDialog
from tk_customframe import CustomGrid
from tk_logger import Log
from tk_menu import Menu
from tk_itemmenu import ItemMenu, Command, Separator, CheckButton
from tk_utils import Utils
from .tk_canvas import Image
from .tk_config import TkConfig
from .tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog, SelectDialog
from .tk_customframe import CustomGrid
from .tk_logger import Log
from .tk_menu import Menu
from .tk_itemmenu import ItemMenu, Command, Separator, CheckButton
from .tk_utils import Utils
__all__ = ["tk_canvas",
"tk_config",
......
......@@ -186,7 +186,7 @@ class Act(object):
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()))
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)
self.tk.dialogue_choose_one(title, current_config, process_config)
......
from segmenter import Segmenter
from slic import Slic
from .segmenter import Segmenter
from .felzenszwalb import Felzenszwalb
from .quickshift import Quickshift
from .slic import Slic
__all__ = ["segmenter",
"felzenszwalb"
"quickshift"
"slic"]
......@@ -9,13 +13,17 @@ from collections import OrderedDict
from util.config import Config
_segmenter_list = OrderedDict( {
"slic" : Config(Slic().get_name(), True, bool, meta=Slic),
"invalid" : Config("Invalid", False, bool, meta=None, hidden=True)
} )
_segmenter_list = OrderedDict( [
["felzenszwalb", Config(Felzenszwalb().get_name(), False, bool, meta=Felzenszwalb)],
["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():
return _segmenter_list
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"])
#!/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 @@
"""
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
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
import cv2
import numpy as np
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 util.config import Config
......@@ -20,20 +18,16 @@ from util.utils import TimeUtils
from util.x11_colors import X11Colors
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.sigma = Config("Sigma", sigma, 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):
......@@ -73,92 +67,18 @@ class Slic(Segmenter):
def get_segment(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)
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):
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