Function iablob

Synopse

Blob measurements from a labeled image.

  • y = iablob(fr, measurement, option="image")
    • y: Image
    • fr: Image Labeled image.
    • measurement: String Choice from 'AREA','CENTROID', 'BOUNDINGBOX', 'PERIMETER', 'ASPECTRATIO', 'CIRCULARITY', 'COMPACTNESS' or 'ECCENTRICITY'.
    • option: String Output format:
      • 'image': results as a binary image;
      • 'data': results a column vector of measurements (attributes).
  1 import numpy as np
  2 from string import upper
  3 import ia870
  4 
  5 def iablob(fr, measurement, option="image"):
  6 
  7     measurement = upper(measurement)
  8     option      = upper(option)
  9     if len(fr.shape) == 1: fr = fr[newaxis,:]
 10     n = fr.max()
 11     if   option      == 'DATA':        y = []
 12     elif measurement == 'CENTROID':    y = np.zeros(fr.shape,bool)
 13     elif measurement == 'BOUNDINGBOX': y = np.zeros(fr.shape,bool)
 14     elif measurement == 'PERIMETER':   y = np.zeros(fr.shape,np.int32)
 15     elif measurement == 'AREA':        y = np.zeros(fr.shape,np.int32)
 16     else:                              y = np.zeros(fr.shape)
 17 
 18     if measurement == 'AREA':
 19         area = np.bincount(fr.ravel())
 20         if option == 'DATA':
 21             y = area[1::]
 22         else:
 23             for i in xrange(1,n+1):
 24                y[fr==i] = area[i]
 25 
 26     elif measurement == 'CENTROID':
 27         for i in xrange(1,n+1):
 28             aux  = (fr==i)
 29             xind,yind = np.nonzero(aux)
 30             area = len(xind)
 31             centroid = [xind.sum()/area,yind.sum()/area]
 32             if option == 'DATA': y.append([centroid[1],centroid[0]])
 33             else               : y[centroid[0],centroid[1]] = 1
 34 
 35     elif measurement == 'BOUNDINGBOX':
 36         for i in xrange(1,n+1):
 37             aux = (fr==i)
 38             col, = np.nonzero(aux.any(0))
 39             row, = np.nonzero(aux.any(1))
 40             if option == 'DATA': y.append([col[0],row[0],col[-1],row[-1]])
 41             else:
 42                 y[row[0]:row[-1],col[0] ] = 1
 43                 y[row[0]:row[-1],col[-1]] = 1
 44                 y[row[0], col[0]:col[-1]] = 1
 45                 y[row[-1],col[0]:col[-1]] = 1
 46 
 47     elif measurement == 'PERIMETER':
 48         Bc = ia870.iasecross()
 49         for i in xrange(1,n+1):
 50            aux = fr == i
 51            grad = aux - ia870.iaero(aux,Bc)
 52            if option == 'DATA': y.append(grad.sum())
 53            else:
 54                y[aux] = grad.sum()
 55 
 56     elif measurement == 'CIRCULARITY':
 57         Bc = ia870.iasecross()
 58         area = np.bincount(fr.ravel())
 59         perim = []
 60         for i in xrange(1,n+1):
 61            aux = fr == i
 62            grad = aux - ia870.iaero(aux,Bc)
 63            perim.append(grad.sum())
 64            if option != 'DATA':
 65                y[aux] = 4*np.pi*area[i]/(perim[i-1]**2)
 66         if option == 'DATA':
 67             perim = np.array(perim)
 68             y = 4*np.pi*area[1::]/(perim**2)
 69 
 70     elif measurement == 'ASPECTRATIO':
 71         for i in xrange(1,n+1):
 72             aux = (fr==i)
 73             col, = np.nonzero(aux.any(0))
 74             row, = np.nonzero(aux.any(1))
 75             if option == 'DATA': y.append(1.*(min(col[-1]-col[0],row[-1]-row[0])+1)/(max(col[-1]-col[0],row[-1]-row[0])+1))
 76             else:
 77                 y[aux] = 1.*(min(col[-1]-col[0],row[-1]-row[0])+1)/(max(col[-1]-col[0],row[-1]-row[0])+1)
 78 
 79     elif measurement == 'COMPACTNESS':
 80         for i in xrange(1,n+1):
 81             aux  = (fr==i)
 82             xind,yind = np.nonzero(aux)
 83             area = len(xind)
 84             centroid = [xind.sum()/area,yind.sum()/area]
 85             m20 = ((1.*xind-centroid[0])**2).sum()/area
 86             m02 = ((1.*yind-centroid[1])**2).sum()/area
 87             compactness = area/(2*np.pi*(m20+m02))
 88             if option == 'DATA': y.append(compactness)
 89             else               : y[aux] = compactness
 90 
 91     elif measurement == 'ECCENTRICITY':
 92         for i in xrange(1,n+1):
 93             aux  = (fr==i)
 94             xind,yind = np.nonzero(aux)
 95             area = len(xind)
 96             centroid = [xind.sum()/area,yind.sum()/area]
 97             m11 = ((1.*xind-centroid[0])*(yind-centroid[1])).sum()/area
 98             m20 = ((1.*xind-centroid[0])**2).sum()/area
 99             m02 = ((1.*yind-centroid[1])**2).sum()/area
