示例#1
0
    def testSSLWorkflowBuilder(self):
        segmenter = DumbSegmenter()
        builder = SSLWorkflowBuilder()
        builder.set_n_jobs(5)
        builder.set_tile_size(512, 768)
        builder.set_overlap(3)
        builder.set_distance_tolerance(7)
        builder.set_background_class(5)
        builder.set_logger(StandardOutputLogger(Logger.DEBUG))

        with self.assertRaises(MissingComponentException):
            builder.get()

        builder.set_segmenter(segmenter)
        builder.set_default_tile_builder()

        workflow = builder.get()
        self.assertIsInstance(workflow, SSLWorkflow)
        self.assertEqual(workflow._n_jobs, 5)
        self.assertEqual(workflow._tile_overlap, 3)
        self.assertEqual(workflow._tile_max_height, 512)
        self.assertEqual(workflow._tile_max_width, 768)
        self.assertIsInstance(workflow._tile_builder, DefaultTileBuilder)
        self.assertIsInstance(workflow.logger, StandardOutputLogger)
        self.assertEqual(workflow._locator._background, 5)
 def __init__(self,
              build_fn=None,
              logger=StandardOutputLogger(Logger.INFO),
              **sk_params):
     super(CellCountRandomizedTrees, self).__init__(build_fn, logger,
                                                    **sk_params)
     self.__forest = None
示例#3
0
 def __init__(self,
              build_fn=None,
              logger=StandardOutputLogger(Logger.INFO),
              **sk_params):
     self.build_fn = build_fn
     self.sk_params = sk_params
     self.logger = logger
    def __init__(self, cytomine, software_id, project_id, job_parameters,
                 tile_overlap, tile_width, tile_height, n_jobs, threshold,
                 min_area, model_path, rseed, working_path):
        """An example job implementing an sldc workflow.

        Parameters
        ----------
        cytomine: Cytomine
            Cytomine client
        software_id: int
            Cytomine software id
        project_id: int
            Cytomine project id
        job_parameters: dict
            Job parameters
        tile_overlap: int
            Number of pixel of overlap between the tiles
        tile_width: int
            Maximum width of the tiles
        tile_height: int
            Maximum height of the tiles
        n_jobs: int
            Number of available jobs
        threshold: int
            Segmentation threshold in [0, 255]
        min_area: int
            Minimum area of the valid objects in pixel squared
        model_path: str
            Path to the pickled pyxit model
        rseed: int
            Random seed
        working_path: str
            Working path of the workflow (for temporary files)
        """
        CytomineJob.__init__(self, cytomine, software_id, project_id, parameters=job_parameters)
        Loggable.__init__(self, logger=StandardOutputLogger(Logger.INFO))
        self._cytomine = cytomine

        # create workflow component
        random_state = check_random_state(rseed)
        tile_builder = CytomineTileBuilder(cytomine, working_path=working_path)
        segmenter = DemoSegmenter(threshold)
        area_rule = ValidAreaRule(min_area)
        classifier = PyxitClassifierAdapter.build_from_pickle(
            model_path, tile_builder, self.logger,
            random_state=random_state,
            n_jobs=n_jobs,
            working_path=working_path
        )

        builder = WorkflowBuilder()
        builder.set_n_jobs(n_jobs)
        builder.set_logger(self.logger)
        builder.set_overlap(tile_overlap)
        builder.set_tile_size(tile_width, tile_height)
        builder.set_tile_builder(tile_builder)
        builder.set_segmenter(segmenter)
        builder.add_classifier(area_rule, classifier, dispatching_label="valid")
        self._workflow = builder.get()
def main(argv):
    with CytomineJob.from_cli(argv) as job:
        if not os.path.exists(job.parameters.working_path):
            os.makedirs(job.parameters.working_path)

        # create workflow component
        logger = StandardOutputLogger(Logger.INFO)
        random_state = check_random_state(int(job.parameters.rseed))
        tile_builder = CytomineTileBuilder(
            working_path=job.parameters.working_path)
        segmenter = DemoSegmenter(job.parameters.threshold)
        area_rule = ValidAreaRule(job.parameters.min_area)
        classifier = PyxitClassifierAdapter.build_from_pickle(
            job.parameters.pyxit_model_path,
            tile_builder,
            logger,
            random_state=random_state,
            n_jobs=job.parameters.n_jobs,
            working_path=job.parameters.working_path)

        builder = SLDCWorkflowBuilder()
        builder.set_n_jobs(job.parameters.n_jobs)
        builder.set_logger(logger)
        builder.set_overlap(job.parameters.sldc_tile_overlap)
        builder.set_tile_size(job.parameters.sldc_tile_width,
                              job.parameters.sldc_tile_height)
        builder.set_tile_builder(tile_builder)
        builder.set_segmenter(segmenter)
        builder.add_classifier(area_rule,
                               classifier,
                               dispatching_label="valid")
        workflow = builder.get()

        slide = CytomineSlide(job.parameters.cytomine_image_id)
        results = workflow.process(slide)

        # Upload results
        for polygon, label, proba, dispatch in results:
            if label is not None:
                # if image is a window, the polygon must be translated
                if isinstance(slide, ImageWindow):
                    polygon = translate(polygon, slide.abs_offset_x,
                                        slide.abs_offset_y)
                # upload the annotation
                polygon = affine_transform(
                    polygon, [1, 0, 0, -1, 0, slide.image_instance.height])
                annotation = Annotation(
                    location=polygon.wkt,
                    id_image=slide.image_instance.id).save()
                AlgoAnnotationTerm(id_annotation=annotation.id,
                                   id_term=label,
                                   rate=float(proba)).save()
