computationalpathologygroup / ASAP

Program for the analysis and visualization of whole-slide images in digital pathology
https://computationalpathologygroup.github.io/ASAP/
GNU General Public License v2.0
607 stars 163 forks source link

Annotation mask generated is incorrect when compared to xml annotation. #128

Closed euwern closed 5 years ago

euwern commented 5 years ago

I am facing some problem with the annotation of CAMELYON16 test data. I use the code provided to generate annotation mask but when I try to count the number of tumors inside the mask, it returns only 1 or 0. which is wrong as the xml file has more than 1 tumor. For example: test_030.xml has 76 tumors annotation but the generated mask tif file returns 1 tumor. I provided a sample of my code to recreate the problem.

Can someone help me to identify the problem?

convert xml to tif

import multiresolutionimageinterface as mir
reader = mir.MultiResolutionImageReader()
mr_image = reader.open('/mnt/datasets/camelyon16/testing/images/test_030.tif')
annotation_list = mir.AnnotationList()
xml_repository = mir.XmlRepository(annotation_list)
xml_repository.setSource('/mnt/datasets/camelyon16/testing/anno/test_030.xml')
xml_repository.load()
annotation_mask = mir.AnnotationToMask()
camelyon17_type_mask = False
label_map = {'metastases': 1, 'normal': 2} if camelyon17_type_mask else {'_0': 1, '_1': 1, '_2': 0}
conversion_order = ['metastases', 'normal'] if camelyon17_type_mask else  ['_0', '_1', '_2']
output_path = '/mnt/datasets/camelyon16/testing/masks/test_030_mask.tif'
annotation_mask.convert(annotation_list, output_path, mr_image.getDimensions(), mr_image.getSpacing(), label_map, conversion_order)

evaluation mask

#note: code obtained from evaluation script
def computeEvaluationMask(maskDIR, resolution, level):
    """Computes the evaluation mask.

    Args:
        maskDIR:    the directory of the ground truth mask
        resolution: Pixel resolution of the image at level 0
        level:      The level at which the evaluation mask is made

    Returns:
        evaluation_mask
    """
    slide = openslide.open_slide(maskDIR)
    dims = slide.level_dimensions[level]
    pixelarray = np.zeros(dims[0]*dims[1], dtype='uint')
    pixelarray = np.array(slide.read_region((0,0), level, dims))
    distance = nd.distance_transform_edt(255 - pixelarray[:,:,0])
    Threshold = 75/(resolution * pow(2, level) * 2) # 75µm is the equivalent size of 5 tumor cells
    binary = distance < Threshold
    filled_image = nd.morphology.binary_fill_holes(binary)
    evaluation_mask = measure.label(filled_image, connectivity = 2) 
    return evaluation_mask

mask_path = '/mnt/datasets/camelyon16/testing/masks/test_030_mask.tif'
EVALUATION_MASK_LEVEL = 5 # Image level at which the evaluation is done
L0_RESOLUTION = 0.243 # pixel resolution at level 0
eval_mask = computeEvaluationMask(mask_path, L0_RESOLUTION, EVALUATION_MASK_LEVEL)
print(np.amax(eval_mask))
GeertLitjens commented 5 years ago

Hi, it is better to ask these CAMELYON specific questions in the CAMELYON forum. Could you post an image of the tif you obtain via the conversion of the XML? You can either open the mask image in ASAP or use matplotlib and imshow to show a low-resolution version. Note that the TIFF file will be binary (e.g. the max value will be 1, not every tumor annotation will get a separate label).

euwern commented 5 years ago

Hi @GeertLitjens I apologize for posting CAMELYON specific question in ASAP github. Thanks for mentioning. I think there is something wrong with the function provided by the evaluation script (I.e. the threshold and binary hole filling are messing with the tiff masks).

As suggested, I generated a preview of the tiff mask and it looks correct. This shows that there is nothing wrong with ASAP. (attached image).

Thanks for your debugging tips.

tumor masks for test_030

christinesu12 commented 4 years ago

i have the same question with you,do you have the solution to this problem?

Reasat commented 3 years ago

Where is the Camelyon forum?