Beispiel #1
0
 def __call__(self, img, bgsource = None, methods = ['subtract'], **kwargs):
     if bgsource is None:
         logger.error(("No background image given to "
                 "RemoveBackgroundPreprocessor, doing nothing!"))
         return img
     if bgsource not in self.bgs:
         logger.debug("Loading background image {}".format(bgsource))
         # Load background image
         try:
             self.bgs[bgsource] = self.manager.loadimage(bgsource)
         except IOError, fire.errors.ImageCannotBeLoadedError:
             logger.error(("Unable to load background image '{}', doing "
                          "nothing!").format(bgsource))
             return img
         # If preprocessing steps are not explicity given, use preprocessing
         # chain used for all images, up to the point where background is
         # removed
         if not 'preprocsteps' in kwargs:
             preprocsteps = self.get_previous_preprocsteps()
             if preprocsteps is None:
                 return img
         else:
             preprocsteps = kwargs['preprocsteps']
         self.bgs[bgsource] = self.manager.preprocess(self.bgs[bgsource],
                                                      preprocsteps)
         self.bgs_nonzero[bgsource] = self.bgs[bgsource].copy()
         self.bgs_nonzero[bgsource][self.bgs[bgsource] == 0.] = (0.01 *
                                                 self.bgs[bgsource].max())
         logger.debug("Background image {} loaded".format(bgsource))
Beispiel #2
0
 def smallest_uint_type(maxval):
     for dtype in (np.uint8, np.uint16, np.uint32, np.uint64):
         if maxval < np.iinfo(dtype).max:
             return dtype
     # Hopefully never happens, who has an image that fits that many areas?
     logger.error("No numpy uint type can hold {}".format(maxval))
     return np.uint64
Beispiel #3
0
 def process(self, configfile, infiles, overwrite = False):
     self.loadconfig(configfile)
     for infile in infiles:
         infile = os.path.abspath(infile)
         if not overwrite:
             ename = self.check_skip(infile, self.exportsteps)
             if ename is not None:
                 logger.warning(
                     ("Skipping '{}', rejected by exporter '{}'. Set "
                      "overwrite = True to ignore.").format(infile, ename))
                 continue
         logger.info("Processing '{}'".format(infile))
         try:
             img = self.loadimage(infile)
         except IOError, fire.errors.ImageCannotBeLoadedError:
             logger.error("Unable to load '{}'".format(infile))
             continue
         img = self.preprocess(img, self.preprocsteps)
         # DEBUG
         #import numpy as np
         #np.save("testdata/img_preproc_cropped.npy", img)
         #from fire.debug import showimg, saveimg
         #showimg(img)
         #exit()
         #saveimg("testdata/img_preproc_cropped.png", img)
         detected = self.processchain(img, self.procsteps)
         self.export(infile, detected, self.exportsteps)
Beispiel #4
0
 def __call__(self, img, just_filter = True):
     """just_filter: Will not binarise if set to True (default)"""
     try:
         return self.mh.edge.sobel(img, just_filter = just_filter)
     except ValueError:
         logger.error(("Sobel preprocessor can only work on greyscale "
             "images, doing nothing!"))
         return img
Beispiel #5
0
 def loadimage(self, infile):
     fileext = os.path.splitext(infile)[1][1:]
     for loader in self.imgloaders:
         if fileext.lower() in loader.supported_file_types:
             return loader.load(infile)
     logger.error(
             "No image loader that can read {} files! (File: {})".format(
                 fileext, infile))
     raise fire.errors.ImageCannotBeLoadedError
Beispiel #6
0
 def get_steps(self, steplist):
     steps = []
     for step in steplist:
         try:
             method, args = step.items()[0]
         except AttributeError:
             # step is not a dict (no args)
             method = step
             args = []
         if not isinstance(args, list):
             args = [args]
         # Does method exist?
         if not hasattr(self, method):
             logger.error("Unknown method: '{}', ignoring".format(method))
             continue
         steps.append((method, args))
     return steps
Beispiel #7
0
 def get_previous_preprocsteps(self):
     # Find myself in preprocessor list
     mykey = None
     for key, preproc in self.manager.preprocessors.iteritems():
         if preproc is self:
             mykey = key
             break
     if mykey is None:
         logger.error(("RemoveBackgroundProcessor lives outside of "
                       "manager.preprocessors? Doing nothing!"))
         return None
     try:
         mypreprocindex = [ x[0] for x in self.manager.preprocsteps
                          ].index(mykey)
     except ValueError:
         logger.error(("RemoveBackgroundProcessor is not in "
                       "preprocessing chain? Doing nothing!"))
         return None
     return self.manager.preprocsteps[:mypreprocindex]