示例#6
0
    def testSLDCWorkflowWithOneShotDispatcher(self):
        # pre build components
        segmenter = DumbSegmenter()
        dispatcher = DumbDispatcher()
        classifier = DumbClassifier()
        rule = DumbRule()
        logger = StandardOutputLogger(Logger.DEBUG)

        builder = SLDCWorkflowBuilder()
        builder.set_tile_size(512, 768)
        builder.set_overlap(3)
        builder.set_distance_tolerance(5)
        builder.set_n_jobs(5)
        builder.set_logger(logger)
        builder.set_parallel_dc(True)
        builder.set_tile_builder(None)

        with self.assertRaises(MissingComponentException):
            builder.get()

        builder.set_segmenter(segmenter)

        with self.assertRaises(MissingComponentException):
            builder.get()

        builder.set_default_tile_builder()

        with self.assertRaises(MissingComponentException):
            builder.get()

        builder.set_one_shot_dispatcher(dispatcher, {"default": classifier})

        with self.assertRaises(InvalidBuildingException):
            builder.add_classifier(rule, classifier, dispatching_label="default")

        with self.assertRaises(InvalidBuildingException):
            builder.add_catchall_classifier(classifier, dispatching_label="default")

        workflow = builder.get()
        self.assertIsInstance(workflow, SLDCWorkflow)
        self.assertEqual(workflow._segmenter, segmenter)
        self.assertEqual(workflow._n_jobs, 5)
        self.assertEqual(workflow._tile_overlap, 3)
        self.assertEqual(workflow._tile_max_height, 512)
        self.assertEqual(workflow._tile_max_width, 768)
        self.assertEqual(workflow.logger, logger)
        self.assertIsInstance(workflow._tile_builder, DefaultTileBuilder)
        self.assertEqual(workflow._dispatch_classifier._dispatcher, dispatcher)
        self.assertEqual(len(workflow._dispatch_classifier._classifiers), 1)
        self.assertEqual(workflow._dispatch_classifier._classifiers[0], classifier)
示例#7
0
    def __init__(self, colorspaces, dtype=np.float16, logger=StandardOutputLogger(Logger.INFO)):
        if colorspaces is None:
            raise ValueError("Colorspace cannot be None")

        self.logger = logger
        self.dtype = dtype
        self.features = None
        self.colorspaces = list()

        colorspaces_dict = split_list_to_dict(colorspaces, splitter='__')
        for colorspace, features in colorspaces_dict.items():
            if colorspace in ('rgb', 'RGB', 'color'):
                self.colorspaces.append(ColorspaceRGB(features))
            elif colorspace in ('gray', 'grayscale', 'L'):
                self.colorspaces.append(ColorspaceGrayscale(features))
示例#8
0
 def __init__(self, default_estimator, param_grid, cv, me, untrainable_param_grid=None,
              scoring_rank='f1_score', refit=False, iid=True, n_jobs=1, pre_dispatch='2*n_jobs',
              logger=StandardOutputLogger(Logger.INFO)):
     self.default_estimator = default_estimator
     self.param_grid = param_grid
     self.untrainable_param_grid = untrainable_param_grid
     self.cv = cv
     self.me = me
     self.scoring_rank = scoring_rank
     self.n_jobs = n_jobs
     self.pre_dispatch = pre_dispatch
     self.logger = logger
     self.refit = refit
     self.iid = iid
     _check_param_grid(param_grid)
     _check_param_grid(untrainable_param_grid)
示例#9
0
    def testMerge(self):
        timing1 = WorkflowTiming()
        timing2 = WorkflowTiming()

        timing1.start("root1")
        timing1.end("root1")
        timing1.start("root")
        timing1.end("root")
        timing1.start("root1.adj")
        timing1.end("root1.adj")
        timing2.start("root2")
        timing2.end("root2")
        timing2.start("root")
        timing2.end("root")
        timing2.start("root1.adj")
        timing2.end("root1.adj")

        # merge without update of initial objects
        merged = merge_timings(timing1, timing2)

        self.assertEqual(len(merged["root1"]), 1)
        self.assertEqual(len(merged["root2"]), 1)
        self.assertEqual(len(merged["root"]), 2)
        self.assertEqual(len(merged["root1.adj"]), 2)

        # merge with update of timing1
        timing1.merge(timing2)

        self.assertEqual(len(timing1["root1"]), 1)
        self.assertEqual(len(timing1["root2"]), 1)
        self.assertEqual(len(timing1["root"]), 2)
        self.assertEqual(len(timing1["root1.adj"]), 2)

        with self.assertRaises(TypeError):
            timing1.merge(StandardOutputLogger(level=Logger.DEBUG))

        timing1.merge(timing1)
        self.assertEqual(len(timing1["root1"]), 1)
        self.assertEqual(len(timing1["root2"]), 1)
        self.assertEqual(len(timing1["root"]), 2)
        self.assertEqual(len(timing1["root1.adj"]), 2)
