#!/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)