Blob features

Find connected regions (blobs) in a grey-scale image.

class machinevisiontoolbox.ImageBlobs.ImageBlobsMixin[source]
blobs(**kwargs)[source]

Find and describe blobs in image

Returns

blobs in the image

Return type

Blobs

Find all blobs in the image and return an object that contains geometric information about them. The object behaves like a list so it can be indexed and sliced.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> type(blobs)
<class 'machinevisiontoolbox.ImageBlobs.Blobs'>
>>> len(blobs)
2
>>> print(blobs)
┌───┬────────┬──────────────┬──────────┬───────┬───────┬────────┬────────┬────────┐
│id │ parent │     centroid │     area │ touch │ perim │ circul │ orient │ aspect │
├───┼────────┼──────────────┼──────────┼───────┼───────┼────────┼────────┼────────┤
│ 0 │     -1 │ 371.2, 355.2 │ 7.59e+03 │ False │ 556.6 │  0.343 │ -11.7° │  0.584 │
│ 1 │     -1 │ 171.2, 155.2 │ 7.59e+03 │ False │ 556.6 │  0.343 │ -11.7° │  0.584 │
└───┴────────┴──────────────┴──────────┴───────┴───────┴────────┴────────┴────────┘

References
  • Robotics, Vision & Control for Python, Section 12.1.2.1, P. Corke, Springer 2023.

Represent blobs

This object contains the features of every blob in the image.

class machinevisiontoolbox.ImageBlobs.Blobs(image=None, **kwargs)[source]

Find blobs and compute their attributes

Parameters

image (Image, optional) – image to use, defaults to None

Uses OpenCV functions findContours to find a hierarchy of regions represented by their contours, and boundingRect, moments to compute moments, perimeters, centroids etc.

This class behaves like a list and each blob is an element of the list

>>> from machinevisiontoolbox import Image
>>> img = Image.Read('sharks.png')
>>> blobs = img.blobs()
>>> len(blobs)
4
>>> blobs[0]
┌───┬────────┬──────────────┬──────────┬───────┬───────┬────────┬────────┬────────┐
│id │ parent │     centroid │     area │ touch │ perim │ circul │ orient │ aspect │
├───┼────────┼──────────────┼──────────┼───────┼───────┼────────┼────────┼────────┤
│ 0 │     -1 │ 245.6, 425.9 │ 1.85e+04 │ False │ 811.2 │  0.392 │  -1.0° │  0.561 │
└───┴────────┴──────────────┴──────────┴───────┴───────┴────────┴────────┴────────┘

>>> blobs.area
array([18465.5,  7509.5,  7523. , 14356. ])

The list can be indexed, sliced or used as an iterator in a for loop or comprehension, for example:

>>> for blob in blobs:
>>>   # do a thing
>>> areas = [blob.area for blob in blobs]

However the last line can also be written as:

>>> areas = blobs.area

since all methods return a scalar if applied to a single blob:

>>> blobs[1].area

or a list if applied to multiple blobs:

>>> blobs.area

Note

A color image is internally converted to greyscale.

References
  • Robotics, Vision & Control for Python, Section 12.1.2.1, P. Corke, Springer 2023.

Seealso

filter sort opencv.moments, opencv.boundingRect, opencv.findContours

filter(area=None, circularity=None, color=None, touch=None, aspect=None)[source]

Filter blobs

Parameters
  • area (scalar or array_like(2), optional) – area minimum or range, defaults to None

  • circularity (scalar or array_like(2), optional) – circularity minimum or range, defaults to None

  • color (bool, optional) – color/polarity to accept, defaults to None

  • touch (bool, optional) – blob touch status to accept, defaults to None

  • aspect (scalar or array_like(2), optional) – aspect ratio minimum or range, defaults to None

Returns

set of filtered blobs

Return type

Blobs

Return a set of blobs that match the filter criteria.

Parameter

Description

"area"

Blob area

"circularity"

Blob circularity

"aspect"

Aspect ratio of equivalent ellipse

"touch"

Blob edge touch status

The filter parameter arguments are:

  • a scalar, representing the minimum acceptable value

  • a array_like(2), representing minimum and maximum acceptable value

Example:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'blobs' is not defined
References
  • Robotics, Vision & Control for Python, Section 12.1.2.1, P. Corke, Springer 2023.