示例#10
0
def main():
    """ (4) build the workflow """
    logger = StandardOutputLogger(Logger.INFO)
    builder = SLDCWorkflowBuilder()
    builder.set_n_jobs(4)
    builder.set_logger(logger)
    builder.set_default_tile_builder()
    builder.set_tile_size(256, 256)
    builder.set_segmenter(BasicSegmenter())
    builder.add_classifier(ShapeRule(ShapeRule.CIRCLE), ColorClassifier(), "circle")
    builder.add_classifier(ShapeRule(ShapeRule.SQUARE), ColorClassifier(), "square")

    workflow = builder.get()

    """ (5) build a (fake) image """
    np_image = np.zeros([2000, 2000], dtype=np.uint8)
    np_image = draw_circle(np_image, 100, (500, 1500), 255)
    np_image = draw_circle(np_image, 100, (1500, 600), 127)
    np_image = draw_square(np_image, 200, (500, 500), 255)
    np_image = draw_square(np_image, 200, (1500, 1500), 127)
    np_image = draw_square(np_image, 300, (1000, 1000), 255)
    image = NumpyImage(np_image)

    """ (6) process the image """
    results = workflow.process(image)

    """ (7) report execution times """
    report_timing(results.timing, logger)

    """ (8) explore the results """
    for i, object_info in enumerate(results):
        print(
            "Object {}:".format(i + 1) + os.linesep +
            "> area    : {}".format(object_info.polygon.area) + os.linesep +
            "> label   : '{}'".format(object_info.label) + os.linesep +
            "> proba   : {}".format(object_info.proba) + os.linesep +
            "> dispatch: '{}'".format(object_info.dispatch)
        )
    def __init__(self, cytomine, software_id, project_id, job_parameters,
                 fix_image_id, moving_image_id, nb_spatial_sample,
                 nb_iterations, storage_id, annotation_fix_id,
                 annotation_moving_id, working_path, cytomine_host,
                 cytomine_upload, pk, prk, export_overlay_images,
                 number_of_resolutions, result_file_name):
        print("After init")
        # call init from parent classes #
        print("project id = " + str(project_id))
        if (cytomine == None):
            print "Cytomine obj null"
        print("soft_id =" + str(software_id))
        CytomineJob.__init__(self,
                             cytomine,
                             software_id,
                             project_id,
                             parameters=None)
        Loggable.__init__(self, logger=StandardOutputLogger(Logger.INFO))

        # keep var from parameters #
        self._fix_image_id = fix_image_id
        self._moving_image_id = moving_image_id
        self._nb_spatial_sample = nb_spatial_sample
        self._nb_iterations = nb_iterations
        self._storage_id = storage_id
        self._id_annotation_fix = annotation_fix_id
        self._id_annotation_moving = annotation_moving_id
        self._working_path = working_path
        self._cytomine_upload = cytomine_upload
        self._cytomine_host = cytomine_host
        self._cytomine = cytomine
        self._project_id = project_id
        self._pk = pk
        self._prk = prk
        self._overlayed_images = export_overlay_images
        self._job_parameters = job_parameters
        self._number_of_resolutions = number_of_resolutions
        self._result_file_name = result_file_name
示例#12
0
    def testWorkflowChainBuilder(self):
        segmenter = DumbSegmenter()
        dispatcher = DumbDispatcher()
        classifier = DumbClassifier()

        builder = SLDCWorkflowBuilder()
        builder.set_segmenter(segmenter)
        builder.set_default_tile_builder()
        builder.set_one_shot_dispatcher(dispatcher, {"default": classifier})
        workflow1 = builder.get()

        builder2 = SSLWorkflowBuilder()
        builder2.set_segmenter(segmenter)
        builder2.set_default_tile_builder()
        workflow2 = builder2.get()

        _filter = DefaultFilter()
        logger = StandardOutputLogger(Logger.DEBUG)
        chain_builder = WorkflowChainBuilder()
        chain_builder.set_logger(logger)

        with self.assertRaises(MissingComponentException):
            chain_builder.get()

        chain_builder.set_first_workflow(workflow1, label="first")
        chain_builder.add_executor(workflow2, label="second", filter=_filter, n_jobs=2, logger=logger)
        chain = chain_builder.get()

        self.assertIsInstance(chain, WorkflowChain)
        self.assertEqual(chain.logger, logger)
        self.assertEqual(chain._first_workflow, workflow1)
        self.assertEqual(len(chain._executors), 1)
        self.assertEqual(chain._executors[0]._workflow, workflow2)
        self.assertEqual(len(chain._labels), 2)
        self.assertEqual(tuple(chain._labels), ("first", "second"))
        self.assertEqual(len(chain._filters), 1)
        self.assertEqual(chain._filters[0], _filter)
示例#13
0
def main(argv):
    with CytomineJob.from_cli(argv) as cj:
        # use only images from the current project
        cj.job.update(progress=1, statusComment="Preparing execution")

        # extract images to process
        if cj.parameters.cytomine_zoom_level > 0 and (
                cj.parameters.cytomine_tile_size != 256
                or cj.parameters.cytomine_tile_overlap != 0):
            raise ValueError(
                "when using zoom_level > 0, tile size should be 256 "
                "(given {}) and overlap should be 0 (given {})".format(
                    cj.parameters.cytomine_tile_size,
                    cj.parameters.cytomine_tile_overlap))

        cj.job.update(
            progress=1,
            statusComment="Preparing execution (creating folders,...).")
        # working path
        root_path = str(Path.home())
        working_path = os.path.join(root_path, "images")
        os.makedirs(working_path, exist_ok=True)

        # load training information
        cj.job.update(progress=5,
                      statusComment="Extract properties from training job.")
        train_job = Job().fetch(cj.parameters.cytomine_id_job)
        properties = PropertyCollection(train_job).fetch().as_dict()
        binary = str2bool(properties["binary"].value)
        classes = parse_domain_list(properties["classes"].value)

        cj.job.update(progress=10, statusComment="Download the model file.")
        attached_files = AttachedFileCollection(train_job).fetch()
        model_file = attached_files.find_by_attribute("filename",
                                                      "model.joblib")
        model_filepath = os.path.join(root_path, "model.joblib")
        model_file.download(model_filepath, override=True)
        pyxit = joblib.load(model_filepath)

        # set n_jobs
        pyxit.base_estimator.n_jobs = cj.parameters.n_jobs
        pyxit.n_jobs = cj.parameters.n_jobs

        cj.job.update(progress=45, statusComment="Build workflow.")
        builder = SSLWorkflowBuilder()
        builder.set_tile_size(cj.parameters.cytomine_tile_size,
                              cj.parameters.cytomine_tile_size)
        builder.set_overlap(cj.parameters.cytomine_tile_overlap)
        builder.set_tile_builder(
            CytomineTileBuilder(working_path, n_jobs=cj.parameters.n_jobs))
        builder.set_logger(StandardOutputLogger(level=Logger.INFO))
        builder.set_n_jobs(1)
        builder.set_background_class(0)
        # value 0 will prevent merging but still requires to run the merging check
        # procedure (inefficient)
        builder.set_distance_tolerance(2 if cj.parameters.union_enabled else 0)
        builder.set_segmenter(
            ExtraTreesSegmenter(
                pyxit=pyxit,
                classes=classes,
                prediction_step=cj.parameters.pyxit_prediction_step,
                background=0,
                min_std=cj.parameters.tile_filter_min_stddev,
                max_mean=cj.parameters.tile_filter_max_mean))
        workflow = builder.get()

        area_checker = AnnotationAreaChecker(
            min_area=cj.parameters.min_annotation_area,
            max_area=cj.parameters.max_annotation_area)

        def get_term(label):
            if binary:
                if "cytomine_id_predict_term" not in cj.parameters:
                    return []
                else:
                    return [int(cj.parameters.cytomine_id_predict_term)]
            # multi-class
            return [label]

        zones = extract_images_or_rois(cj.parameters)
        for zone in cj.monitor(zones,
                               start=50,
                               end=90,
                               period=0.05,
                               prefix="Segmenting images/ROIs"):
            results = workflow.process(zone)

            annotations = AnnotationCollection()
            for obj in results:
                if not area_checker.check(obj.polygon):
                    continue
                polygon = obj.polygon
                if isinstance(zone, ImageWindow):
                    polygon = affine_transform(
                        polygon,
                        [1, 0, 0, 1, zone.abs_offset_x, zone.abs_offset_y])
                polygon = change_referential(polygon, zone.base_image.height)
                if cj.parameters.cytomine_zoom_level > 0:
                    zoom_mult = (2**cj.parameters.cytomine_zoom_level)
                    polygon = affine_transform(
                        polygon, [zoom_mult, 0, 0, zoom_mult, 0, 0])
                annotations.append(
                    Annotation(location=polygon.wkt,
                               id_terms=get_term(obj.label),
                               id_project=cj.project.id,
                               id_image=zone.base_image.image_instance.id))
            annotations.save()

        cj.job.update(status=Job.TERMINATED,
                      status_comment="Finish",
                      progress=100)