100             eccentricity = sqrt((m20-m02)**2+4*m11**2)/(m20+m02)
101             if option == 'DATA': y.append(eccentricity)
102             else               : y[aux] = eccentricity
103 
104     else:
105         print "Measurement option should be 'AREA','CENTROID', 'BOUNDINGBOX', 'PERIMETER', "
106         print "'ASPECTRATIO', 'CIRCULARITY', 'COMPACTNESS' or 'ECCENTRICITY'."
107 
108     return np.array(y)

Description

Take measurements from the labeled image fr. The labels must be sequentially from 1 to n. The measurements are: area, centroid, or bounding rectangle. The parameter option controls the output format: 'IMAGE': the result is an image; 'DATA': the result is a double column vector with the measurement for each blob. The region with label zero is not measured as it is normally the background. The measurement of region with label 1 appears at the first row of the output.

Examples

Example 1

 1 from ia870 import iablob
 2 
 3 fr=uint8([
 4    [1,1,1,0,0,0],
 5    [1,1,1,0,0,2],
 6    [1,1,1,0,2,2]])
 7 d_area=iablob(fr,'area','data')
 8 print 'd_area=',d_area
 9 d_cent=iablob(fr,'centroid','data')
10 print 'd_cent=',d_cent
11 d_bb=iablob(fr,'boundingbox','data')
12 print 'd_bb=\n',d_bb
13 d_p=iablob(fr,'perimeter','data')
14 print 'd_p=\n',d_p
15 
16 f_area=iablob(fr,'area')
17 print 'f_area=',f_area
18 f_cent=iablob(fr,'centroid')
19 print 'f_cent=\n', f_cent * 1
20 f_bb=iablob(fr,'boundingbox')
21 print 'f_bb=\n', f_bb * 1
22 f_p =iablob(fr,'perimeter')
23 print 'f_p=\n', f_p
d_area= [9 3]
d_cent= [[1 1]
 [4 1]]
d_bb=
[[0 0 2 2]
 [4 1 5 2]]
d_p=
[3 2]
f_area= [[9 9 9 0 0 0]
 [9 9 9 0 0 3]
 [9 9 9 0 3 3]]
f_cent=
[[0 0 0 0 0 0]
 [0 1 0 0 1 0]
 [0 0 0 0 0 0]]
f_bb=
[[1 1 1 0 0 0]
 [1 0 1 0 1 1]
 [1 1 0 0 1 0]]
f_p=
[[3 3 3 0 0 0]
 [3 3 3 0 0 2]
 [3 3 3 0 2 2]]

Example Area

1 from ia870 import ialabel
2 from ia636 import ianormalize
3 
4 f=adreadgray('blob3.tif') > 0
5 fr=ialabel(f)
6 g=iablob(fr,'area')
7 adshow(f)
8 adshow(ianormalize(g))

Example Centroid

1 from ia870 import iadil, iagshow
2 
3 f=adreadgray('blob3.tif') > 0
4 fr=ialabel(f)
5 centr=iablob(fr,'centroid')
6 adshow(iagshow(f,iadil(centr)))

Example Bounding box

1 from ia870 import iagshow
2 
3 f=adreadgray('blob3.tif') > 0
4 fr=ialabel(f)
5 box=iablob(fr,'boundingbox')
6 bb = iablob(fr,'boundingbox','data')
7 print bb
8 adshow(iagshow(f,box))
[[ 32   0  56  12]
 [119   0 127  19]
 [ 14   8  35  35]
 [ 75   9 105  34]
 [ 43  13  68  41]
 [  0  15  12  39]
 [115  30 127  58]
 [ 70  40  96  64]
 [ 35  43  58  66]
 [  0  47  11  66]
 [ 98  59 125  84]
 [ 45  65  70  90]
 [  4  66  27  92]
 [ 75  77  98 105]
 [ 19  94  46 122]
 [119  95 127 113]
 [ 88  98 116 127]
 [ 50  99  78 125]]

Example Perimeter

1 from ia870 import iagshow
2 
3 f  = adreadgray('blob3.tif') > 0
4 fr = ialabel(f)
5 p  = iablob(fr,'perimeter')
6 pd = iablob(fr,'perimeter','data')
7 print pd
8 adshow(ianormalize(p))
[36 23 68 78 76 34 40 73 65 31 75 71 73 73 78 25 72 78]

See also

  • ialabel - Label a binary image
  • iagrain - Gray-scale attributes of a grain blob
  • iagshow - Display binary images overlaid a gray scale image

Contributions

  • Francislei José da Silva, Jun 2014: 'ASPECTRATIO', 'CIRCULARITY', 'COMPACTNESS' or 'ECCENTRICITY'