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

Pynovisao - Adicionando extratores de atributos

parent 56c1db36
from extractor import Extractor
from color_summarizer import ColorStats
from hog import HOG
from image_moments import ImageMoments
from lbp import LBP
__all__ = ["extractor",
"color_summarizer",
"hog",
"image_moments",
"lbp"]
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),
"image_moments" : Config("Image Moments (Hu)", True, bool, meta=ImageMoments),
"lbp" : Config("Local Binary Patterns", True, bool, meta=LBP)
} )
def get_extractor_config():
return _extractor_list
def set_extractor_config(configs):
_extractor_list["color_summarizer"] = Config.nvl_config(configs["color_summarizer"], _extractor_list["color_summarizer"])
_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["lbp"] = Config.nvl_config(configs["lbp"], _extractor_list["lbp"])
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Calculate min, max, mean and standard deviation for color channels RGB, HSV and CIELab.
Name: color_summarizer.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
import cv2
from util.utils import ImageUtils
from extractor import Extractor
class ColorStats(Extractor):
def __init__(self, image, image_bgr = None, image_hsv = None, image_cielab = None):
if image_bgr is None:
image_bgr = ImageUtils.image_to_bgr(image)
if image_hsv is None:
image_hsv = ImageUtils.image_to_hsv(image_bgr, bgr = True)
if image_cielab is None:
image_cielab = ImageUtils.image_to_cielab(image_bgr, bgr = True)
super(self.__class__, self).__init__(image=image, image_bgr=image_bgr, image_hsv=image_hsv, image_cielab=image_cielab)
def run(self):
imagemHSV = cv2.cvtColor(self.imagem, cv2.COLOR_BGR2HSV)
imagemCIELab = cv2.cvtColor(self.imagem, cv2.COLOR_BGR2LAB)
b, g, r = cv2.split(self.imagem_bgr)
h, s, v = cv2.split(self.imagem_hsv)
ciel, ciea, cieb = cv2.split(self.imagem_cielab)
labels = [
'cor_rmin', 'cor_rmax', 'cor_rmediamedia', 'cor_rdesvio',
'cor_gmin', 'cor_gmax', 'cor_gmedia', 'cor_gdesvio',
'cor_bmin', 'cor_bmax', 'cor_bmedia', 'cor_bdesvio',
'cor_hmin', 'cor_hmax', 'cor_hmedia', 'cor_hdesvio',
'cor_smin', 'cor_smax', 'cor_smedia', 'cor_sdesvio',
'cor_vmin', 'cor_vmax', 'cor_vmedia', 'cor_vdesvio',
'cor_cielmin', 'cor_cielmax', 'cor_cielmedia', 'cor_cieldesvio',
'cor_cieamin', 'cor_cieamax', 'cor_cieamedia', 'cor_cieadesvio',
'cor_ciebmin', 'cor_ciebmax', 'cor_ciebmedia', 'cor_ciebdesvio'
]
tipos = [Extractor.NUMERIC] * len(labels)
values = [
np.min(r), np.max(r), np.mean(r), np.std(r),
np.min(g), np.max(g), np.mean(g), np.std(g),
np.min(b), np.max(b), np.mean(b), np.std(b),
np.min(h), np.max(h), np.mean(h), np.std(h),
np.min(s), np.max(s), np.mean(s), np.std(s),
np.min(v), np.max(v), np.mean(v), np.std(v),
np.min(ciel), np.max(ciel), np.mean(ciel), np.std(ciel),
np.min(ciea), np.max(ciea), np.mean(ciea), np.std(ciea),
np.min(cieb), np.max(cieb), np.mean(cieb), np.std(cieb)
]
return labels, types, values
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Abstract class for feature extraction algorithms.
Name: extractor.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from abc import ABCMeta, abstractmethod
class Extractor(object):
__metaclass__ = ABCMeta
NUMERIC = 'numeric'
NOMINAL = 'nominal'
def __init__(self,
image = None,
image_bgr = None,
image_hsv = None,
image_cielab = None,
image_grayscale = None,
image_binary = None,
image_edge = None,
image_128x128 = None):
self.image = image
self.image_bgr = image_bgr
self.image_hsv = image_hsv
self.image_cielab = image_cielab
self.image_grayscale = image_grayscale
self.image_binary = image_binary
self.image_edge = image_edge
self.image_128x128 = image_128x128
@staticmethod
def get_name(self):
return self.__class__.__name__
@abstractmethod
def run(self):
pass
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Extract HOG (Histogram of Oriented Gradient) feature.
Name: hog.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from skimage import feature
from util.utils import ImageUtils
from extractor import Extractor
class HOG(Extractor):
def __init__(self, image, image_128x128 = None):
if image_128x128 is None:
image_128x128 = ImageUtils.image_resize( ImageUtils.image_to_bgr(image), 128, 128)
super(self.__class__, self).__init__(image=image, image_128x128=image_128x128)
def run(self):
labels = [m+n for m,n in zip(['hog_'] * len(valores),map(str,range(0,len(valores))))]
types = [Extractor.NUMERIC] * len(labels)
values, _ = feature.hog(self.image_128x128, orientations=8, pixels_per_cell=(32, 32),
cells_per_block=(1, 1), visualise=True)
return labels, types, list(values)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Calculate raw, central and Hu's set of image moments.
Name: image_moments.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from skimage import measure
from util.utils import ImageUtils
from extractor import Extractor
class ImageMoments(Extractor):
def __init__(self, image, image_grayscale = None):
if image_grayscale is None:
image_grayscale = ImageUtils.image_grayscale(image)
super(self.__class__, self).__init__(image=image, image_grayscale=image)
self._moments_order = [(0, 1), (1, 0), (1, 1), (0, 2), (2, 0)]
def run(self):
m = measure.moments(self.image_grayscale)
values_m = [m[p, q] for (p, q) in self._moments_order]
labels_m = [M+str(p)+str(q) for M,(p,q) in zip(['M_'] * len(self._moments_order), self._moments_order)]
row = m[0, 1] / m[0, 0]
col = m[1, 0] / m[0, 0]
mu = measure.moments_central(self.image_grayscale, row, col)
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)]
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(valores_hu),map(str,range(0,len(valores_hu))))]
values = values_m + values_mu + values_hu
labels = labels_m + labels_mu + labels_hu
types = [Extractor.NUMERIC] * len(labels)
return labels, types, values
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
"""
Extract LBP (Local Binary Patterns) feature.
Name: lpb.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
from skimage import feature
from util.utils import ImageUtils
from extractor import Extractor
class LBP(Extractor):
def __init__(self, image, image_grayscale = None, lbp_radius = 2, n_bins = 18):
if image_grayscale is None:
image_grayscale = ImageUtils.image_grayscale(image)
super(self.__class__, self).__init__(image=image, image_grayscale=image)
self.lbp_radius = lbp_radius
self.n_bins = n_bins
def run(self):
labels = [m+n for m,n in zip(['lbp_'] * len(valores),map(str,range(0,len(valores))))]
types = [Extractor.NUMERIC] * len(labels)
lbp = feature.local_binary_pattern(self.image_grayscale, 8 * self.lbp_radius, self.lbp_radius, 'uniform')
valuess, _ = np.histogram(lbp, normed=True, bins=self.n_bins, range=(0, self.n_bins))
return labels, types, list(values)
from tk_canvas import Image
from tk_config import TkConfig
from tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog
from tk_customdialog import SimpleDialog, ConfigDialog, ChooseOneDialog, SelectDialog
from tk_customframe import CustomGrid
from tk_logger import Log
from tk_menu import Menu
......
......@@ -103,7 +103,6 @@ class ChooseOneDialog(SimpleDialog):
self._configs = OrderedDict()
for key in configs:
if configs[key].hidden == False:
Tk.Label(self, text=configs[key].label).grid(row=row, padx=4, pady=4, sticky=Tk.W)
radio = Tk.Radiobutton(self, text=configs[key].label, value=key, variable=self.v, width=25,
bg='white', fg='black', padx=4, pady=4, indicatoron=1, anchor=Tk.W,
......@@ -135,3 +134,52 @@ class ChooseOneDialog(SimpleDialog):
def get_configs(self):
return self._configs
class SelectDialog(SimpleDialog):
def __init__(self, parent, title = None, configs = None, command_ok = None):
SimpleDialog.__init__(self, parent, title, command_ok)
self._configs = None
if configs is not None:
self.add_configs(configs, command_ok)
def add_configs(self, configs, command_ok):
row = 0
self._configs = OrderedDict()
for key in configs:
if configs[key].hidden == False:
entry = Tk.IntVar()
c = Tk.Checkbutton(self, text=configs[key].label, variable=entry, onvalue=True, offvalue=None, width=25,
bg='white', fg='black', padx=4, pady=4, anchor=Tk.W,
activebackground='white', activeforeground='black', highlightbackground='white')
c.grid(row=row, padx=4, pady=4, sticky=Tk.W)
if configs[key].value == True:
c.select()
row += 1
self._configs[key] = TkConfig(configs[key].label, configs[key].value, c_type=configs[key].c_type, tk_entry=entry, hidden=configs[key].hidden, meta=configs[key].meta)
else:
self._configs[key] = TkConfig(configs[key].label, configs[key].value, c_type=configs[key].c_type, hidden=configs[key].hidden, meta=configs[key].meta )
B1 = Tk.Button(self, text="Ok", width=5, command = command_ok)
B1.grid(row=row, padx=6, pady=6, sticky=Tk.W+Tk.E)
self.bind("<Return>", command_ok)
#B2 = Tk.Button(self, text="Cancel", width=5, command = self.destroy)
#B2.grid(row=row+1, column=0, padx=6, pady=6, sticky=Tk.W)
self.bind("<Escape>", lambda *_: self.destroy())
def update_and_validate_configs(self):
for key in self._configs:
self._configs[key].value = self._configs[key].get_entry_val()
def get_configs(self):
return self._configs
......@@ -4,7 +4,7 @@
"""
Implements graphical interface using Tkinter package modules.
Name: main.py
Name: tk_interface.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
......@@ -173,6 +173,9 @@ class TkInterface(Interface):
def dialogue_choose_one(self, title, configs, callback):
self._conf_dialog = tk_local.ChooseOneDialog(self._root, title, configs, command_ok = lambda *_: self._apply( callback ))
def dialogue_select(self, title, configs, callback):
self._conf_dialog = tk_local.SelectDialog(self._root, title, configs, command_ok = lambda *_: self._apply( callback ))
def get_config_and_destroy(self):
if self._conf_dialog is None:
return None
......@@ -188,7 +191,8 @@ class TkInterface(Interface):
return configs
except:
self._conf_dialog.destroy()
raise IException("Illegal values, please try again")
#raise IException("Illegal values, please try again")
raise
def show_error(self, fmt, *args):
......
......@@ -50,9 +50,9 @@ if __name__ == "__main__":
tk.add_command("Execute", act.run_segmenter, 'S')
tk.add_menu("Feature Extraction")
tk.add_command("Configure", act.func_not_available)
tk.add_command("Select extractors", act.select_extractors, 'e')
tk.add_separator()
tk.add_command("Execute", act.func_not_available, 'E')
tk.add_command("Execute", act.func_not_available, 'F')
tk.add_menu("Classification")
tk.add_command("Configure", act.func_not_available)
......
......@@ -14,6 +14,7 @@ import interface
from interface.interface import InterfaceException as IException
import segmentation
import extraction
import util
from util.config import Config
......@@ -27,6 +28,9 @@ class Act(object):
self.segmenter = [segmentation._segmenter_list[segmenter].meta for segmenter in segmentation._segmenter_list
if segmentation._segmenter_list[segmenter].value == True ][0]()
self.extractors = [extraction._extractor_list[extractor].meta for extractor in extraction._extractor_list
if extraction._extractor_list[extractor].value == True ]
self._image = None
self._const_image = None
......@@ -215,6 +219,27 @@ class Act(object):
self.tk.refresh_image(self._image)
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)
def func_not_available(self):
self.tk.write_log("This functionality is not available right now.")
......@@ -22,12 +22,7 @@ from util.x11_colors import X11Colors
from segmenter import Segmenter
class Slic(Segmenter):
n_segments = None
sigma = None
compactness = None
border_color = None
border_outline = None
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)
......
from config import Config
from file_utils import File
from utils import ColorUtils, TimeUtils
from utils import ColorUtils, ImageUtils, TimeUtils
from x11_colors import X11Colors
__all__ = ["config",
......
......@@ -7,6 +7,7 @@
Name: main.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
"""
import cv2
import random
import time
......@@ -18,6 +19,49 @@ class ColorUtils(object):
return '#%02X%02X%02X' % (r(0, 255), r(0, 255), r(0, 255))
class ImageUtils(object):
@staticmethod
def image_to_bgr(image):
return cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
@staticmethod
def image_to_hsv(image, bgr = False):
if bgr == False:
image = image_to_bgr(image)
return cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
@staticmethod
def image_to_cielab(image, bgr = False):
if bgr == False:
image = image_to_bgr(image)
return cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
@staticmethod
def image_grayscale(image, bgr = False):
if bgr == False:
image = image_to_bgr(image)
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
@staticmethod
def image_binary(image, bgr = False, grayscale = False):
if grayscale == False:
image = image_grayscale(image, bgr)
_, image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
return image
@staticmethod
def image_edge_detector(image, canny_min = 100, canny_max = 200, bgr = False, grayscale = False):
if grayscale == False:
image = image_grayscale(image, bgr)
return cv2.Canny(image, canny_min, canny_max)
@staticmethod
def image_resize(image, width, height):
return cv2.resize(image, (width, height))
class TimeUtils(object):
@staticmethod
......
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