示例#14
0
    def flip(m, axis):
        indexer = [slice(None)] * m.ndim
        indexer[axis] = slice(None, None, -1)
        return m[tuple(indexer)]

    filename = sys.argv[1]
    if not os.path.exists(filename):
        raise IOError("File " + filename + " does not exist !")
    img = cv2.imread(filename, cv2.IMREAD_COLOR)
    img = img[250:,250:,...]

    colorspaces = ['RGB__rgb', 'RGB__luv', 'RGB__hsv', 'L__normalized',
                   'L__sobel1', 'L__sobel_gradmagn', 'L__sobel2']

    fe = FeaturesExtractor(colorspaces, logger=StandardOutputLogger(Logger.DEBUG))
    fe.build(img)

    titles = ['Red', 'Green', 'Blue', 'L*', 'u*', 'v*', 'Hue', 'Saturation', 'Value',
              'Eq. grayscale', '1st-Sobel x', '1st-Sobel y', 'Sobel grad. magn.',
              '2st-Sobel x', '2st-Sobel y']

    n_rows = 4
    n_cols = 4

    fig = plt.figure()
    a = fig.add_subplot(n_rows, n_cols, 1)
    plt.imshow(flip(img, 2))
    a.set_title('Original RGB image')
    a.set_axis_off()
