Parametric maps#

For data visualization, parametric maps or feature images, can be useful. This notebook demonstrates how parametric maps can be made. In such parametric images, pixel intensity corresponds to measurements of the objects, for example area.

import numpy as np
import pyclesperanto_prototype as cle
from skimage.io import imread
from skimage.measure import regionprops, regionprops_table
from skimage.util import map_array
from napari_segment_blobs_and_things_with_membranes import voronoi_otsu_labeling

Starting point for drawing parametric maps is always a label image.

image = imread("../../data/BBBC007_batch/17P1_POS0013_D_1UL.tif")
labels = voronoi_otsu_labeling(image)
labels
nsbatwm made image
shape(340, 340)
dtypeint32
size451.6 kB
min0
max46

Parametric maps using scikit-image#

You can now compute your own measurement for each object and then visualize it in a parametric map image, for example using scikit-image’s regionprops() for computing the measurements.

statistics_table = regionprops_table(cle.pull(labels), properties=('label', 'area',))

Area map#

area_map = map_array(
        cle.pull(labels),
        statistics_table['label'],
        statistics_table['area'],
        )

cle.imshow(area_map, colorbar=True, color_map="jet")
C:\Users\rober\miniconda3\envs\devbio-napari-env4\lib\site-packages\pyclesperanto_prototype\_tier9\_imshow.py:46: UserWarning: The imshow parameter color_map is deprecated. Use colormap instead.
  warnings.warn("The imshow parameter color_map is deprecated. Use colormap instead.")
../_images/04_parametric_maps_7_1.png

Parametric maps in pyclesperanto#

Simpler access, also to more advanced methods for generating parametric maps are available in pyclesperanto. It comes with some maps built-in. For example the pixel count map which is identical to the above shown area map in case the pixel size is 1.

pixel_count_map = cle.pixel_count_map(labels)

cle.imshow(pixel_count_map, color_map='jet', colorbar=True)
C:\Users\rober\miniconda3\envs\devbio-napari-env4\lib\site-packages\pyclesperanto_prototype\_tier9\_imshow.py:46: UserWarning: The imshow parameter color_map is deprecated. Use colormap instead.
  warnings.warn("The imshow parameter color_map is deprecated. Use colormap instead.")
../_images/04_parametric_maps_10_1.png

Advanced methods for studying cells in tissues allow for counting for example the number of neighboring cells in a given radius.

neighbor_count_map = cle.proximal_neighbor_count_map(labels, max_distance=50)

cle.imshow(neighbor_count_map, color_map='jet', colorbar=True)
../_images/04_parametric_maps_12_0.png

Visualization in napari#

To visualize the parametric images on top of the original image, using napari is recommended.

import napari

viewer = napari.Viewer()

viewer.add_image(image)
area_map_layer = viewer.add_image(area_map, opacity=0.2, blending="additive", colormap="turbo")

napari.utils.nbscreenshot(viewer)
area_map_layer.opacity = 0.9

napari.utils.nbscreenshot(viewer)

Exercise#

Modify the code above to measure the major_axis_length of the objects and visualize the measurements in color in napari. The documentation of regionprops might be useful:

regionprops?
Signature:
regionprops(
    label_image,
    intensity_image=None,
    cache=True,
    coordinates=None,
    *,
    extra_properties=None,
)
Docstring:
Measure properties of labeled image regions.

Parameters
----------
label_image : (M, N[, P]) ndarray
    Labeled input image. Labels with value 0 are ignored.

    .. versionchanged:: 0.14.1
        Previously, ``label_image`` was processed by ``numpy.squeeze`` and
        so any number of singleton dimensions was allowed. This resulted in
        inconsistent handling of images with singleton dimensions. To
        recover the old behaviour, use
        ``regionprops(np.squeeze(label_image), ...)``.
intensity_image : (M, N[, P][, C]) ndarray, optional
    Intensity (i.e., input) image with same size as labeled image, plus
    optionally an extra dimension for multichannel data. Currently,
    this extra channel dimension, if present, must be the last axis.
    Default is None.

    .. versionchanged:: 0.18.0
        The ability to provide an extra dimension for channels was added.
cache : bool, optional
    Determine whether to cache calculated properties. The computation is
    much faster for cached properties, whereas the memory consumption
    increases.
