Esempio n. 1
0
    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]
Esempio n. 2
0
 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]