示例#15
0
def train(argv):
    parser = ArgumentParser(prog="Extra-Trees Object Counter Model Builder")

    # Cytomine
    parser.add_argument('--cytomine_host', dest='cytomine_host',
                        default='demo.cytomine.be', help="The Cytomine host")
    parser.add_argument('--cytomine_public_key', dest='cytomine_public_key',
                        help="The Cytomine public key")
    parser.add_argument('--cytomine_private_key', dest='cytomine_private_key',
                        help="The Cytomine private key")
    parser.add_argument('--cytomine_base_path', dest='cytomine_base_path',
                        default='/api/', help="The Cytomine base path")
    parser.add_argument('--cytomine_working_path', dest='cytomine_working_path',
                        default=None, help="The working directory (eg: /tmp)")
    parser.add_argument('--cytomine_id_software', dest='cytomine_software', type=int,
                        help="The Cytomine software identifier")
    parser.add_argument('--cytomine_id_project', dest='cytomine_project', type=int,
                        help="The Cytomine project identifier")
    parser.add_argument('--cytomine_force_download', dest='cytomine_force_download', type=bool, default=True,
                        help="Force download from Cytomine or not")

    # Objects
    parser.add_argument('--cytomine_object_term', dest='cytomine_object_term', type=int,
                        help="The Cytomine identifier of object term")
    parser.add_argument('--cytomine_object_user', dest='cytomine_object_user', type=int,
                        help="The Cytomine identifier of object owner")
    parser.add_argument('--cytomine_object_reviewed_only', dest='cytomine_object_reviewed_only', type=bool,
                        help="Whether objects have to be reviewed or not")

    # ROI
    parser.add_argument('--cytomine_roi_term', dest='cytomine_roi_term', type=int, default=None,
                        help="The Cytomine identifier of region of interest term")
    parser.add_argument('--cytomine_roi_user', dest='cytomine_roi_user', type=int,
                        help="The Cytomine identifier of ROI owner")
    parser.add_argument('--cytomine_roi_reviewed_only', dest='cytomine_roi_reviewed_only', type=bool,
                        help="Whether ROIs have to be reviewed or not")

    # Pre-processing
    parser.add_argument('--mean_radius', dest='mean_radius', type=int, required=True,
                        help="The mean radius of object to detect")
    parser.add_argument('--pre_transformer', dest='pre_transformer',
                        default=None, choices=['edt', 'euclidean_distance_transform', 'density', None, 'None'],
                        help="Scoremap transformer (None, edt, euclidean_distance_transform, density)")
    parser.add_argument('--pre_alpha', dest='pre_alpha', action='append', type=int,
                        help="Exponential decrease rate of distance (if EDT)")

    # Subwindows
    parser.add_argument('--sw_input_size', dest='sw_input_size', action='append', type=int,
                        help="Size of input subwindow")
    parser.add_argument('--sw_output_size', dest='sw_output_size', action='append', type=int,
                        help="Size of output subwindow (ignored for FCRN)")
    parser.add_argument('--sw_extr_mode', dest='sw_extr_mode', choices=['random', 'sliding', 'scoremap_constrained'],
                        help="Mode of extraction (random, scoremap_constrained)")
    parser.add_argument('--sw_extr_score_thres', dest='sw_extr_score_thres', action='append', type=float,
                        help="Minimum threshold to be foreground in subwindows extraction"
                             "(if 'scoremap_constrained' mode)")
    parser.add_argument('--sw_extr_ratio', dest='sw_extr_ratio', action='append', type=float,
                        help="Ratio of background subwindows extracted in subwindows "
                             "extraction (if 'scoremap_constrained' mode)")
    parser.add_argument('--sw_extr_npi', dest="sw_extr_npi", action='append', type=int,
                        help="Number of extracted subwindows per image (if 'random' mode)")
    parser.add_argument('--sw_colorspace', dest="sw_colorspace", type=str, default='RGB__rgb',
                        help="List of colorspace features")

    # Forest
    parser.add_argument('--forest_method', dest='forest_method', type=str,
                        action='append', choices=['ET-clf', 'ET-regr', 'RF-clf', 'RF-regr'],
                        help="Type of forest method")
    parser.add_argument('--forest_n_estimators', dest='forest_n_estimators', action='append', type=int,
                        help="Number of trees in forest")
    parser.add_argument('--forest_min_samples_split', dest='forest_min_samples_split', action='append', type=int,
                        help="Minimum number of samples for further splitting")
    parser.add_argument('--forest_max_features', dest='forest_max_features', action='append',
                        help="Max features")

    # Dataset augmentation
    parser.add_argument('--augmentation', dest='augmentation', type=bool)
    parser.add_argument('--aug_rotation_range', dest='rotation_range', type=float)
    parser.add_argument('--aug_width_shift_range', dest='width_shift_range', type=float)
    parser.add_argument('--aug_height_shift_range', dest='height_shift_range', type=float)
    parser.add_argument('--aug_zoom_range', dest='zoom_range', type=float)
    parser.add_argument('--aug_fill_mode', dest='fill_mode', type=str)
    parser.add_argument('--aug_horizontal_flip', dest='horizontal_flip', type=bool)
    parser.add_argument('--aug_vertical_flip', dest='vertical_flip', type=bool)
    parser.add_argument('--aug_featurewise_center', dest='featurewise_center', type=bool)
    parser.add_argument('--aug_featurewise_std_normalization', dest='featurewise_std_normalization', type=bool)

    # Execution
    parser.add_argument('--n_jobs', dest='n_jobs', type=int, default=1, help="Number of jobs")
    parser.add_argument('--verbose', '-v', dest='verbose', default=0, help="Level of verbosity")

    params, other = parser.parse_known_args(argv)
    if params.cytomine_working_path is None:
        params.cytomine_working_path = os.path.join(tempfile.gettempdir(), "cytomine")
    make_dirs(params.cytomine_working_path)

    params.pre_transformer = check_default(params.pre_transformer, None, return_list=False)
    params.pre_alpha = check_default(params.pre_alpha, 5)
    params.forest_method = check_default(params.forest_method, 'ET-regr')
    params.forest_n_estimators = check_default(params.forest_n_estimators, 1)
    params.forest_min_samples_split = check_default(params.forest_min_samples_split, 2)
    params.forest_max_features = check_default(params.forest_max_features, 'sqrt')
    params.forest_max_features = check_max_features(params.forest_max_features)
    params.sw_input_size = check_default(params.sw_input_size, 4)
    params.sw_input_size = [(s, s) for s in params.sw_input_size]
    params.sw_output_size = check_default(params.sw_output_size, 1)
    params.sw_output_size = [(s, s) for s in params.sw_output_size]
    params.sw_extr_mode = check_default(params.sw_extr_mode, 'scoremap_constrained', return_list=False)
    params.sw_extr_ratio = check_default(params.sw_extr_ratio, 0.5)
    params.sw_extr_score_thres = check_default(params.sw_extr_score_thres, 0.4)
    params.sw_extr_npi = check_default(params.sw_extr_npi, 100)
    params.sw_colorspace = params.sw_colorspace.split(' ')

    params.augmentation = check_default(params.augmentation, False, return_list=False)
    if params.augmentation:
        params.rotation_range = check_default(params.rotation_range, 30., return_list=False)
        params.width_shift_range = check_default(params.width_shift_range, 0.3, return_list=False)
        params.height_shift_range = check_default(params.height_shift_range, 0.3, return_list=False)
        params.zoom_range = check_default(params.zoom_range, 0.3, return_list=False)
        params.fill_mode = check_default(params.fill_mode, 'constant', return_list=False)
        params.horizontal_flip = check_default(params.horizontal_flip, True, return_list=False)
        params.vertical_flip = check_default(params.vertical_flip, True, return_list=False)
        params.featurewise_center = check_default(params.featurewise_center, False, return_list=False)
        params.featurewise_std_normalization = check_default(params.featurewise_std_normalization, False,
                                                             return_list=False)
    else:
        params.rotation_range = 0.
        params.width_shift_range = 0.
        params.height_shift_range = 0.
        params.zoom_range = 0.
        params.fill_mode = 'reflect'
        params.horizontal_flip = False
        params.vertical_flip = False
        params.featurewise_center = False
        params.featurewise_std_normalization = False

    params = params_remove_list(params)

    # Initialize logger
    logger = StandardOutputLogger(params.verbose)
    for key, val in sorted(vars(params).iteritems()):
        logger.info("[PARAMETER] {}: {}".format(key, val))

    # Initialize Cytomine client
    cytomine = Cytomine(
        params.cytomine_host,
        params.cytomine_public_key,
        params.cytomine_private_key,
        working_path=params.cytomine_working_path,
        base_path=params.cytomine_base_path,
        verbose=(params.verbose >= Logger.DEBUG)
    )

    # Start job
    with CytomineJob(cytomine,
                     params.cytomine_software,
                     params.cytomine_project,
                     parameters=vars(params_remove_none(params))) as job:
        cytomine.update_job_status(job.job, status_comment="Starting...", progress=0)

        cytomine.update_job_status(job.job, status_comment="Loading training set...", progress=1)
        X, y = get_dataset(cytomine, params.cytomine_working_path, params.cytomine_project, params.cytomine_object_term,
                           params.cytomine_roi_term, params.cytomine_object_user, params.cytomine_object_reviewed_only,
                           params.cytomine_roi_user, params.cytomine_roi_reviewed_only, params.cytomine_force_download)
        logger.d("X size: {} samples".format(len(X)))
        logger.d("y size: {} samples".format(len(y)))

        cytomine.update_job_status(job.job, status_comment="Training forest...", progress=5)
        estimator = CellCountRandomizedTrees(logger=logger, **vars(params))
        estimator.fit(np.asarray(X), np.asarray(y))

        cytomine.update_job_status(job.job, status_comment="Saving (best) model", progress=95)
        model_path = os.path.join(params.cytomine_working_path, "models", str(params.cytomine_software))
        model_file = os.path.join(model_path, "{}.pkl".format(job.job.id))
        make_dirs(model_path)
        estimator.save(model_file)

        cytomine.update_job_status(job.job, status_comment="Finished.", progress=100)