Seealso

sort

sort(by='area', reverse=False)[source]

Sort blobs

Parameters
  • by (str, optional) – parameter to sort on, defaults to “area”

  • reverse (bool, optional) – sort in ascending order, defaults to False

Returns

set of sorted blobs

Return type

Blobs

Return a blobs object where the blobs are sorted according to the sort parameter:

Parameter

Description

"area"

Blob area

"circularity"

Blob circularity

"perimeter"

Blob external perimeter length

"aspect"

Aspect ratio of equivalent ellipse

"touch"

Blob edge touch status

Example:

>>> from machinevisiontoolbox import Image
>>> img = Image.Read('sharks.png')
>>> blobs = img.blobs()
>>> blobs.sort()
┌───┬────────┬──────────────┬──────────┬───────┬────────┬────────┬────────┬────────┐
│id │ parent │     centroid │     area │ touch │  perim │ circul │ orient │ aspect │
├───┼────────┼──────────────┼──────────┼───────┼────────┼────────┼────────┼────────┤
│ 1 │     -1 │ 502.3, 183.9 │ 7.51e+03 │ False │  514.8 │  0.396 │ -30.9° │  0.562 │
│ 2 │     -1 │  82.9, 159.6 │ 7.52e+03 │ False │  513.4 │  0.399 │  28.9° │  0.562 │
│ 3 │     -1 │ 297.0, 180.0 │ 1.44e+04 │ False │ 1235.4 │  0.132 │ -95.6° │  0.701 │
│ 0 │     -1 │ 245.6, 425.9 │ 1.85e+04 │ False │  811.2 │  0.392 │  -1.0° │  0.561 │
└───┴────────┴──────────────┴──────────┴───────┴────────┴────────┴────────┴────────┘

References
  • Robotics, Vision & Control for Python, Section 12.1.2.1, P. Corke, Springer 2023.

Seealso

filter

property area

Area of the blob

Returns

area in pixels

Return type

int

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].area
7590.5
>>> blobs.area
array([7590.5, 7590.5])
property u

u-coordinate of the blob centroid

Returns

u-coordinate (horizontal)

Return type

float

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].u
371.2073205542015
>>> blobs.u
array([371.2073, 171.2073])
property v

v-coordinate of the blob centroid

Returns

v-coordinate (vertical)

Return type

float

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].v
355.18802011286033
>>> blobs.v
array([355.188, 155.188])
property centroid

Centroid of blob

Returns

centroid of the blob

Return type

2-tuple

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].bboxarea
122400
>>> blobs.bboxarea
array([122400,  20800])
Seealso

u v moments

property p

Centroid point of blob

Returns

centroid of the blob

Return type

2-tuple

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].bboxarea
122400
>>> blobs.bboxarea
array([122400,  20800])
Seealso

u v

property bbox

Bounding box

Returns

bounding

Return type

ndarray(4)

The bounding box is a 1D array [umin, umax, vmin, vmax].

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].bbox
array([299, 445, 300, 408])
>>> blobs.bbox
[array([299, 445, 300, 408]), array([ 99, 245, 100, 208])]

Note

The bounding box is the smallest box with vertical and horizontal edges that fully encloses the blob.

Seealso

umin vmin umax umax,

property umin

Minimum u-axis extent

Returns

maximum u-coordinate of the blob

Return type

int

Returns the u-coordinate of the left side of the bounding box.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].umin
299
>>> blobs.umin
array([299,  99])
Seealso

umax bbox

property umax

Maximum u-axis extent

Returns

maximum u-coordinate of the blob

Return type

int

Returns the u-coordinate of the right side of the bounding box.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].umin
299
>>> blobs.umin
array([299,  99])
Seealso

umin bbox

property vmin

Maximum v-axis extent

Returns

maximum v-coordinate of the blob

Return type

int

Returns the v-coordinate of the top side of the bounding box.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].vmin
299
>>> blobs.vmin
array([299,  99])
Seealso

vmax bbox

property vmax

Minimum v-axis extent

Returns

maximum v-coordinate of the blob

Return type

int

Returns the v-coordinate of the bottom side of the bounding box.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].vmax
853
>>> blobs.vmax
array([853, 453])
Seealso

vmin bbox

property bboxarea

Area of the bounding box

Returns

area of the bounding box in pixels

