Beispiel #1
0
def run():
    """
    Deletes all the annotations from an image, but those created by a software

    Example:
      python main.py --cytomine_host 'localhost-core' --cytomine_public_key 'b6ebb23c-00ff-427b-be24-87b2a82490df' --cytomine_private_key '6812f09b-3f33-4938-82ca-b23032d377fd' --cytomine_id_image_instance 347 --cytomine_id_user 61 --cytomine_id_project 154

      python main.py --cytomine_host 'localhost-core' --cytomine_public_key 'b6ebb23c-00ff-427b-be24-87b2a82490df' --cytomine_private_key '6812f09b-3f33-4938-82ca-b23032d377fd' --cytomine_id_image_instance 3643 --cytomine_id_user 61 --cytomine_id_project 154

      python main.py --cytomine_host 'localhost-core' --cytomine_public_key 'd2be8bd7-2b0b-40c3-9e81-5ad5765568f3' --cytomine_private_key '6dfe27d7-2ad1-4ca2-8ee9-6321ec3f1318' --cytomine_id_image_instance 2140 --cytomine_id_user 58 --cytomine_id_project 197
    """
    parser = ArgumentParser(prog="Cytomine Python client example")

    # Cytomine
    parser.add_argument('--cytomine_host',
                        dest='host',
                        default='demo.cytomine.be',
                        help="The Cytomine host")
    parser.add_argument('--cytomine_public_key',
                        dest='public_key',
                        help="The Cytomine public key")
    parser.add_argument('--cytomine_private_key',
                        dest='private_key',
                        help="The Cytomine private key")

    parser.add_argument('--cytomine_id_image_instance',
                        dest='id_image_instance',
                        help="The image with annotations to delete")
    parser.add_argument('--cytomine_id_user',
                        dest='id_user',
                        help="The user with annotations to delete")
    parser.add_argument('--cytomine_id_project',
                        dest='id_project',
                        help="The project with annotations to delete")
    params, _ = parser.parse_known_args(sys.argv[1:])

    with Cytomine(host=params.host,
                  public_key=params.public_key,
                  private_key=params.private_key,
                  verbose=logging.INFO) as cytomine:
        # Get the list of annotations
        annotations = AnnotationCollection()
        annotations.image = params.id_image_instance
        # NOTE: use userjob id to retrieve annotations from the job. However, they
        # cannot be deleted.
        annotations.user = params.id_user
        annotations.project = params.id_project
        annotations.fetch()
        print(annotations)

        for annotation in annotations:
            annotation.delete()