coordinates : DEPRECATED
    This argument is deprecated and will be removed in a future version
    of scikit-image.

    See :ref:`Coordinate conventions <numpy-images-coordinate-conventions>`
    for more details.

    .. deprecated:: 0.16.0
        Use "rc" coordinates everywhere. It may be sufficient to call
        ``numpy.transpose`` on your label image to get the same values as
        0.15 and earlier. However, for some properties, the transformation
        will be less trivial. For example, the new orientation is
        :math:`\frac{\pi}{2}` plus the old orientation.
extra_properties : Iterable of callables
    Add extra property computation functions that are not included with
    skimage. The name of the property is derived from the function name,
    the dtype is inferred by calling the function on a small sample.
    If the name of an extra property clashes with the name of an existing
    property the extra property wil not be visible and a UserWarning is
    issued. A property computation function must take a region mask as its
    first argument. If the property requires an intensity image, it must
    accept the intensity image as the second argument.

Returns
-------
properties : list of RegionProperties
    Each item describes one labeled region, and can be accessed using the
    attributes listed below.

Notes
-----
The following properties can be accessed as attributes or keys:

**area** : int
    Number of pixels of the region.
**area_bbox** : int
    Number of pixels of bounding box.
**area_convex** : int
    Number of pixels of convex hull image, which is the smallest convex
    polygon that encloses the region.
**area_filled** : int
    Number of pixels of the region will all the holes filled in. Describes
    the area of the image_filled.
**axis_major_length** : float
    The length of the major axis of the ellipse that has the same
    normalized second central moments as the region.
**axis_minor_length** : float
    The length of the minor axis of the ellipse that has the same
    normalized second central moments as the region.
**bbox** : tuple
    Bounding box ``(min_row, min_col, max_row, max_col)``.
    Pixels belonging to the bounding box are in the half-open interval
    ``[min_row; max_row)`` and ``[min_col; max_col)``.
**centroid** : array
    Centroid coordinate tuple ``(row, col)``.
**centroid_local** : array
    Centroid coordinate tuple ``(row, col)``, relative to region bounding
    box.
**centroid_weighted** : array
    Centroid coordinate tuple ``(row, col)`` weighted with intensity
    image.
**centroid_weighted_local** : array
    Centroid coordinate tuple ``(row, col)``, relative to region bounding
    box, weighted with intensity image.
**coords** : (N, 2) ndarray
    Coordinate list ``(row, col)`` of the region.
**eccentricity** : float
    Eccentricity of the ellipse that has the same second-moments as the
    region. The eccentricity is the ratio of the focal distance
    (distance between focal points) over the major axis length.
    The value is in the interval [0, 1).
    When it is 0, the ellipse becomes a circle.
**equivalent_diameter_area** : float
    The diameter of a circle with the same area as the region.
**euler_number** : int
    Euler characteristic of the set of non-zero pixels.
    Computed as number of connected components subtracted by number of
    holes (input.ndim connectivity). In 3D, number of connected
    components plus number of holes subtracted by number of tunnels.
**extent** : float
    Ratio of pixels in the region to pixels in the total bounding box.
    Computed as ``area / (rows * cols)``
**feret_diameter_max** : float
    Maximum Feret's diameter computed as the longest distance between
    points around a region's convex hull contour as determined by
    ``find_contours``. [5]_
**image** : (H, J) ndarray
    Sliced binary region image which has the same size as bounding box.
**image_convex** : (H, J) ndarray
    Binary convex hull image which has the same size as bounding box.
**image_filled** : (H, J) ndarray
    Binary region image with filled holes which has the same size as
    bounding box.
**image_intensity** : ndarray
    Image inside region bounding box.
**inertia_tensor** : ndarray
    Inertia tensor of the region for the rotation around its mass.
**inertia_tensor_eigvals** : tuple
    The eigenvalues of the inertia tensor in decreasing order.
**intensity_max** : float
    Value with the greatest intensity in the region.
**intensity_mean** : float
    Value with the mean intensity in the region.
**intensity_min** : float
    Value with the least intensity in the region.
**label** : int
    The label in the labeled input image.
**moments** : (3, 3) ndarray
    Spatial moments up to 3rd order::

        m_ij = sum{ array(row, col) * row^i * col^j }

    where the sum is over the `row`, `col` coordinates of the region.
