def __call__( self, img, prev_detected, seed_threshold=None, erode_factor=1, minsize=0, maxhole=0.5, checkQsize=0, minQ=0.5, **kwargs ): # Guess threshold if not given if seed_threshold is None: from fire.debug import showimg # Otsu needs int, convert to range 0-255 normimg = (img - img.min()) / (img.max() - img.min()) intimg = np.rint(normimg * 255).astype(np.uint8) intimg_threshold = self.mh.thresholding.otsu(intimg) # Convert received threshold back to image range seed_threshold = intimg_threshold / 255.0 * (img.max() - img.min()) + img.min() logger.debug("Guessed threshold (Otsu): {}".format(seed_threshold)) # Find seeds binary = img > seed_threshold for i in range(erode_factor): binary = self.mh.morph.erode(binary) from fire.debug import showimg showimg(binary) seeds, nr_of_seeds = self.mh.label(binary) logger.debug("Number of watershed seeds: {}".format(nr_of_seeds)) # Do watershed transformation labeled = self.mh.cwatershed(img.max() - img, seeds) logger.debug("Number of areas: {}".format(len(labeled))) # Extract sizes of area and filter for minsize sizes = np.bincount(labeled.flat) bigareas = np.argwhere(sizes > maxhole * minsize) logger.debug("With minimum size (holes not filled) {}: {}".format(maxhole * minsize, len(bigareas))) # Create detection info detected = NonOverlappingFreeAreasInfo( np.zeros(img.shape, dtype=NonOverlappingFreeAreasInfo.smallest_uint_type(len(bigareas))) ) for bigarea in bigareas: filled = self.fill_holes(labeled == bigarea) size = np.count_nonzero(filled) if size < minsize: continue elif size < checkQsize and self.isoperimetric_quotient(filled) < minQ: continue else: detected.addarea(filled) logger.debug("Found {} areas".format(np.max(detected.labeledareas))) return [detected]
def __call__( self, img, prev_detected, threshold=None, minsize=0, maxsize=None, steps_prelabel=[], steps_postlabel=[], **kwargs ): if threshold is None: threshold = self.otsu(img) logger.debug("Guessed threshold (Otsu): {}".format(threshold)) binary = img > threshold for pdetected in prev_detected: for d in pdetected: binary[d.pixels()] = False self.backgroundinfos = [] binary = self.do_steps(img, binary, steps_prelabel) # Label labeled, nr_labels = self.mh.label(binary) logger.debug("Number of areas: {}".format(nr_labels)) # Filter for size requirements sizes = np.bincount(labeled.flat) considered_sizes = sizes >= minsize if maxsize is not None: considered_sizes = np.logical_and(considered_sizes, sizes <= maxsize) considered_labels = np.argwhere(considered_sizes) logger.debug("Meeting size requirements: {}".format(len(considered_labels))) # Create detection info detected = NonOverlappingFreeAreasInfo( np.zeros(img.shape, dtype=NonOverlappingFreeAreasInfo.smallest_uint_type(len(considered_labels))) ) for area_label in considered_labels: if area_label == 0: continue # ignore background thisarea = labeled == area_label try: thisarea = self.do_steps(img, thisarea, steps_postlabel) except self.RejectArea: continue detected.addarea(thisarea) logger.debug("Found {} areas".format(np.max(detected.labeledareas))) return self.backgroundinfos + [detected]