def predict(argv):
    parser = ArgumentParser(prog="Extra-Trees Object Counter Predictor")

    # Cytomine
    parser.add_argument('--cytomine_host', dest='cytomine_host',
                        default='demo.cytomine.be', help="The Cytomine host")
    parser.add_argument('--cytomine_public_key', dest='cytomine_public_key',
                        help="The Cytomine public key")
    parser.add_argument('--cytomine_private_key', dest='cytomine_private_key',
                        help="The Cytomine private key")
    parser.add_argument('--cytomine_base_path', dest='cytomine_base_path',
                        default='/api/', help="The Cytomine base path")
    parser.add_argument('--cytomine_working_path', dest='cytomine_working_path',
                        default=None, help="The working directory (eg: /tmp)")
    parser.add_argument('--cytomine_id_software', dest='cytomine_software', type=int,
                        help="The Cytomine software identifier")
    parser.add_argument('--cytomine_id_project', dest='cytomine_project', type=int,
                        help="The Cytomine project identifier")

    # Objects
    parser.add_argument('--cytomine_object_term', dest='cytomine_object_term', type=int,
                        help="The Cytomine identifier of object term")

    # Post-processing
    parser.add_argument('--post_threshold', dest='post_threshold', type=float,
                        help="Post-processing discarding threshold")
    parser.add_argument('--post_sigma', dest='post_sigma', type=float,
                        help="Std-dev of Gauss filter applied to smooth prediction")
    parser.add_argument('--post_min_dist', dest='post_min_dist', type=int,
                        help="Minimum distance between two peaks")

    # ROI
    parser.add_argument('--annotation', dest='annotation', type=str, action='append', default=[])
    parser.add_argument('--image', dest='image', type=str, action='append', default=[])

    # Execution
    parser.add_argument('--n_jobs', dest='n_jobs', type=int, default=1, help="Number of jobs")
    parser.add_argument('--verbose', '-v', dest='verbose', type=int, default=0, help="Level of verbosity")
    parser.add_argument('--model_id_job', dest='model_id_job', type=str, default=None, help="Model job ID")
    parser.add_argument('--model_file', dest="model_file", type=str, default=None, help="Model file")

    params, other = parser.parse_known_args(argv)
    if params.cytomine_working_path is None:
        params.cytomine_working_path = os.path.join(tempfile.gettempdir(), "cytomine")
    make_dirs(params.cytomine_working_path)

    params.model_id_job = str2int(params.model_id_job)
    params.image = [str2int(i) for i in params.image]
    params.annotation = [str2int(i) for i in params.annotation]

    # Initialize logger
    logger = StandardOutputLogger(params.verbose)
    for key, val in sorted(vars(params).iteritems()):
        logger.info("[PARAMETER] {}: {}".format(key, val))

    # Start job
    with CytomineJob(params.cytomine_host,
                     params.cytomine_public_key,
                     params.cytomine_private_key,
                     params.cytomine_software,
                     params.cytomine_project,
                     parameters=vars(params),
                     working_path=params.cytomine_working_path,
                     base_path=params.cytomine_base_path,
                     verbose=(params.verbose >= Logger.DEBUG)) as job:
        cytomine = job
        cytomine.update_job_status(job.job, status_comment="Starting...", progress=0)

        cytomine.update_job_status(job.job, status_comment="Loading model...", progress=1)
        logger.i("Loading model...")
        if params.model_file:
            model_file = params.model_file
        else:
            model_job = cytomine.get_job(params.model_id_job)
            model_file = os.path.join(params.cytomine_working_path, "models", str(model_job.software),
                                      "{}.pkl".format(model_job.id))
        with open(model_file, 'rb') as f:
            estimator = pickle.load(f)
            predict_params = vars(params).copy()
            predict_params.pop("image", None)
            predict_params.pop("annotation", None)
            estimator.set_params(**predict_params)

        cytomine.update_job_status(job.job, status_comment="Dumping annotations/images to predict...", progress=3)
        logger.i("Dumping annotations/images to predict...")
        if params.annotation[0] is not None:
            annots = [cytomine.get_annotation(id) for id in params.annotation]
            annots_collection = AnnotationCollection()
            annots_collection._data = annots
            crops = cytomine.dump_annotations(annotations=annots_collection,
                                              dest_path=os.path.join(params.cytomine_working_path, "crops",
                                                                     str(params.cytomine_project)),
                                              desired_zoom=0,
                                              get_image_url_func=Annotation.get_annotation_alpha_crop_url)
            X = crops.data()
        elif params.image[0] is not None:
            image_instances = [cytomine.get_image_instance(id) for id in params.image]
            image_instances = cytomine.dump_project_images(id_project=params.cytomine_project,
                                                           dest_path="/imageinstances/",
                                                           image_instances=image_instances,
                                                           max_size=True)
            X = image_instances
        else:
            X = []

        logger.d("X size: {} samples".format(len(X)))

        for i, x in enumerate(X):
            logger.i("Predicting ID {}...".format(x.id))
            cytomine.update_job_status(job.job, status_comment="Predicting ID {}...".format(x.id),
                                       progress=5 + np.ceil(i / len(X)) * 95)
            y = estimator.predict([x.filename])
            y = estimator.postprocessing([y], **estimator.filter_sk_params(estimator.postprocessing))

            logger.i("Uploading annotations...")
            cytomine.update_job_status(job.job, status_comment="Uploading annotations...")
            upload_annotations(cytomine, x, y, term=params.cytomine_object_term)

        logger.i("Finished.")
        cytomine.update_job_status(job.job, status_comment="Finished.", progress=100)