**moments_central** : (3, 3) ndarray
    Central moments (translation invariant) up to 3rd order::

        mu_ij = sum{ array(row, col) * (row - row_c)^i * (col - col_c)^j }

    where the sum is over the `row`, `col` coordinates of the region,
    and `row_c` and `col_c` are the coordinates of the region's centroid.
**moments_hu** : tuple
    Hu moments (translation, scale and rotation invariant).
**moments_normalized** : (3, 3) ndarray
    Normalized moments (translation and scale invariant) up to 3rd order::

        nu_ij = mu_ij / m_00^[(i+j)/2 + 1]

    where `m_00` is the zeroth spatial moment.
**moments_weighted** : (3, 3) ndarray
    Spatial moments of intensity image up to 3rd order::

        wm_ij = sum{ array(row, col) * row^i * col^j }

    where the sum is over the `row`, `col` coordinates of the region.
**moments_weighted_central** : (3, 3) ndarray
    Central moments (translation invariant) of intensity image up to
    3rd order::

        wmu_ij = sum{ array(row, col) * (row - row_c)^i * (col - col_c)^j }

    where the sum is over the `row`, `col` coordinates of the region,
    and `row_c` and `col_c` are the coordinates of the region's weighted
    centroid.
**moments_weighted_hu** : tuple
    Hu moments (translation, scale and rotation invariant) of intensity
    image.
**moments_weighted_normalized** : (3, 3) ndarray
    Normalized moments (translation and scale invariant) of intensity
    image up to 3rd order::

        wnu_ij = wmu_ij / wm_00^[(i+j)/2 + 1]

    where ``wm_00`` is the zeroth spatial moment (intensity-weighted area).
**orientation** : float
    Angle between the 0th axis (rows) and the major
    axis of the ellipse that has the same second moments as the region,
    ranging from `-pi/2` to `pi/2` counter-clockwise.
**perimeter** : float
    Perimeter of object which approximates the contour as a line
    through the centers of border pixels using a 4-connectivity.
**perimeter_crofton** : float
    Perimeter of object approximated by the Crofton formula in 4
    directions.
**slice** : tuple of slices
    A slice to extract the object from the source image.
**solidity** : float
    Ratio of pixels in the region to pixels of the convex hull image.

Each region also supports iteration, so that you can do::

  for prop in region:
      print(prop, region[prop])

See Also
--------
label

References
----------
.. [1] Wilhelm Burger, Mark Burge. Principles of Digital Image Processing:
       Core Algorithms. Springer-Verlag, London, 2009.
.. [2] B. Jähne. Digital Image Processing. Springer-Verlag,
       Berlin-Heidelberg, 6. edition, 2005.
.. [3] T. H. Reiss. Recognizing Planar Objects Using Invariant Image
       Features, from Lecture notes in computer science, p. 676. Springer,
       Berlin, 1993.
.. [4] https://en.wikipedia.org/wiki/Image_moment
.. [5] W. Pabst, E. Gregorová. Characterization of particles and particle
       systems, pp. 27-28. ICT Prague, 2007.
       https://old.vscht.cz/sil/keramika/Characterization_of_particles/CPPS%20_English%20version_.pdf

Examples
--------
>>> from skimage import data, util
>>> from skimage.measure import label, regionprops
>>> img = util.img_as_ubyte(data.coins()) > 110
>>> label_img = label(img, connectivity=img.ndim)
>>> props = regionprops(label_img)
>>> # centroid of first labeled object
>>> props[0].centroid
(22.72987986048314, 81.91228523446583)
>>> # centroid of first labeled object
>>> props[0]['centroid']
(22.72987986048314, 81.91228523446583)

Add custom measurements by passing functions as ``extra_properties``

>>> from skimage import data, util
>>> from skimage.measure import label, regionprops
>>> import numpy as np
>>> img = util.img_as_ubyte(data.coins()) > 110
>>> label_img = label(img, connectivity=img.ndim)
>>> def pixelcount(regionmask):
...     return np.sum(regionmask)
>>> props = regionprops(label_img, extra_properties=(pixelcount,))
>>> props[0].pixelcount
7741
>>> props[1]['pixelcount']
42
File:      c:\users\rober\miniconda3\envs\devbio-napari-env4\lib\site-packages\skimage\measure\_regionprops.py
Type:      function