Beispiel #8
0
 def __call__(self, img, croptype = "rect", **ppargs):
     if croptype == "rect":
         if not all(( z in ppargs for z in ['x', 'y', 'dx', 'dy'] )):
             logger.error(("Crop processor needs x, y, dx, and dy parameters"
                           " for type 'rect'. Doing nothing!"))
             return img
         return img[ ppargs['y'] : ppargs['y'] + ppargs['dy'],
                     ppargs['x'] : ppargs['x'] + ppargs['dx'] ]
     elif croptype == "circular":
         if not all(( z in ppargs for z in ['x', 'y', 'r'] )):
             logger.error(("Crop processor needs x, y, and r parameters for "
                           "type 'circular'. Doing nothing!"))
             return img
         xmin = np.floor(ppargs['x'] - ppargs['r'])
         xmax = np.ceil(ppargs['x'] + ppargs['r']) + 1
         ymin = np.floor(ppargs['y'] - ppargs['r'])
         ymax = np.ceil(ppargs['y'] + ppargs['r']) + 1
         procimg = img[ymin:ymax, xmin:xmax]
         ys = np.arange(ymax - ymin)
         xs = np.arange(xmax - xmin)
         procimg[(ys[:, None] + ymin - ppargs['y'])**2 + (xs[None, :] +
                 xmin - ppargs['x'])**2 > ppargs['r']**2] = procimg.min()
         procimg[(ys[:, None] + ymin - ppargs['y'])**2 + (xs[None, :] +
                 xmin - ppargs['x'])**2 > (ppargs['r']+2)**2] = procimg.max()
         return procimg
     else:
         logger.error("Unknown crop method: '{}', doing nothing!".format(
                         croptype))
Beispiel #9
0
 def __call__(self, img, prev_detected, **params):
     if "tiles" in params:
         params["tiles_v"] = params["tiles"]
         params["tiles_h"] = params["tiles"]
     elif not ("tiles_v" in params and "tiles_h" in params):
         logger.error(
             (
                 "Invalid tiling information given to "
                 "TiledFCDProcessor. Provide either 'tiles' or both 'tiles_h' "
                 "and 'tiles_v'."
             )
         )
         return []
     # Copy given parameters and check for completeness
     self.p.update(params)
     if not self.all_params_set(params):
         logger.critical("First FCD parameter set must be complete")
         return []
     if self.img is None:
         self.img = np.copy(img)
     if self.neighbourhood_max_img is None and self.p["mincenterlevel"] is not None:
         self.neighbourhood_max_img = self.generic_filter(self.img, np.max, 3)
     if self.prev_detected is None:
         self.prev_detected = list(prev_detected)  # copy
     # Process
     firstnewcircle = len(self.allcircles)
     logger.debug("Preprocessing image...")
     # try:
     #    import pickle
     #    gradcircles = pickle.load(open("testdata/circles.pickle_5tiles", 'r'))
     # except IOError:
     if True:
         img_preproc = self.preprocess(self.img, self.p["gaussian"], self.p["sobel"])
         logger.debug("Computing gradient...")
         grads = self.tiled_gradients(
             img_preproc, prev_detected, self.p["tiles_v"], self.p["tiles_h"], self.p["maxr"] + 3
         )
         gradcircles = []
         for i, grad in enumerate(grads):
             logger.debug("Tile {} / {}".format(i + 1, len(grads)))
             logger.debug("Finding circle candidates...")
             candidates = self.findcandidates(
                 grad,
                 self.p["alpha"],
                 self.p["beta"],
                 self.p["gamma"],
                 self.p["minnorm"],
                 self.p["maxr"],
                 self.p["mincenterlevel"],
             )
             logger.debug("Number of candidates: {}".format(len(candidates)))
             logger.debug("Clustering...")
             circles = self.cluster(
                 candidates,
                 self.p["minr"],
                 self.p["maxr"],
                 self.p["radiusscaler"],
                 self.p["minmembers"],
                 self.p["epsilon"],
                 self.p["minsamples"],
                 self.p["maxangspread"],
             )
             logger.debug("Number of detected circles: {}".format(len(circles)))
             # Attach index of this tile to circles
             circles = np.hstack((circles, i * np.ones((circles.shape[0], 1))))
             gradcircles.append(circles)
         # import pickle
         # pickle.dump(gradcircles, open("testdata/circles.pickle", 'w'), -1)
     logger.debug("Cleaning circle list...")
     self.totmergers = 0
     self.totoverl = 0
     for i in range(self.p["tiles_v"] - 1):
         for j in range(self.p["tiles_h"] - 1):
             logger.debug(
                 "Circle group {} / {}".format(
                     i * (self.p["tiles_h"] - 1) + j + 1, (self.p["tiles_v"] - 1) * (self.p["tiles_h"] - 1)
                 )
             )
             tileindices = (
                 i * self.p["tiles_h"] + j,
                 i * self.p["tiles_h"] + j + 1,
                 (i + 1) * self.p["tiles_h"] + j,
                 (i + 1) * self.p["tiles_h"] + j + 1,
             )
             # Put circles of four-tile-groups into same list and clean
             groupcircles = np.concatenate(tuple(gradcircles[ti] for ti in tileindices))
             groupcircles = self.cleancirclelist(groupcircles)
             # Split returned list back into corresponding gradcircles
             for x in tileindices:
                 gradcircles[x] = groupcircles[groupcircles[:, -1] == x]
     logger.debug("Total mergers: {}".format(self.totmergers))
     logger.debug("Total overlaps: {}".format(self.totoverl))
     newcircles = np.concatenate(gradcircles)
     logger.debug("Number of new circles: {}".format(len(newcircles)))
     self.allcircles = np.concatenate((self.allcircles, newcircles))
     return [DiskInfo(c[0], c[1], c[2]) for c in self.allcircles[firstnewcircle:]]