def main(argv):
    parser = ArgumentParser()
    parser.add_argument(*_cytomine_parameter_name_synonyms("project_id"),
                        dest="project_id",
                        type=int,
                        help="The Cytomine project id.",
                        required=True)
    parser.add_argument(
        "-i",
        "--ignore-existing",
        action="store_true",
        dest="ignore_existing",
        help=
        "Ignore existing ground truth annotation associated with the project. If not specified,"
        " current annotations will be deleted before uploading the new ones.")
    parser.set_defaults(ignore_existing=False)
    options, _ = parser.parse_known_args(argv)

    with Cytomine.connect_from_cli(argv) as cytomine:
        project = Project().fetch(options.project_id)
        print("Project '{}' (#{}): discipline '{}'".format(
            project.name, project.id, project.disciplineShortName))

        if not options.ignore_existing:
            annotations = AnnotationCollection()
            annotations.project = project.id
            annotations.user = cytomine.current_user.id
            annotations.fetch()
            delete_collection(annotations, "annotation")

            tracks = TrackCollection()
            tracks.project = project.id
            tracks.user = cytomine.current_user.id
            tracks.fetch_with_filter("project", project.id)
            tracks._data = [
                t for t in tracks.data() if t.name.startswith("gt-")
            ]
            delete_collection(tracks, "track")

        fake_job = FakeJob(project)
        home = Path.home()
        in_path = os.path.join(home, "data", "in")
        gt_path = os.path.join(home, "data", "gt")
        os.makedirs(in_path)
        os.makedirs(gt_path)
        in_images, gt_images = download_images(fake_job,
                                               in_path,
                                               gt_path,
                                               gt_suffix="_lbl")

        if project.disciplineShortName == "TreTrc":
            # ground truth is contained in swc files so need to
            # convert them into masks beforehand
            print("TreTrc problem: start converting SWC to masks")
            download_attached(in_images, gt_path, do_download=True)
            alternate_gt_path = os.path.join(home, "data", "altgt")
            os.makedirs(alternate_gt_path)
            for in_image in in_images:
                swc_filepath = in_image.attached[0].filepath
                im_size = imageio.volread(
                    in_image.filepath).shape  # Size is Depth,Height,Width
                im_size = im_size[::
                                  -1]  # Invert the size order to Width,Height,Depth
                swc_to_tiff_stack(input_path=swc_filepath,
                                  output_path=os.path.join(
                                      alternate_gt_path, in_image.filename),
                                  im_size=im_size)
            gt_path = alternate_gt_path

        is_2d = guess_dims(gt_path)
        print("Image detected as {}".format("2d" if is_2d else ">2d"))
        upload_data(problemclass=project.disciplineShortName,
                    nj=fake_job,
                    inputs=in_images,
                    out_path=gt_path,
                    is_2d=is_2d,
                    projection=-1)
    parser.add_argument('--cytomine_private_key',
                        dest='private_key',
                        help="The Cytomine private key")

    parser.add_argument('--cytomine_id_image_instance',
                        dest='id_image_instance',
                        help="The image with annotations to delete")
    parser.add_argument('--cytomine_id_user',
                        dest='id_user',
                        help="The user with annotations to delete")
    parser.add_argument('--cytomine_id_project',
                        dest='id_project',
                        help="The project with annotations to delete")
    params, other = parser.parse_known_args(sys.argv[1:])

    with Cytomine(host=params.host,
                  public_key=params.public_key,
                  private_key=params.private_key,
                  verbose=logging.INFO) as cytomine:

        # Get the list of annotations
        annotations = AnnotationCollection()
        annotations.image = params.id_image_instance
        annotations.user = params.id_user
        annotations.project = params.id_project
        annotations.fetch()
        print(annotations)

        for annotation in annotations:
            annotation.delete()
    # Cytomine
    parser.add_argument('--cytomine_host', dest='host',
                        default='demo.cytomine.be', help="The Cytomine host")
    parser.add_argument('--cytomine_public_key', dest='public_key',
                        help="The Cytomine public key")
    parser.add_argument('--cytomine_private_key', dest='private_key',
                        help="The Cytomine private key")

    parser.add_argument('--cytomine_id_image_instance', dest='id_image_instance',
                        help="The image with annotations to delete")
    parser.add_argument('--cytomine_id_user', dest='id_user',
                        help="The user with annotations to delete")
    parser.add_argument('--cytomine_id_project', dest='id_project',
                        help="The project with annotations to delete")
    params, other = parser.parse_known_args(sys.argv[1:])

    with Cytomine(host=params.host, public_key=params.public_key, private_key=params.private_key,
                  verbose=logging.INFO) as cytomine:

        # Get the list of annotations
        annotations = AnnotationCollection()
        annotations.image = params.id_image_instance
        annotations.user = params.id_user
        annotations.project = params.id_project
        annotations.fetch()
        print(annotations)

        for annotation in annotations:
            annotation.delete()