Return type

int

Return the area of the bounding box which is invariant to blob position.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].bboxarea
122400
>>> blobs.bboxarea
array([122400,  20800])

Note

The bounding box is the smallest box with vertical and horizontal edges that fully encloses the blob.

Seealso

bbox area fillfactor

property fillfactor

Fill factor, ratio of area to bounding box area

Returns

fill factor

Return type

int

Return the ratio, \(\le 1\), of the blob area to the area of the bounding box. This is a simple shape metric which is invariant to blob position and scale.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].fillfactor
0.06201388888888889
>>> blobs.fillfactor
array([0.062 , 0.3649])

Note

The bounding box is the smallest box with vertical and horizontal edges that fully encloses the blob.

Seealso

bbox

property a

Radius of equivalent ellipse

Returns

largest ellipse radius

Return type

float

Returns the major axis length which is invariant to blob position and orientation.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].a
69.53272449306235
>>> blobs.a
array([69.5327, 69.5327])
Seealso

b aspect

property b

Radius of equivalent ellipse

Returns

smallest ellipse radius

Return type

float

Returns the minor axis length which is invariant to blob position and orientation.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].b
40.59882970386957
>>> blobs.b
array([40.5988, 40.5988])
Seealso

a aspect

property aspect

Blob aspect ratio

Returns

ratio of equivalent ellipse axes

Return type

float

Returns the ratio of equivalent ellipse axis lengths, \(<1\), which is invariant to blob position, orientation and scale.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].aspect
0.5838808992436407
>>> blobs.aspect
array([0.5839, 0.5839])
Seealso

a b

property orientation

Blob orientation

Returns

Orientation of equivalent ellipse (in radians)

Return type

float

Returns the orientation of equivalent ellipse major axis with respect to the horizontal axis, which is invariant to blob position and scale.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].orientation
-0.2046350254173464
>>> blobs.orientation
array([-0.2046, -0.2046])
property touch

Blob edge touch status

Returns

blob touches the edge of the image

Return type

bool

Returns true if the blob touches the edge of the image.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].touch
False
>>> blobs.touch
array([False, False])
property level

Blob level in hierarchy

Returns

blob level in hierarchy

Return type

int

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('multiblobs.png')
>>> blobs = im.blobs()
>>> blobs[2].level
2
>>> blobs.level
array([0, 1, 2, 2, 1, 0, 1, 1, 0, 1])
Seealso

color parent children dotfile

property color

Blob color

Returns

blob color

Return type

int

Blob color in a binary image. This is inferred from the level in the blob hierarchy. The background blob is black (0), the first-level child blobs are white (1), etc.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('multiblobs.png')
>>> blobs = im.blobs()
>>> blobs[2].color
0
>>> blobs.color
array([0, 1, 0, 0, 1, 0, 1, 1, 0, 1])
Seealso

level parent children

property parent

Parent blob

Returns

index of this blob’s parent

Return type

int

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('multiblobs.png')
>>> blobs = im.blobs()
>>> print(blobs)
┌───┬────────┬───────────────┬──────────┬───────┬────────┬────────┬─────────┬────────┐
│id │ parent │      centroid │     area │ touch │  perim │ circul │  orient │ aspect │
├───┼────────┼───────────────┼──────────┼───────┼────────┼────────┼─────────┼────────┤
│ 0 │     -1 │  907.9, 735.1 │ 1.94e+05 │ False │ 2219.0 │  0.551 │ -103.6° │  0.814 │
│ 1 │      0 │ 1025.0, 813.7 │ 1.06e+05 │ False │ 1386.9 │  0.770 │  -90.0° │  0.802 │
│ 2 │      1 │  938.1, 855.2 │ 1.72e+04 │ False │  489.7 │  1.005 │  -12.5° │  0.945 │
│ 3 │      1 │  988.1, 697.2 │ 1.21e+04 │ False │  411.5 │  0.999 │ -102.8° │  0.919 │
│ 4 │      0 │  846.0, 511.7 │ 1.75e+04 │ False │  495.9 │  0.996 │  -90.1° │  0.871 │
│ 5 │     -1 │  291.7, 377.8 │  1.7e+05 │ False │ 1711.6 │  0.811 │ -102.9° │  0.775 │
│ 6 │      5 │  312.7, 472.1 │ 1.75e+04 │ False │  494.5 │  1.001 │  -90.2° │   0.87 │
│ 7 │      5 │  241.9, 245.0 │ 1.75e+04 │ False │  495.9 │  0.996 │  -90.1° │  0.871 │
│ 8 │     -1 │ 1228.0, 254.3 │ 8.14e+04 │ False │ 1214.2 │  0.772 │ -102.9° │  0.651 │
│ 9 │      8 │ 1225.2, 220.0 │ 1.75e+04 │ False │  495.9 │  0.996 │  -90.0° │  0.871 │
└───┴────────┴───────────────┴──────────┴───────┴────────┴────────┴─────────┴────────┘

