コード例 #1
0
def removeFatlikeTissue(s, params):
    logging.info(f"{s['filename']} - \tremoveFatlikeTissue")
    fat_cell_size = int(params.get("fat_cell_size", 64))
    kernel_size = int(params.get("kernel_size", 3))
    max_keep_size = int(params.get("max_keep_size", 1000))

    img_reduced = morphology.remove_small_holes(s["img_mask_use"],
                                                min_size=fat_cell_size)
    img_small = img_reduced & np.invert(s["img_mask_use"])
    img_small = ~morphology.remove_small_holes(~img_small, min_size=9)

    mask_dilate = morphology.dilation(img_small,
                                      selem=np.ones(
                                          (kernel_size, kernel_size)))
    mask_dilate_removed = remove_large_objects(mask_dilate, max_keep_size)

    mask_fat = mask_dilate & ~mask_dilate_removed

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_fatlike.png",
              mask_fat * 255)
    s["img_mask_fatlike"] = (mask_fat * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = prev_mask & ~mask_fat

    s.addToPrintList(
        "percent_fatlike_tissue_removed",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))
コード例 #2
0
def identifyBlurryRegions(s, params):
    logging.info(f"{s['filename']} - \tidentifyBlurryRegions")

    blur_radius = int(params.get("blur_radius", 7))
    blur_threshold = float(params.get("blur_threshold", .1))

    img = s.getImgThumb(params.get("image_work_size", "2.5x"))
    img = rgb2gray(img)
    img_laplace = np.abs(skimage.filters.laplace(rgb2gray(img)))
    mask = skimage.filters.gaussian(img_laplace,
                                    sigma=blur_radius) <= blur_threshold

    mask = skimage.transform.resize(
        mask, s.getImgThumb(s["image_work_size"]).shape, order=0
    )[:, :, 1]  # for some reason resize takes a grayscale and produces a 3chan
    mask = s["img_mask_use"] & (mask > 0)

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_blurry.png", mask * 255)
    s["img_mask_blurry"] = (mask * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_blurry"]

    s.addToPrintList(
        "percent_blurry",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    return
コード例 #3
0
ファイル: BasicModule.py プロジェクト: ylch/HistoQC
def finalProcessingArea(s, params):
    logging.info(f"{s['filename']} - \tfinalProcessingArea")
    area_thresh = int(params.get("area_threshold", "1000"))
    mask = s["img_mask_use"]

    mask_opened = remove_small_objects(mask, min_size=area_thresh)
    mask_removed_area = ~mask_opened & mask

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_areathresh.png",
              img_as_ubyte(mask_removed_area))

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = mask_opened > 0

    s.addToPrintList(
        "areaThresh",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After BasicModule.finalProcessingArea NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After BasicModule.finalProcessingArea NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
コード例 #4
0
def detectSmoothness(s, params):
        logging.info(f"{s['filename']} - \tBubbleRegionByRegion.detectSmoothness")
        thresh = float(params.get("threshold", ".01" ))
        kernel_size = int(params.get("kernel_size", "10"))
        min_object_size = int(params.get("min_object_size", "100"))

        img = s.getImgThumb(s["image_work_size"])
        img = color.rgb2gray(img)
        avg = np.ones((kernel_size, kernel_size)) / (kernel_size**2)

        imf = scipy.signal.convolve2d(img, avg, mode="same")
        mask_flat = abs(imf - img) < thresh

        mask_flat = remove_small_objects(mask_flat, min_size=min_object_size)
        mask_flat = ~remove_small_objects(~mask_flat, min_size=min_object_size)

        prev_mask = s["img_mask_use"]
        s["img_mask_flat"] = mask_flat

        io.imsave(s["outdir"] + os.sep + s["filename"] + "_flat.png", img_as_ubyte(mask_flat & prev_mask))

        s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_flat"]


        s.addToPrintList("flat_areas",
                         printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask,
                                         s["img_mask_use"]))

        if len(s["img_mask_use"].nonzero()[0]) == 0:  # add warning in case the final tissue is empty
            logging.warning(f"{s['filename']} - After BubbleRegionByRegion.detectSmoothness: NO tissue "
                            f"remains detectable! Downstream modules likely to be incorrect/fail")
            s["warnings"].append(f"After BubbleRegionByRegion.detectSmoothness: NO tissue remains "
                                 f"detectable! Downstream modules likely to be incorrect/fail")

        return
コード例 #5
0
ファイル: MorphologyModule.py プロジェクト: sbalci/HistoQC
def removeFatlikeTissue(s, params):
    logging.info(f"{s['filename']} - \tremoveFatlikeTissue")
    fat_cell_size = int(params.get("fat_cell_size", 64))
    kernel_size = int(params.get("kernel_size", 3))
    max_keep_size = int(params.get("max_keep_size", 1000))

    img_reduced = morphology.remove_small_holes(s["img_mask_use"], area_threshold=fat_cell_size)
    img_small = img_reduced & np.invert(s["img_mask_use"])
    img_small = ~morphology.remove_small_holes(~img_small, area_threshold=9)

    mask_dilate = morphology.dilation(img_small, selem=np.ones((kernel_size, kernel_size)))
    mask_dilate_removed = remove_large_objects(mask_dilate, max_keep_size)

    mask_fat = mask_dilate & ~mask_dilate_removed

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_fatlike.png", img_as_ubyte(mask_fat))
    s["img_mask_fatlike"] = (mask_fat * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = prev_mask & ~mask_fat

    s.addToPrintList("percent_fatlike_tissue_removed",
                     printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()[0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(f"{s['filename']} - After MorphologyModule.removeFatlikeTissue: NO tissue "
                        f"remains detectable! Downstream modules likely to be incorrect/fail")
        s["warnings"].append(f"After MorphologyModule.removeFatlikeTissue: NO tissue remains "
                             f"detectable! Downstream modules likely to be incorrect/fail")
コード例 #6
0
ファイル: LightDarkModule.py プロジェクト: NKI-AI/HistoQC
def minimumPixelIntensityNeighborhoodFiltering(s,params):
    logging.info(f"{s['filename']} - \tLightDarkModule.minimumPixelNeighborhoodFiltering")
    disk_size = int(params.get("disk_size", 10000))
    threshold = int(params.get("upper_threshold", 200))

    img = s.getImgThumb(s["image_work_size"])
    img = color.rgb2gray(img)
    img = (img * 255).astype(np.uint8)
    selem = disk(disk_size)

    imgfilt = rank.minimum(img, selem)
    s["img_mask_bright"] = imgfilt > threshold


    if strtobool(params.get("invert", "True")):
        s["img_mask_bright"] = ~s["img_mask_bright"]

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & s["img_mask_bright"]

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_bright.png", img_as_ubyte(prev_mask & ~s["img_mask_bright"]))

    s.addToPrintList("brightestPixels",
                     printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()[0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(f"{s['filename']} - After LightDarkModule.minimumPixelNeighborhoodFiltering NO tissue "
                        f"remains detectable! Downstream modules likely to be incorrect/fail")
        s["warnings"].append(f"After LightDarkModule.minimumPixelNeighborhoodFiltering NO tissue remains "
                             f"detectable! Downstream modules likely to be incorrect/fail")

    return
コード例 #7
0
def fillSmallHoles(s, params):
    logging.info(f"{s['filename']} - \tfillSmallHoles")
    min_size = int(params.get("min_size", 64))
    img_reduced = morphology.remove_small_holes(s["img_mask_use"],
                                                area_threshold=min_size)
    img_small = img_reduced & np.invert(s["img_mask_use"])

    # io.imsave(s["outdir"] + os.sep + s["filename"] + "_small_fill.png", img_as_ubyte(img_small))
    s["img_mask_small_removed"] = (img_small * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = img_reduced

    s.addToPrintList(
        "percent_small_tissue_filled",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After MorphologyModule.fillSmallHoles: NO tissue "
            f"remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After MorphologyModule.fillSmallHoles: NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")
    return
コード例 #8
0
ファイル: BasicModule.py プロジェクト: ylch/HistoQC
def finalProcessingSpur(s, params):
    logging.info(f"{s['filename']} - \tfinalProcessingSpur")
    disk_radius = int(params.get("disk_radius", "25"))
    selem = disk(disk_radius)
    mask = s["img_mask_use"]
    mask_opened = binary_opening(mask, selem)
    mask_spur = ~mask_opened & mask

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_spur.png",
              img_as_ubyte(mask_spur))

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = mask_opened

    s.addToPrintList(
        "spur_pixels",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After BasicModule.finalProcessingSpur NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After BasicModule.finalProcessingSpur NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
コード例 #9
0
def identifyBlurryRegions(s, params):
    logging.info(f"{s['filename']} - \tidentifyBlurryRegions")

    blur_radius = int(params.get("blur_radius", 7))
    blur_threshold = float(params.get("blur_threshold", .1))

    img = s.getImgThumb(params.get("image_work_size", "2.5x"))
    img = rgb2gray(img)
    img_laplace = np.abs(skimage.filters.laplace(img))
    mask = skimage.filters.gaussian(img_laplace, sigma=blur_radius) <= blur_threshold

    mask = skimage.transform.resize(mask, s.getImgThumb(s["image_work_size"]).shape, order=0)[:, :,
           1]  # for some reason resize takes a grayscale and produces a 3chan
    mask = s["img_mask_use"] & (mask > 0)

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_blurry.png", img_as_ubyte(mask))
    s["img_mask_blurry"] = (mask * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_blurry"]

    s.addToPrintList("percent_blurry",
                     printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()[0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After BlurDetectionModule.identifyBlurryRegions NO tissue remains detectable! Downstream modules likely to be incorrect/fail")
        s["warnings"].append(
            f"After BlurDetectionModule.identifyBlurryRegions NO tissue remains detectable! Downstream modules likely to be incorrect/fail")


    return
コード例 #10
0
def pixelWise(s, params):
    name = params.get("name", "classTask")
    logging.info(f"{s['filename']} - \tpixelWise:\t", name)

    thresh = float(params.get("threshold", .5))

    fname = params.get("tsv_file", "")
    if fname == "":
        logging.error(
            f"{s['filename']} - tsv_file not set in ClassificationModule.pixelWise for ",
            name)
        sys.exit(1)
        return
    model_vals = np.loadtxt(fname, delimiter="\t", skiprows=1)

    img = s.getImgThumb(s["image_work_size"])

    gnb = GaussianNB()
    gnb.fit(model_vals[:, 1:], model_vals[:, 0])
    cal = gnb.predict_proba(img.reshape(-1, 3))

    cal = cal.reshape(img.shape[0], img.shape[1], 2)
    mask = cal[:, :, 1] > thresh

    mask = s["img_mask_use"] & (mask > 0)

    s.addToPrintList(name, str(mask.mean()))

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_" + name + ".png",
              img_as_ubyte(mask))
    s["img_mask_" + name] = (mask * 255) > 0
    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_" + name]

    s.addToPrintList(
        name,
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After ClassificationModule.pixelWise:{name} NO tissue "
            f"remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After ClassificationModule.pixelWise:{name} NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")

    return
コード例 #11
0
def getIntensityThresholdPercent(s, params):
    name = params.get("name", "classTask")
    logging.info(
        f"{s['filename']} - \tLightDarkModule.getIntensityThresholdPercent:\t {name}"
    )

    lower_thresh = float(params.get("lower_threshold", -float("inf")))
    upper_thresh = float(params.get("upper_threshold", float("inf")))

    lower_var = float(params.get("lower_variance", -float("inf")))
    upper_var = float(params.get("upper_variance", float("inf")))

    img = s.getImgThumb(s["image_work_size"])
    img_var = img.std(axis=2)

    map_var = np.bitwise_and(img_var > lower_var, img_var < upper_var)

    img = color.rgb2gray(img)
    map = np.bitwise_and(img > lower_thresh, img < upper_thresh)

    map = np.bitwise_and(map, map_var)

    s["img_mask_" + name] = map > 0

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_" + name + ".png",
              s["img_mask_" + name] * 255)

    if strtobool(params.get("invert", "False")):
        s["img_mask_" + name] = ~s["img_mask_" + name]

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & s["img_mask_" + name]

    s.addToPrintList(
        name,
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After LightDarkModule.getIntensityThresholdPercent:{name} NO tissue "
            f"remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After LightDarkModule.getIntensityThresholdPercent:{name} NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")

    return
コード例 #12
0
ファイル: LightDarkModule.py プロジェクト: Pacific89/HistoQC
def getIntensityThresholdOtsu(s, params):
    logging.info(
        f"{s['filename']} - \tLightDarkModule.getIntensityThresholdOtsu")
    name = "otsu"

    local = strtobool(params.get("local", "False"))

    radius = float(params.get("radius", 15))
    selem = disk(radius)

    img = s.getImgThumb(s["image_work_size"])

    img = color.rgb2gray(img)

    if local:
        thresh = rank.otsu(img, selem)
        name += "local"
    else:
        thresh = threshold_otsu(img)

    map = img < thresh

    s["img_mask_" + name] = map > 0
    if strtobool(params.get("invert", "False")):
        s["img_mask_" + name] = ~s["img_mask_" + name]

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_" + name + ".png",
              img_as_ubyte(s["img_mask_" + name]))

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & s["img_mask_" + name]

    s.addToPrintList(
        name,
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After LightDarkModule.getIntensityThresholdOtsu:{name} NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")
        s["warnings"].append(
            f"After LightDarkModule.getIntensityThresholdOtsu:{name} NO tissue remains detectable! "
            f"Downstream modules likely to be incorrect/fail")

    return
コード例 #13
0
ファイル: MorphologyModule.py プロジェクト: NKI-AI/HistoQC
def removeSmallObjects(s, params):
    logging.info(f"{s['filename']} - \tremoveSmallObjects")
    min_size = int(params.get("min_size", 64))
    img_reduced = morphology.remove_small_objects(s["img_mask_use"],
                                                  min_size=min_size)
    img_small = np.invert(img_reduced) & s["img_mask_use"]

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_small_remove.png",
              img_as_ubyte(img_small))
    s["img_mask_small_filled"] = (img_small * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = img_reduced

    rps = measure.regionprops(morphology.label(img_small))
    if rps:
        areas = np.asarray([rp.area for rp in rps])
        nobj = len(rps)
        area_max = areas.max()
        area_mean = areas.mean()
    else:
        nobj = area_max = area_mean = 0

    s.addToPrintList("small_tissue_removed_num_regions", str(nobj))
    s.addToPrintList("small_tissue_removed_mean_area", str(area_mean))
    s.addToPrintList("small_tissue_removed_max_area", str(area_max))

    s.addToPrintList(
        "small_tissue_removed_percent",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After MorphologyModule.removeSmallObjects: NO tissue "
            f"remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After MorphologyModule.removeSmallObjects: NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")

    return
コード例 #14
0
ファイル: AnnotationModule.py プロジェクト: sbalci/HistoQC
def geoJSONMask(s, params):
    logging.info(f"{s['filename']} - \tgeoJSONMask")
    mask = s["img_mask_use"]

    geojson_basepath = params.get("geojson_filepath", None)
    geojson_suffix = params.get("geojson_suffix", "")
    if not geojson_basepath:
        geojson_basepath = s["dir"]

    fname = geojson_basepath + os.sep + PurePosixPath(
        s['filename']).stem + geojson_suffix + '.json'
    if not Path(fname).is_file():
        msg = f"Annotation file {fname} does not exist. Skipping."
        logging.warning(f"{s['filename']} - {msg}")
        s["warnings"].append(msg)
        return

    logging.info(f"{s['filename']} - \tusing {fname}")

    point_sets = get_points_from_geojson(s, fname)
    annotationMask = mask_out_annotation(s, point_sets) > 0
    io.imsave(s["outdir"] + os.sep + s["filename"] + "_geoJSONMask.png",
              img_as_ubyte(annotationMask))

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = prev_mask & annotationMask

    s.addToPrintList(
        "geoJSONMask",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After AnnotationModule.geoJSONMask NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After AnnotationModule.geoJSONMask NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )

    return
コード例 #15
0
def fillSmallHoles(s, params):
    logging.info(f"{s['filename']} - \tfillSmallHoles")
    min_size = int(params.get("min_size", 64))
    img_reduced = morphology.remove_small_holes(s["img_mask_use"],
                                                min_size=min_size)
    img_small = img_reduced & np.invert(s["img_mask_use"])

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_small_fill.png",
              img_small * 255)
    s["img_mask_small_removed"] = (img_small * 255) > 0

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = img_reduced

    s.addToPrintList(
        "percent_small_tissue_filled",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    return
コード例 #16
0
def pixelWise(s, params):
    name = params.get("name", "classTask")
    logging.info(f"{s['filename']} - \tpixelWise:\t", name)

    thresh = float(params.get("threshold", .5))

    fname = params.get("tsv_file", "")
    if fname == "":
        logging.error(
            f"{s['filename']} - tsv_file not set in ClassificationModule.pixelWise for ",
            name)
        sys.exit(1)
        return
    model_vals = np.loadtxt(fname, delimiter="\t", skiprows=1)

    img = s.getImgThumb(s["image_work_size"])

    gnb = GaussianNB()
    gnb.fit(model_vals[:, 1:], model_vals[:, 0])
    cal = gnb.predict_proba(img.reshape(-1, 3))

    cal = cal.reshape(img.shape[0], img.shape[1], 2)
    mask = cal[:, :, 1] > thresh

    mask = s["img_mask_use"] & (mask > 0)

    s.addToPrintList(name, str(mask.mean()))

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_" + name + ".png",
              mask * 255)
    s["img_mask_" + name] = (mask * 255) > 0
    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_" + name]

    s.addToPrintList(
        name,
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    return
コード例 #17
0
ファイル: GridDetectionModule.py プロジェクト: CielAl/HistoQC
def grid_detect(s: BaseImage, params):
    logging.debug(params)
    method_name: str = params.get('name', 'Radon').lower()
    # streak_perc_thresh = params.get('streak_prec_thresh')
    class_grid_detect: Type[AbstractGrid] = method_map[method_name]
    img = s.getImgThumb(params.get("image_work_size", "1.25x"))
    detector: AbstractGrid = class_grid_detect(img)
    # todo detector(params)
    # todo
    img, bg, mask = detector(params)
    cv2.imwrite(s["outdir"] + os.sep + s["filename"] + "_grid_mask.png",
                mask * 255)
    cv2.imwrite(s["outdir"] + os.sep + s["filename"] + "_grid_bg.png", bg)
    s["img_mask_grid"] = (mask * 255) > 0
    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_grid"]
    s.addToPrintList(
        'percent_grid',
        printMaskHelper(type=params.get("mask_statistics",
                                        s["mask_statistics"]),
                        prev_mask=prev_mask,
                        curr_mask=s["img_mask_use"]))
コード例 #18
0
ファイル: LightDarkModule.py プロジェクト: NKI-AI/HistoQC
def removeBrightestPixels(s, params):
    logging.info(f"{s['filename']} - \tLightDarkModule.removeBrightestPixels")

    # lower_thresh = float(params.get("lower_threshold", -float("inf")))
    # upper_thresh = float(params.get("upper_threshold", float("inf")))
    #
    # lower_var = float(params.get("lower_variance", -float("inf")))
    # upper_var = float(params.get("upper_variance", float("inf")))

    img = s.getImgThumb(s["image_work_size"])
    img = color.rgb2gray(img)

    kmeans = KMeans(n_clusters=3,  n_init=1).fit(img.reshape([-1, 1]))
    brightest_cluster = np.argmax(kmeans.cluster_centers_)
    darkest_point_in_brightest_cluster = (img.reshape([-1, 1])[kmeans.labels_ == brightest_cluster]).min()

    s["img_mask_bright"] = img > darkest_point_in_brightest_cluster



    if strtobool(params.get("invert", "False")):
        s["img_mask_bright"] = ~s["img_mask_bright"]

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & s["img_mask_bright"]

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_bright.png", img_as_ubyte(prev_mask & ~s["img_mask_bright"]))

    s.addToPrintList("brightestPixels",
                     printMaskHelper(params.get("mask_statistics", s["mask_statistics"]), prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()[0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(f"{s['filename']} - After LightDarkModule.removeBrightestPixels NO tissue "
                        f"remains detectable! Downstream modules likely to be incorrect/fail")
        s["warnings"].append(f"After LightDarkModule.removeBrightestPixels NO tissue remains "
                             f"detectable! Downstream modules likely to be incorrect/fail")

    return
コード例 #19
0
ファイル: AnnotationModule.py プロジェクト: pjl54/HistoQC
def xmlMask(s, params):
    logging.info(f"{s['filename']} - \txmlMask")
    mask = s["img_mask_use"]

    xml_basepath = params.get("xml_filepath", None)
    xml_suffix = params.get("xml_suffix", "")
    if not xml_basepath:
        xml_basepath = s["dir"]

    xml_fname = xml_basepath + os.sep + PurePosixPath(
        s['filename']).stem + xml_suffix + '.xml'

    logging.info(f"{s['filename']} - \tusing {xml_fname}")

    annotationMask = mask_out_annotation(s, xml_fname) > 0
    io.imsave(s["outdir"] + os.sep + s["filename"] + "_xmlMask.png",
              img_as_ubyte(annotationMask))

    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = prev_mask & annotationMask

    s.addToPrintList(
        "xmlMask",
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After AnnotationModule.xmlMask NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After AnnotationModule.xmlMask NO tissue remains detectable! Downstream modules likely to be incorrect/fail"
        )

    return
コード例 #20
0
def byExampleWithFeatures(s, params):
    name = params.get("name", "classTask")
    logging.info(
        f"{s['filename']} - \tClassificationModule.byExample:\t{name}")

    thresh = float(params.get("threshold", .5))

    examples = params.get("examples", "")
    if examples == "":
        logging.error(
            f"{s['filename']} - No examples provided in ClassificationModule.byExample for {name} !!"
        )
        sys.exit(1)
        return

    if params.get("features", "") == "":
        logging.error(
            f"{s['filename']} - No features provided in ClassificationModule.byExample for {name} !!"
        )
        sys.exit(1)
        return

    with params[
            "lock"]:  # this lock is shared across all threads such that only one thread needs to train the model
        # then it is shared with all other modules
        if not params["shared_dict"].get("model_" + name, False):
            logging.info(
                f"{s['filename']} - Training model ClassificationModule.byExample:{name}"
            )

            model_vals = []
            model_labels = np.empty([0, 1])

            for ex in params["examples"].splitlines():
                ex = ex.split(":")
                img = io.imread(ex[0])
                eximg = compute_features(img, params)
                eximg = eximg.reshape(-1, eximg.shape[2])
                model_vals.append(eximg)

                mask = io.imread(ex[1], as_gray=True).reshape(-1, 1)
                model_labels = np.vstack((model_labels, mask))

            # do stuff here with model_vals
            model_vals = np.vstack(model_vals)
            clf = RandomForestClassifier(n_jobs=-1)
            clf.fit(model_vals, model_labels.ravel())
            params["shared_dict"]["model_" + name] = clf
            logging.info(
                f"{s['filename']} - Training model ClassificationModule.byExample:{name}....done"
            )

    clf = params["shared_dict"]["model_" + name]
    img = s.getImgThumb(s["image_work_size"])
    feats = compute_features(img, params)
    cal = clf.predict_proba(feats.reshape(-1, feats.shape[2]))
    cal = cal.reshape(img.shape[0], img.shape[1], 2)

    mask = cal[:, :, 1] > thresh

    area_thresh = int(params.get("area_threshold", "5"))
    if area_thresh > 0:
        mask = remove_small_objects(mask, min_size=area_thresh, in_place=True)

    dilate_kernel_size = int(params.get("dilate_kernel_size", "0"))
    if dilate_kernel_size > 0:
        mask = dilation(mask,
                        selem=np.ones(
                            (dilate_kernel_size, dilate_kernel_size)))

    mask = s["img_mask_use"] & (mask > 0)

    io.imsave(s["outdir"] + os.sep + s["filename"] + "_" + name + ".png",
              img_as_ubyte(mask))
    s["img_mask_" + name] = (mask * 255) > 0
    prev_mask = s["img_mask_use"]
    s["img_mask_use"] = s["img_mask_use"] & ~s["img_mask_" + name]

    s.addToPrintList(
        name,
        printMaskHelper(params.get("mask_statistics", s["mask_statistics"]),
                        prev_mask, s["img_mask_use"]))

    if len(s["img_mask_use"].nonzero()
           [0]) == 0:  # add warning in case the final tissue is empty
        logging.warning(
            f"{s['filename']} - After ClassificationModule.byExampleWithFeatures:{name} NO tissue "
            f"remains detectable! Downstream modules likely to be incorrect/fail"
        )
        s["warnings"].append(
            f"After ClassificationModule.byExampleWithFeatures:{name} NO tissue remains "
            f"detectable! Downstream modules likely to be incorrect/fail")

    s["img_mask_force"].append("img_mask_" + name)
    s["completed"].append(f"byExampleWithFeatures:{name}")

    return