Blob detection#

A common procedure for local maxima detection on processed images is called Blob detection. It is typically applied to Difference-of-Gaussian (DoG), Laplacian-of-Gaussian (LoG) and Determinant-of-Hessian (DoH) images. We will use scikit-image functions for that. The advantage of these methods is that no pre-processing is necessary, it is built-in.

See also

from skimage.feature import blob_dog, blob_log, blob_doh

import pyclesperanto_prototype as cle
from skimage.io import imread, imshow
from skimage.filters import gaussian 
import matplotlib.pyplot as plt

We start by loading an image and cropping a region for demonstration purposes. We used image set BBBC007v1 image set version 1 (Jones et al., Proc. ICCV Workshop on Computer Vision for Biomedical Image Applications, 2005), available from the Broad Bioimage Benchmark Collection [Ljosa et al., Nature Methods, 2012].

image = imread("../../data/BBBC007_batch/A9 p7d.tif")[-100:, 0:100]

cle.imshow(image)
../_images/8641a082f73416921fa012245d92e7dcb078bcb651b843865b416a1a714e51e0.png

For technial reasons it is important to convert the pixel type of this image first (see this discussion) and this github issue.

image = image.astype(float)

Difference-of-Gaussian (DoG)#

The DoG technique consists of two Gaussian-blur operations applied to an image. The resulting images are subtracted from each other resulting in an image where objects smaller and larger than a defined size or sigma range are removed. In this image, local maxima are detected. Read more in the documentation of blob_dog.

coordinates_dog = blob_dog(image, min_sigma=1, max_sigma=10, threshold=1)
coordinates_dog
array([[10.    , 30.    ,  4.096 ],
       [24.    , 85.    ,  4.096 ],
       [42.    , 39.    ,  4.096 ],
       [11.    ,  0.    ,  4.096 ],
       [87.    , 35.    ,  4.096 ],
       [71.    , 85.    ,  4.096 ],
       [32.    , 71.    ,  4.096 ],
       [46.    ,  0.    ,  1.    ],
       [ 9.    , 58.    ,  4.096 ],
       [78.    , 18.    ,  6.5536],
       [81.    , 85.    ,  1.6   ],
       [99.    , 90.    ,  2.56  ],
       [ 0.    , 99.    ,  6.5536],
       [51.    , 41.    ,  1.6   ],
       [52.    ,  0.    ,  1.    ],
       [16.    , 99.    ,  1.6   ],
       [99.    , 81.    ,  1.6   ],
       [41.    , 27.    ,  1.    ],
       [34.    , 37.    ,  1.    ],
       [16.    ,  8.    ,  1.    ],
       [46.    , 25.    ,  1.    ],
       [99.    , 49.    ,  1.    ],
       [99.    , 45.    ,  1.    ]])
coordinates_dog.shape
(23, 3)

This array contains coordinates in x and y and the sigma corresponding to the maximum. We can extract the list of coordinates and visualize it.

cle.imshow(image, continue_drawing=True)
plt.plot(coordinates_dog[:, 1], coordinates_dog[:, 0], 'r.')
[<matplotlib.lines.Line2D at 0x1a509079a00>]
../_images/04dbb052939cd5cad2686af6662a69b07d8e48238b0791180c5e83c66d6f3d51.png

Laplacian-of-Gaussian (LoG)#

The LoG technique is a Laplacian kernel applied to a Gaussian blurred image. In the resulting image, objects with a given size can be detected more easily because noise has been remove and edges enhanced.

coordinates_log = blob_log(image, min_sigma=1, max_sigma=10, num_sigma=10, threshold=1)
coordinates_log
array([[10., 30.,  5.],
       [23., 85.,  4.],
       [43., 38.,  6.],
       [11.,  0.,  6.],
       [71., 85.,  6.],
       [87., 35.,  5.],
       [ 9., 58.,  5.],
       [46.,  0.,  1.],
       [77., 17.,  7.],
       [81., 85.,  2.],
       [99., 90.,  3.],
       [ 0., 99.,  8.],
       [51., 41.,  2.],
       [52.,  0.,  1.],
       [16., 99.,  3.],
       [87., 19.,  2.],
       [99., 81.,  2.],
       [41., 27.,  1.],
       [34., 36.,  1.],
       [56., 38.,  1.],
       [17.,  8.,  1.],
       [46., 25.,  1.],
       [35., 44.,  1.],
       [56., 33.,  1.],
       [62., 83.,  1.],
       [99., 49.,  2.],
       [99., 45.,  1.],
       [82., 95.,  1.],
       [99., 42.,  1.]])
cle.imshow(image, continue_drawing=True)
plt.plot(coordinates_log[:, 1], coordinates_log[:, 0], 'r.')
[<matplotlib.lines.Line2D at 0x1a5090b3a90>]
../_images/4bdf11e1fc397d63d1bedad4ab36eda87210f12eb274eb513979c9905b0efe28.png

Determinant-of-Hessian (DoH)#

This approach works by determining maxima in the Hessian determinant image of a Gaussian blurred image of the original (read more).

coordinates_doh = blob_doh(image, min_sigma=1, max_sigma=10, num_sigma=10, threshold=1)
coordinates_doh
array([[25., 85., 10.],
       [43., 37., 10.],
       [86., 34.,  8.],
       [71., 85., 10.],
       [ 0., 30., 10.],
       [31., 70.,  9.],
       [ 0., 77., 10.],
       [76., 16., 10.],
       [ 0., 57.,  9.],
       [ 1., 93.,  5.],
       [97., 89.,  3.],
       [ 0., 44.,  6.],
       [71., 29.,  9.],
       [ 0.,  0.,  9.],
       [19., 16., 10.],
       [95., 22.,  9.],
       [62.,  0., 10.],
       [92.,  0., 10.],
       [28., 50., 10.],
       [41., 81.,  9.],
       [30., 25., 10.],
       [59., 72., 10.],
       [43., 58., 10.],
       [85., 95.,  9.],
       [88., 74., 10.],
       [17., 34.,  5.],
       [74., 45., 10.],
       [98., 84.,  1.],
       [53., 11., 10.],
       [99., 43.,  9.],
       [35., 98.,  9.],
       [58., 49.,  9.],
       [57., 99.,  9.],
       [10., 99.,  7.],
       [57., 34.,  3.],
       [32.,  0., 10.]])
cle.imshow(image, continue_drawing=True)
plt.plot(coordinates_doh[:, 1], coordinates_doh[:, 0], 'r.')
[<matplotlib.lines.Line2D at 0x1a5090d0310>]
../_images/2406ef61364ebb6c3f17adc617d29a3cb276c0f340ec7008c4d5710eccacf5aa.png