>>> blobs[5].parent
-1
>>> blobs[6].parent
5

A parent of -1 is the image background.

Seealso

children level dotfile

property children

Child blobs

Returns

list of indices of this blob’s children

Return type

list of int

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('multiblobs.png')
>>> blobs = im.blobs()
>>> blobs[5].children
[6, 7]
Seealso

parent level dotfile

property moments

Moments of blobs

Returns

moments of blobs

Return type

named tuple or list of named tuples

Compute multiple moments of each blob and return them as a named tuple with attributes

Moment type

attribute name

moments

m00 m10 m01 m20 m11 m02 m30 m21 m12 m03

central moments

mu20 mu11 mu02 mu30 mu21 mu12 mu03 |

normalized central moments

nu20 nu11 nu02 nu30 nu21 nu12 nu03 |

Seealso

centroid humoments

property humoments

Hu image moment invariants of blobs

Returns

Hu image moments

Return type

ndarray(7) or ndarray(N,7)

Computes the seven Hu image moment invariants of the image. These are a robust shape descriptor that is invariant to position, orientation and scale.

Seealso

moments

property perimeter_length

Perimeter length of the blob

Returns

perimeter length in pixels

Return type

float

Return the length of the blob’s external perimeter. This is an 8-way connected chain of edge pixels.

Example:

>>> from machinevisiontoolbox import Image
>>> import numpy as np
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].perimeter_length
556.5706294775009
>>> blobs.perimeter_length
array([556.5706, 556.5706])

Note

The length of the internal perimeter is found from summing the external perimeter of each child blob.

Seealso

perimeter children

property circularity

Blob circularity

Returns

circularity

Return type

float

Circularity, computed as \(\rho = \frac{A}{4 \pi p^2} \le 1\). Circularity is one for a circular blob and < 1 for all other shapes, approaching zero for a line.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].circularity
0.34258515276788193
>>> blobs.circularity
array([0.3426, 0.3426])

Note

Kulpa’s correction factor is applied to account for edge discretization:

  • Area and perimeter measurement of blobs in discrete binary pictures. Z.Kulpa. Comput. Graph. Image Process., 6:434-451, 1977.

  • Methods to Estimate Areas and Perimeters of Blob-like Objects: a Comparison. Proc. IAPR Workshop on Machine Vision Applications., December 13-15, 1994, Kawasaki, Japan L. Yang, F. Albregtsen, T. Loennestad, P. Groettum

Seealso

area perimeter_length

property perimeter

Perimeter of the blob

Returns

Perimeter, one point per column

Return type

ndarray(2,N)

Return the coordinates of the pixels that form the blob’s external perimeter. This is an 8-way connected chain of edge pixels.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].perimeter.shape
(2, 471)
>>> with np.printoptions(threshold=10):
...     blobs[0].perimeter
...     blobs.perimeter
... 
array([[367, 366, 365, ..., 370, 369, 368],
       [300, 301, 301, ..., 300, 300, 300]], dtype=int32)
[array([[367, 366, 365, ..., 370, 369, 368],
       [300, 301, 301, ..., 300, 300, 300]], dtype=int32), array([[167, 166, 165, ..., 170, 169, 168],
       [100, 101, 101, ..., 100, 100, 100]], dtype=int32)]

Note

The perimeter is not closed, that is, the first and last point are not the same.

Seealso

perimeter_approx polar

perimeter_approx()[source]

Approximate perimeter of the blob

Parameters

epsilon (int) – maximum distance between the original curve and its approximation, default is exact contour

Returns

Perimeter, one point per column

Return type

ndarray(2,N)

