Skip to content

blur_score_piqe

Creates per-pixel and per-image coverage mask of the blur score based on the PIQE algorithm.

Parameters:

Name Type Description Default
img RGBImage

RGB Image of the tissue, minimum size 10x10 pixels.

required
pixel_size float

Size of a pixel in micrometers. The score is most accurate at pixel sizes around 0.44 micrometers.

0.44
foreground_mask BinaryMask | None

Binary mask of the tissue, where 1 represents tissue and 0 represents background. If not provided, foreground mask is computed by simple_foreground_mask function. foreground_mask is used to nullify blur detections in the background. The standard tissue mask has proven to be too coarse for this use, especially for tiles with little or no background.

None

Returns:

Type Description
BlurScore

Dictionary with the per-pixel and coverage mask blur_score_per_pixel - binary mask composed of 16x16 px blocks marking blurred areas. blur_score_coverage - coverage mask of the per_pixel detections. Coverage ranges from 0.0 to 1.0.

Note

The returned dictionary contains the following values:

Key Description
blur_score_per_pixel Binary mask of the blur score.
blur_score_coverage Coverage mask of the blur score.

Examples:

from skimage.data import immunohistochemistry

from rationai.qc.blur import blur_score_piqe

img = immunohistochemistry()
pixel_size = 0.44  # pixel size of img in micrometers

result = blur_score_piqe(img, pixel_size)

# Mask of the blur coverage range from 0.0 to 1.0
coverage_mask = result["blur_score_coverage"]

# Binary mask of the blur detections
blur_score_per_pixel = result["blur_score_per_pixel"]

Source code in rationai/qc/blur/blur_score_piqe.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def blur_score_piqe(
    img: RGBImage,
    pixel_size: float = 0.44,
    foreground_mask: BinaryMask | None = None,
) -> BlurScore:
    """Creates per-pixel and per-image coverage mask of the blur score based on the PIQE algorithm.

    Args:
        img: RGB Image of the tissue, minimum size 10x10 pixels.
        pixel_size: Size of a pixel in micrometers. The score is most accurate
            at pixel sizes around 0.44 micrometers.
        foreground_mask: Binary mask of the tissue, where 1 represents tissue and 0 represents background.
            If not provided, foreground mask is computed by `simple_foreground_mask` function.
            foreground_mask is used to nullify blur detections in the background.
            The standard tissue mask has proven to be too coarse for this use, especially
            for tiles with little or no background.

    Returns:
        Dictionary with the per-pixel and coverage mask
            blur_score_per_pixel - binary mask composed of 16x16 px blocks marking blurred areas.
            blur_score_coverage - coverage mask of the per_pixel detections. Coverage ranges from 0.0 to 1.0.


    Note:
        The returned dictionary contains the following values:

        | Key                   | Description                     |
        |-----------------------|---------------------------------|
        | `blur_score_per_pixel`| Binary mask of the blur score.  |
        | `blur_score_coverage` | Coverage mask of the blur score.|

    Examples:
    ```python
    from skimage.data import immunohistochemistry

    from rationai.qc.blur import blur_score_piqe

    img = immunohistochemistry()
    pixel_size = 0.44  # pixel size of img in micrometers

    result = blur_score_piqe(img, pixel_size)

    # Mask of the blur coverage range from 0.0 to 1.0
    coverage_mask = result["blur_score_coverage"]

    # Binary mask of the blur detections
    blur_score_per_pixel = result["blur_score_per_pixel"]
    ```

    """
    # Used for calculating the kernel size
    # for the median filter based on the pixel size
    optimal_pixel_size = 0.44

    kernel_size = 2 * round(1 / pixel_size * optimal_pixel_size + 1e-9) + 1
    grayscale_img = median(
        rgb2gray(img), footprint=np.ones((kernel_size, kernel_size), dtype=bool)
    )
    (
        _,  # Piqe score (not relevant for our purposes)
        _,  # Noticeable artifacts mask
        _,  # Noise mask
        activity_mask,
    ) = piqe(
        grayscale_img * 255
    )  # grayscale_img is pixel array with values between 0 and 1, piqe expects values between 0 and 255

    # Activity mask is one column shorter for images
    # with dimensions that are not divisible by 16
    if grayscale_img.shape != activity_mask.shape:
        activity_mask = np.pad(activity_mask, ((0, 0), (0, 1)), mode="edge")

    if foreground_mask is None:
        foreground_mask = simple_foreground_mask(grayscale_img)

    # activity_mask is inverted, blurred areas and empty areas (background) are set to 1
    activity_mask = ~(activity_mask > 0)
    # activity_mask is multiplied by the foreground mask to nullify background pixels
    activity_mask = activity_mask * foreground_mask

    return {
        "blur_score_per_pixel": activity_mask > 0,
        "blur_score_coverage": get_coverage_mask(
            grayscale_img, activity_mask, foreground_mask
        ),
    }