def get_images_mask_per_annotation_per_user(proj_id, image_id, user_id,
                                            scale_factor, dest):
    im = ImageInstanceCollection()
    im.project = proj_id
    im.image = image_id
    im.fetch_with_filter("project", proj_id)
    image_width = int(im[0].width)
    image_height = int(im[0].height)
    print(image_height, image_width)

    annotations = AnnotationCollection()
    annotations.project = proj_id
    annotations.image = image_id

    annotations.user = user_id
    annotations.showWKT = True
    annotations.showMeta = True
    annotations.showTerm = True
    annotations.showGIS = True
    annotations.showImage = True
    annotations.showUser = True
    annotations.fetch()

    dct_anotations = {}
    for a in annotations:
        print(a.user)
        if len(a.term) == 1:
            term = a.term[0]
            if term not in dct_anotations:
                dct_anotations[term] = []
            dct_anotations[term].append(a.location)
        else:
            warnings.warn("Not suited for multiple or no annotation term")
    for t, lanno in dct_anotations.items():
        result_image = Image.new(mode='1',
                                 size=(int(image_width * scale_factor),
                                       int(image_height * scale_factor)),
                                 color=0)
        for pwkt in lanno:
            if pwkt.startswith("POLYGON"):
                label = "POLYGON"
            elif pwkt.startswith("MULTIPOLYGON"):
                label = "MULTIPOLYGON"

            coordinatesStringList = pwkt.replace(label, '')

            if label == "POLYGON":
                coordinates_string_lists = [coordinatesStringList]
            elif label == "MULTIPOLYGON":
                coordinates_string_lists = coordinatesStringList.split(
                    ')), ((')

                coordinates_string_lists = [
                    coordinatesStringList.replace('(', '').replace(')', '')
                    for coordinatesStringList in coordinates_string_lists
                ]

            for coordinatesStringList in coordinates_string_lists:
                #  create lists of x and y coordinates
                x_coords = []
                y_coords = []
                for point in coordinatesStringList.split(','):
                    point = point.strip(
                        string.whitespace)  # remove leading and ending spaces
                    point = point.strip(
                        string.punctuation
                    )  # Have seen some strings have a ')' at the end so remove it
                    x_coords.append(round(float(point.split(' ')[0])))
                    y_coords.append(round(float(point.split(' ')[1])))

                x_coords_correct_lod = [
                    int(x * scale_factor) for x in x_coords
                ]
                y_coords_correct_lod = [
                    image_height * scale_factor - int(x * scale_factor)
                    for x in y_coords
                ]
                coords = [
                    (i, j)
                    for i, j in zip(x_coords_correct_lod, y_coords_correct_lod)
                ]

                #  draw the polygone in an image and fill it
                ImageDraw.Draw(result_image).polygon(coords, outline=1, fill=1)

        result_image.save(params.dest + '/' + str(t) + '.png')