示例#17
0
 def create_from_parameters(cls, parameters, logger=StandardOutputLogger(Logger.INFO)):
     kwargs = parameters if isinstance(parameters, dict) else vars(parameters)
     kwargs.update({'logger': logger})
     return cls(**kwargs)
示例#18
0
def train(argv):
    parser = ArgumentParser(prog="CNN Object Counter Model Builder")

    # Cytomine
    parser.add_argument('--cytomine_host', dest='cytomine_host',
                        default='demo.cytomine.be', help="The Cytomine host")
    parser.add_argument('--cytomine_public_key', dest='cytomine_public_key',
                        help="The Cytomine public key")
    parser.add_argument('--cytomine_private_key', dest='cytomine_private_key',
                        help="The Cytomine private key")
    parser.add_argument('--cytomine_base_path', dest='cytomine_base_path',
                        default='/api/', help="The Cytomine base path")
    parser.add_argument('--cytomine_working_path', dest='cytomine_working_path',
                        default=None, help="The working directory (eg: /tmp)")
    parser.add_argument('--cytomine_id_software', dest='cytomine_software', type=int,
                        help="The Cytomine software identifier")
    parser.add_argument('--cytomine_id_project', dest='cytomine_project', type=int,
                        help="The Cytomine project identifier")
    parser.add_argument('--cytomine_force_download', dest='cytomine_force_download', type=str, default=True,
                        help="Force download from Cytomine or not")

    # Objects
    parser.add_argument('--cytomine_object_term', dest='cytomine_object_term', type=int,
                        help="The Cytomine identifier of object term")
    parser.add_argument('--cytomine_object_user', dest='cytomine_object_user', type=str,
                        help="The Cytomine identifier of object owner")
    parser.add_argument('--cytomine_object_reviewed_only', dest='cytomine_object_reviewed_only', type=str,
                        help="Whether objects have to be reviewed or not")

    # ROI
    parser.add_argument('--cytomine_roi_term', dest='cytomine_roi_term', type=int, default=None,
                        help="The Cytomine identifier of region of interest term")
    parser.add_argument('--cytomine_roi_user', dest='cytomine_roi_user', type=str,
                        help="The Cytomine identifier of ROI owner")
    parser.add_argument('--cytomine_roi_reviewed_only', dest='cytomine_roi_reviewed_only', type=str,
                        help="Whether ROIs have to be reviewed or not")

    # Pre-processing
    parser.add_argument('--pre_transformer', dest='pre_transformer',
                        default='density', choices=['edt', 'euclidean_distance_transform', 'density', None, 'None'],
                        help="Scoremap transformer (None, edt, euclidean_distance_transform, density)")
    parser.add_argument('--pre_alpha', dest='pre_alpha', type=int, default=3,
                        help="Exponential decrease rate of distance (if EDT)")

    # Subwindows for training
    parser.add_argument('--sw_input_size', dest='sw_input_size', type=int, default=128,
                        help="Size of input subwindow")
    parser.add_argument('--sw_colorspace', dest="sw_colorspace", type=str, default='RGB__rgb',
                        help="List of colorspace features")
    parser.add_argument('--sw_extr_npi', dest="sw_extr_npi", type=int, default=100,
                        help="Number of extracted subwindows per image (if 'random' mode)")

    # CNN
    parser.add_argument('--cnn_architecture', '--architecture', dest='cnn_architecture',
                        type=str, choices=['FCRN-A', 'FCRN-B'], default='FCRN-A')
    parser.add_argument('--cnn_initializer', '--initializer', dest='cnn_initializer', type=str, default='orthogonal')
    parser.add_argument('--cnn_batch_normalization', '--batch_normalization', dest='cnn_batch_normalization', type=str,
                        default=True)
    parser.add_argument('--cnn_learning_rate', '--learning_rate', '--lr', dest='cnn_learning_rate', type=float,
                        default=0.01)
    parser.add_argument('--cnn_momentum', '--momentum', dest='cnn_momentum', type=float, default=0.9)
    parser.add_argument('--cnn_nesterov', '--nesterov', dest='cnn_nesterov', type=str, default=True)
    parser.add_argument('--cnn_decay', '--decay', dest='cnn_decay', type=float, default=0.0)
    parser.add_argument('--cnn_epochs', '--epochs', dest='cnn_epochs', type=int, default=24)
    parser.add_argument('--cnn_batch_size', '--batch_size', dest='cnn_batch_size', type=int, default=16)

    # Dataset augmentation
    parser.add_argument('--augmentation', dest='augmentation', type=str, default=True)
    parser.add_argument('--aug_rotation_range', dest='rotation_range', type=float, default=0.)
    parser.add_argument('--aug_width_shift_range', dest='width_shift_range', type=float, default=0.)
    parser.add_argument('--aug_height_shift_range', dest='height_shift_range', type=float, default=0.)
    parser.add_argument('--aug_zoom_range', dest='zoom_range', type=float, default=0.)
    parser.add_argument('--aug_fill_mode', dest='fill_mode', type=str, default="reflect")
    parser.add_argument('--aug_horizontal_flip', dest='horizontal_flip', type=bool, default=False)
    parser.add_argument('--aug_vertical_flip', dest='vertical_flip', type=bool, default=False)
    parser.add_argument('--aug_featurewise_center', dest='featurewise_center', type=bool, default=False)
    parser.add_argument('--aug_featurewise_std_normalization', dest='featurewise_std_normalization', type=bool,
                        default=False)

    # Execution
    parser.add_argument('--n_jobs', dest='n_jobs', type=int, default=1, help="Number of jobs")
    parser.add_argument('--verbose', '-v', dest='verbose', type=int, default=0, help="Level of verbosity")

    params, other = parser.parse_known_args(argv)
    if params.cytomine_working_path is None:
        params.cytomine_working_path = os.path.join(tempfile.gettempdir(), "cytomine")
    make_dirs(params.cytomine_working_path)

    params.cytomine_force_download = str2bool(params.cytomine_force_download)
    params.cytomine_object_reviewed_only = str2bool(params.cytomine_object_reviewed_only)
    params.cytomine_roi_reviewed_only = str2bool(params.cytomine_roi_reviewed_only)
    params.cnn_batch_normalization = str2bool(params.cnn_batch_normalization)
    params.cnn_nesterov = str2bool(params.cnn_nesterov)
    params.augmentation = str2bool(params.augmentation)

    d = 8. if params.cnn_architecture == 'FCRN-A' else 4.
    params.sw_size = (int(np.ceil(params.sw_input_size / d) * d), int(np.ceil(params.sw_input_size / d) * d))
    params.sw_input_size = params.sw_size
    params.sw_output_size = params.sw_size
    params.sw_colorspace = params.sw_colorspace.split(' ')
    params.sw_extr_mode = 'random'
    params.cnn_regularizer = None
    params.mean_radius = 2
    params.k_factor = 100

    if params.augmentation:
        params.rotation_range = check_default(params.rotation_range, 30., return_list=False)
        params.width_shift_range = check_default(params.width_shift_range, 0.3, return_list=False)
        params.height_shift_range = check_default(params.height_shift_range, 0.3, return_list=False)
        params.zoom_range = check_default(params.zoom_range, 0.3, return_list=False)
        params.fill_mode = check_default(params.fill_mode, 'constant', return_list=False)
        params.horizontal_flip = check_default(params.horizontal_flip, True, return_list=False)
        params.vertical_flip = check_default(params.vertical_flip, True, return_list=False)
        params.featurewise_center = check_default(params.featurewise_center, False, return_list=False)
        params.featurewise_std_normalization = check_default(params.featurewise_std_normalization, False,
                                                             return_list=False)

    # Initialize logger
    logger = StandardOutputLogger(params.verbose)
    for key, val in sorted(vars(params).iteritems()):
        logger.info("[PARAMETER] {}: {}".format(key, val))

    # Start job
    with CytomineJob(params.cytomine_host,
                     params.cytomine_public_key,
                     params.cytomine_private_key,
                     params.cytomine_software,
                     params.cytomine_project,
                     parameters=vars(params),
                     working_path=params.cytomine_working_path,
                     base_path=params.cytomine_base_path,
                     verbose=(params.verbose >= Logger.DEBUG)) as job:
        cytomine = job
        cytomine.update_job_status(job.job, status_comment="Starting...", progress=0)

        cytomine.update_job_status(job.job, status_comment="Loading training set...", progress=1)
        logger.i("Loading training set...")
        X, y = get_dataset(cytomine, params.cytomine_working_path, params.cytomine_project, params.cytomine_object_term,
                           params.cytomine_roi_term, params.cytomine_object_user, params.cytomine_object_reviewed_only,
                           params.cytomine_roi_user, params.cytomine_roi_reviewed_only, params.cytomine_force_download)
        logger.d("X size: {} samples".format(len(X)))
        logger.d("y size: {} samples".format(len(y)))

        # Rename parameters
        params.architecture = params.cnn_architecture
        params.initializer = params.cnn_initializer
        params.regularizer = params.cnn_regularizer
        params.batch_normalization = params.cnn_batch_normalization
        params.learning_rate = params.cnn_learning_rate
        params.momentum = params.cnn_momentum
        params.nesterov = params.cnn_nesterov
        params.decay = params.cnn_decay
        params.epochs = params.cnn_epochs
        params.batch_size = params.cnn_batch_size

        model_path = os.path.join(params.cytomine_working_path, "models", str(params.cytomine_software))
        model_file = os.path.join(model_path, "{}.h5".format(job.job.id))
        make_dirs(model_path)

        # Callbacks
        # checkpoint_callback = ModelCheckpoint(model_file, monitor='loss', save_best_only=True)
        lr_callback = LearningRateScheduler(lr_scheduler)
        callbacks = [lr_callback]

        logger.i("Training FCRN...")
        cytomine.update_job_status(job.job, status_comment="Training FCRN...", progress=5)
        estimator = FCRN(FCRN.build_fcrn, callbacks, **vars(params))
        estimator.fit(np.asarray(X), np.asarray(y))

        logger.i("Saving model...")
        cytomine.update_job_status(job.job, status_comment="Saving (best) model", progress=95)
        estimator.save(model_file)

        logger.i("Finished.")
        cytomine.update_job_status(job.job, status_comment="Finished.", progress=100)