The result is a low-order polygonal approximation to the original perimeter. Increasing epsilon reduces the number of perimeter points.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs[0].perimeter.shape
(2, 471)
>>> blobs[0].perimeter_approx(5).shape
(2, 15)
>>> with np.printoptions(threshold=10):
...     blobs[0].perimeter_approx(5)
... 
array([[367, 316, 299, ..., 411, 369, 368],
       [300, 345, 377, ..., 337, 326, 300]], dtype=int32)

which in this case has reduced the number of perimeter points from 471 to 15.

Note

The perimeter is not closed, that is, the first and last point are not the same.

Seealso

perimeter polar cv2.approxPolyDP

polar()[source]

Boundary in polar cooordinate form

Parameters

N (int, optional) – number of points around perimeter, defaults to 400

Returns

Contour, one point per column

Return type

ndarray(2,N)

Returns a polar representation of the boundary with respect to the centroid. Each boundary point is represented by a column \((r, \theta)\). The polar profile can be used for scale and orientation invariant matching of shapes.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> p = blobs[0].polar()
>>> p.shape
(2, 400)

Note

The points are evenly spaced around the perimeter but are not evenly spaced in subtended angle.

Seealso

polarmatch perimeter

polarmatch(target)[source]

Compare polar profiles

Parameters

target (int) – the blob index to match against

Returns

similarity and orientation offset

Return type

ndarray(N), ndarray(N)

Performs cross correlation between the polar profiles of blobs. All blobs are matched against blob index target. Blob index target is included in the results.

There are two return values:

  1. Similarity is a 1D array, one entry per blob, where a value of one indicates maximum similarity irrespective of orientation and scale.

  2. Orientation offset is a 1D array, one entry per blob, is the relative orientation of blobs with respect to the target blob. The target blob has an orientation offset of 0.5. These values lie in the range [0, 1), equivalent to \([0, 2\pi)\) and wraps around.

Example:

>>> from machinevisiontoolbox import Image
>>> im = Image.Read('shark2.png')
>>> blobs = im.blobs()
>>> blobs.polarmatch(1)
([0.9999999999999999, 0.9999999999999999], array([0.5, 0.5]))

Note

  • Can be considered as matching two functions defined over \(S^1\).

  • Orientation is obtained by cross-correlation of the polar-angle profile.

Seealso

polar contour

plot_box(**kwargs)[source]

Plot a bounding box for the blob using Matplotlib

Parameters

kwargs – arguments passed to plot_box

Plot a bounding box for every blob described by this object.

Example:


Seealso

plot_labelbox plot_centroid plot_perimeter plot_box

plot_labelbox(**kwargs)[source]

Plot a labelled bounding box for the blob using Matplotlib

Parameters

kwargs – arguments passed to plot_labelbox

Plot a labelled bounding box for every blob described by this object. The blobs are labeled by their blob index.

Seealso

plot_box plot_centroid plot_perimeter plot_labelbox

plot_centroid(label=False, **kwargs)[source]

Draw the centroid of the blob using matplotlib

Parameters
  • label (bool) – add a sequential numeric label to each point, defaults to False

  • kwargs – other arguments passed to plot_point

If no marker style is given then it will be an overlaid “o” and “x” in blue.

Seealso

plot_box plot_perimeter plot_point

plot_perimeter(**kwargs)[source]

Plot perimeter of blob using Matplotlib

Parameters

kwargs – line style parameters passed to plot

Highlights the perometer of a blob or blobs on the current plot.

Seealso

plot_box plot_centroid

label_image(image=None)[source]

Create label image from blobs

Parameters

image (Image, optional) – image to draw into, defaults to new image

Returns

greyscale label image

Return type

Image

The perimeter information from the blobs is used to generate a greyscale label image where the greyvalue of each region corresponds to the blob index.

Seealso

labels_binary

dotfile(filename=None, direction=None, show=False)[source]

Create a GraphViz dot file

Parameters
  • filename (str, optional) – filename to save graph to, defaults to None

  • direction (str, optional) – graph drawing direction, defaults to top to bottom

  • show (bool, optional) – compile the graph and display in browser tab, defaults to False

Creates the specified file which contains the GraphViz code to represent the blob hierarchy as a directed graph. By default output is to the console.

Note

If filename is a file object then the file will not be closed after the GraphViz model is written.

Seealso

child parent level