Beispiel #6
0
def main(argv):
    with CytomineJob.from_cli(argv) as conn:
        # with Cytomine(argv) as conn:
        print(conn.parameters)

        conn.job.update(status=Job.RUNNING,
                        progress=0,
                        statusComment="Initialization...")
        base_path = "{}".format(os.getenv("HOME"))  # Mandatory for Singularity
        working_path = os.path.join(base_path, str(conn.job.id))

        # with Cytomine(host=params.host, public_key=params.public_key, private_key=params.private_key,
        #           verbose=logging.INFO) as cytomine:

        # ontology = Ontology("classPNcells"+str(conn.parameters.cytomine_id_project)).save()
        # ontology_collection=OntologyCollection().fetch()
        # print(ontology_collection)
        # ontology = Ontology("CLASSPNCELLS").save()
        # terms = TermCollection().fetch_with_filter("ontology", ontology.id)
        terms = TermCollection().fetch_with_filter(
            "project", conn.parameters.cytomine_id_project)
        conn.job.update(status=Job.RUNNING,
                        progress=1,
                        statusComment="Terms collected...")
        print(terms)

        # term_P = Term("PositiveCell", ontology.id, "#FF0000").save()
        # term_N = Term("NegativeCell", ontology.id, "#00FF00").save()
        # term_P = Term("PositiveCell", ontology, "#FF0000").save()
        # term_N = Term("NegativeCell", ontology, "#00FF00").save()

        # Get all the terms of our ontology
        # terms = TermCollection().fetch_with_filter("ontology", ontology.id)
        # terms = TermCollection().fetch_with_filter("ontology", ontology)
        # print(terms)

        # #Loading pre-trained Stardist model
        # np.random.seed(17)
        # lbl_cmap = random_label_cmap()
        # #Stardist H&E model downloaded from https://github.com/mpicbg-csbd/stardist/issues/46
        # #Stardist H&E model downloaded from https://drive.switch.ch/index.php/s/LTYaIud7w6lCyuI
        # model = StarDist2D(None, name='2D_versatile_HE', basedir='/models/')   #use local model file in ~/models/2D_versatile_HE/

        #Select images to process
        images = ImageInstanceCollection().fetch_with_filter(
            "project", conn.parameters.cytomine_id_project)
        conn.job.update(status=Job.RUNNING,
                        progress=2,
                        statusComment="Images gathered...")

        list_imgs = []
        if conn.parameters.cytomine_id_images == 'all':
            for image in images:
                list_imgs.append(int(image.id))
        else:
            list_imgs = [
                int(id_img)
                for id_img in conn.parameters.cytomine_id_images.split(',')
            ]
            print(list_imgs)

        #Go over images
        conn.job.update(status=Job.RUNNING,
                        progress=10,
                        statusComment="Running PN classification on image...")
        #for id_image in conn.monitor(list_imgs, prefix="Running PN classification on image", period=0.1):
        for id_image in list_imgs:

            roi_annotations = AnnotationCollection()
            roi_annotations.project = conn.parameters.cytomine_id_project
            roi_annotations.term = conn.parameters.cytomine_id_cell_term
            roi_annotations.image = id_image  #conn.parameters.cytomine_id_image
            roi_annotations.job = conn.parameters.cytomine_id_annotation_job
            roi_annotations.user = conn.parameters.cytomine_id_user_job
            roi_annotations.showWKT = True
            roi_annotations.fetch()
            print(roi_annotations)

            #Go over ROI in this image
            #for roi in conn.monitor(roi_annotations, prefix="Running detection on ROI", period=0.1):
            for roi in roi_annotations:
                #Get Cytomine ROI coordinates for remapping to whole-slide
                #Cytomine cartesian coordinate system, (0,0) is bottom left corner
                print(
                    "----------------------------Cells------------------------------"
                )
                roi_geometry = wkt.loads(roi.location)
                # print("ROI Geometry from Shapely: {}".format(roi_geometry))
                #                 print("ROI Bounds")
                #                 print(roi_geometry.bounds)
                minx = roi_geometry.bounds[0]
                miny = roi_geometry.bounds[3]
                #Dump ROI image into local PNG file
                # roi_path=os.path.join(working_path,str(roi_annotations.project)+'/'+str(roi_annotations.image)+'/'+str(roi.id))
                roi_path = os.path.join(
                    working_path,
                    str(roi_annotations.project) + '/' +
                    str(roi_annotations.image) + '/')
                #                 print(roi_path)
                roi_png_filename = os.path.join(roi_path + str(roi.id) +
                                                '.png')
                conn.job.update(status=Job.RUNNING,
                                progress=20,
                                statusComment=roi_png_filename)
                #                 print("roi_png_filename: %s" %roi_png_filename)
                roi.dump(dest_pattern=roi_png_filename, alpha=True)
                #roi.dump(dest_pattern=os.path.join(roi_path,"{id}.png"), mask=True, alpha=True)

                # im=Image.open(roi_png_filename)

                J = cv2.imread(roi_png_filename, cv2.IMREAD_UNCHANGED)
                J = cv2.cvtColor(J, cv2.COLOR_BGRA2RGBA)
                [r, c, h] = J.shape
                # print("J: ",J)

                if r < c:
                    blocksize = r
                else:
                    blocksize = c
                # print("blocksize:",blocksize)
                rr = np.zeros((blocksize, blocksize))
                cc = np.zeros((blocksize, blocksize))

                zz = [*range(1, blocksize + 1)]
                # print("zz:", zz)
                for i in zz:
                    rr[i - 1, :] = zz
                # print("rr shape:",rr.shape)

                zz = [*range(1, blocksize + 1)]
                for i in zz:
                    cc[:, i - 1] = zz
                # print("cc shape:",cc.shape)

                cc1 = np.asarray(cc) - 16.5
                rr1 = np.asarray(rr) - 16.5
                cc2 = np.asarray(cc1)**2
                rr2 = np.asarray(rr1)**2
                rrcc = np.asarray(cc2) + np.asarray(rr2)

                weight = np.sqrt(rrcc)
                # print("weight: ",weight)
                weight2 = 1. / weight
                # print("weight2: ",weight2)
                #                 print("weight2 shape:",weight2.shape)
                coord = [c / 2, r / 2]
                halfblocksize = blocksize / 2

                y = round(coord[1])
                x = round(coord[0])

                # Convert the RGB image to HSV
                Jalpha = J[:, :, 3]
                Jalphaloc = Jalpha / 255
                Jrgb = cv2.cvtColor(J, cv2.COLOR_RGBA2RGB)
                Jhsv = cv2.cvtColor(Jrgb, cv2.COLOR_RGB2HSV_FULL)
                Jhsv = Jhsv / 255
                Jhsv[:, :, 0] = Jhsv[:, :, 0] * Jalphaloc
                Jhsv[:, :, 1] = Jhsv[:, :, 1] * Jalphaloc
                Jhsv[:, :, 2] = Jhsv[:, :, 2] * Jalphaloc
                # print("Jhsv: ",Jhsv)

                # print("Jhsv size:",Jhsv.shape)
                # print("Jhsv class:",Jhsv.dtype)

                currentblock = Jhsv[0:blocksize, 0:blocksize, :]
                # print("currentblock: ",currentblock)
                #                 print(currentblock.dtype)
                currentblockH = currentblock[:, :, 0]
                currentblockV = 1 - currentblock[:, :, 2]
                hue = sum(sum(currentblockH * weight2))
                val = sum(sum(currentblockV * weight2))
                #                 print("hue:", hue)
                #                 print("val:", val)

                if hue < 2:
                    cellclass = 1
                elif val < 15:
                    cellclass = 2
                else:
                    if hue < 30 or val > 40:
                        cellclass = 1
                    else:
                        cellclass = 2

                # tags = TagCollection().fetch()
                # tags = TagCollection()
                # print(tags)

                if cellclass == 1:
                    #                     print("Positive (H: ", str(hue), ", V: ", str(val), ")")
                    id_terms = conn.parameters.cytomine_id_positive_term
                    # tag = Tag("Positive (H: ", str(hue), ", V: ", str(val), ")").save()
                    # print(tag)
                    # id_terms=Term("PositiveCell", ontology.id, "#FF0000").save()
                elif cellclass == 2:
                    #                     print("Negative (H: ", str(hue), ", V: ", str(val), ")")
                    id_terms = conn.parameters.cytomine_id_negative_term
                    # for t in tags:
                    # tag = Tag("Negative (H: ", str(hue), ", V: ", str(val), ")").save()
                    # print(tag)
                    # id_terms=Term("NegativeCell", ontology.id, "#00FF00").save()

                    # First we create the required resources

                cytomine_annotations = AnnotationCollection()
                # property_collection = PropertyCollection(uri()).fetch("annotation",id_image)
                # property_collection = PropertyCollection().uri()
                # print(property_collection)
                # print(cytomine_annotations)

                # property_collection.append(Property(Annotation().fetch(id_image), key="Hue", value=str(hue)))
                # property_collection.append(Property(Annotation().fetch(id_image), key="Val", value=str(val)))
                # property_collection.save()

                # prop1 = Property(Annotation().fetch(id_image), key="Hue", value=str(hue)).save()
                # prop2 = Property(Annotation().fetch(id_image), key="Val", value=str(val)).save()

                # prop1.Property(Annotation().fetch(id_image), key="Hue", value=str(hue)).save()
                # prop2.Property(Annotation().fetch(id_image), key="Val", value=str(val)).save()

                # for pos, polygroup in enumerate(roi_geometry,start=1):
                #     points=list()
                #     for i in range(len(polygroup[0])):
                #         p=Point(minx+polygroup[1][i],miny-polygroup[0][i])
                #         points.append(p)

                annotation = roi_geometry

                # tags.append(TagDomainAssociation(Annotation().fetch(id_image, tag.id))).save()

                # association = append(TagDomainAssociation(Annotation().fetch(id_image, tag.id))).save()
                # print(association)

                cytomine_annotations.append(
                    Annotation(
                        location=annotation.wkt,  #location=roi_geometry,
                        id_image=id_image,  #conn.parameters.cytomine_id_image,
                        id_project=conn.parameters.cytomine_id_project,
                        id_terms=[id_terms]))
                print(".", end='', flush=True)

                #Send Annotation Collection (for this ROI) to Cytomine server in one http request
                ca = cytomine_annotations.save()

        conn.job.update(status=Job.TERMINATED,
                        progress=100,
                        statusComment="Finished.")
Beispiel #7
0
def main(argv):
    with CytomineJob.from_cli(argv) as conn:
        conn.job.update(progress=0, statusComment="Initialization..")
        base_path = "{}".format(os.getenv("HOME"))  # Mandatory for Singularity
        working_path = os.path.join(base_path, str(conn.job.id))

        # Load pretrained model (assume the best of all)
        conn.job.update(progress=0,
                        statusComment="Loading segmentation model..")

        with open("/models/resnet50b_fpn256/config.json") as f:
            config = json.load(f)
        model = FPN.build_resnet_fpn(
            name=config['name'],
            input_size=conn.parameters.dataset_patch_size,  # must be / by 16
            input_channels=1 if config['input']['mode'] == 'grayscale' else 3,
            output_channels=config['fpn']['out_channels'],
            num_classes=2,  # legacy
            in_features=config['fpn']['in_features'],
            out_features=config['fpn']['out_features'])
        model.to(_DEVICE)
        model_dict = torch.load(config['weights'],
                                map_location=torch.device(_DEVICE))
        model.load_state_dict(model_dict['model'])

        # Select images to process
        images = ImageInstanceCollection().fetch_with_filter(
            "project", conn.parameters.cytomine_id_project)

        if conn.parameters.cytomine_id_images != 'all':
            images = [
                _ for _ in images
                if _.id in map(lambda x: int(x.strip()),
                               conn.parameters.cytomine_id_images.split(','))
            ]
        images_id = [image.id for image in images]

        # Download selected images into "working_directory"
        img_path = os.path.join(working_path, "images")
        os.makedirs(img_path)
        for image in conn.monitor(
                images,
                start=2,
                end=50,
                period=0.1,
                prefix="Downloading images into working directory.."):
            fname, fext = os.path.splitext(image.filename)
            if image.download(dest_pattern=os.path.join(
                    img_path, "{}{}".format(image.id, fext))) is not True:

                print("Failed to download image {}".format(image.filename))

        # create a file that lists all images (used by PatchBasedDataset
        conn.job.update(progress=50,
                        statusComment="Preparing data for execution..")
        images = os.listdir(img_path)
        images = list(map(lambda x: x + '\n', images))
        with open(os.path.join(working_path, 'images.txt'), 'w') as f:
            f.writelines(images)

        # Prepare dataset and dataloader objects
        ImgTypeBits = {'.dcm': 16}
        channel_bits = ImgTypeBits.get(fext.lower(), 8)
        mean, std = compute_mean_and_std(img_path, bits=channel_bits)

        dataset = InferencePatchBasedDataset(
            path=working_path,
            subset='images',
            patch_size=conn.parameters.dataset_patch_size,
            mode=config['input']['mode'],
            bits=channel_bits,
            mean=mean,
            std=std)

        dataloader = DataLoader(
            dataset=dataset,
            batch_size=conn.parameters.model_batch_size,
            drop_last=False,
            shuffle=False,
            num_workers=0,
            collate_fn=InferencePatchBasedDataset.collate_fn)

        # Go over images
        conn.job.update(status=Job.RUNNING,
                        progress=55,
                        statusComment="Running inference on images..")
        results = inference_on_segmentation(
            model, dataloader, conn.parameters.postprocess_p_threshold)

        for id_image in conn.monitor(
                images_id,
                start=90,
                end=95,
                prefix="Deleting old annotations on images..",
                period=0.1):
            # Delete old annotations
            del_annotations = AnnotationCollection()
            del_annotations.image = id_image
            del_annotations.user = conn.job.id
            del_annotations.project = conn.parameters.cytomine_id_project
            del_annotations.term = conn.parameters.cytomine_id_predict_term,
            del_annotations.fetch()
            for annotation in del_annotations:
                annotation.delete()

        conn.job.update(
            status=Job.RUNNING,
            progress=95,
            statusComment="Uploading new annotations to Cytomine server..")
        annotations = AnnotationCollection()
        for instance in results:
            idx, _ = os.path.splitext(instance['filename'])
            width, height = instance['size']

            for box in instance['bbox']:
                points = [
                    Point(box[0], height - 1 - box[1]),
                    Point(box[0], height - 1 - box[3]),
                    Point(box[2], height - 1 - box[3]),
                    Point(box[2], height - 1 - box[1])
                ]
                annotation = Polygon(points)

                annotations.append(
                    Annotation(
                        location=annotation.wkt,
                        id_image=int(idx),
                        id_terms=[conn.parameters.cytomine_id_predict_term],
                        id_project=conn.parameters.cytomine_id_project))
        annotations.save()

        conn.job.update(status=Job.TERMINATED,
                        status_comment="Finish",
                        progress=100)