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).
001. import numpy as np
002. from string import upper
003. import ia870
004. 
005. def iablob(fr, measurement, option="image"):
006. 
007.     measurement = upper(measurement)
008.     option      = upper(option)
009.     if len(fr.shape) == 1: fr = fr[newaxis,:]
010.     n = fr.max()
011.     if   option      == 'DATA':        y = []
012.     elif measurement == 'CENTROID':    y = np.zeros(fr.shape,bool)
013.     elif measurement == 'BOUNDINGBOX': y = np.zeros(fr.shape,bool)
014.     elif measurement == 'PERIMETER':   y = np.zeros(fr.shape,np.int32)
015.     elif measurement == 'AREA':        y = np.zeros(fr.shape,np.int32)
016.     else:                              y = np.zeros(fr.shape)
017. 
018.     if measurement == 'AREA':
019.         area = np.bincount(fr.ravel())
020.         if option == 'DATA':
021.             y = area[1::]
022.         else:
023.             for i in xrange(1,n+1):
024.                y[fr==i] = area[i]
025. 
026.     elif measurement == 'CENTROID':
027.         for i in xrange(1,n+1):
028.             aux  = (fr==i)
029.             xind,yind = np.nonzero(aux)
030.             area = len(xind)
031.             centroid = [xind.sum()/area,yind.sum()/area]
032.             if option == 'DATA': y.append([centroid[1],centroid[0]])
033.             else               : y[centroid[0],centroid[1]] = 1
034. 
035.     elif measurement == 'BOUNDINGBOX':
036.         for i in xrange(1,n+1):
037.             aux = (fr==i)
038.             col, = np.nonzero(aux.any(0))
039.             row, = np.nonzero(aux.any(1))
040.             if option == 'DATA': y.append([col[0],row[0],col[-1],row[-1]])
041.             else:
042.                 y[row[0]:row[-1],col[0] ] = 1
043.                 y[row[0]:row[-1],col[-1]] = 1
044.                 y[row[0], col[0]:col[-1]] = 1
045.                 y[row[-1],col[0]:col[-1]] = 1
046. 
047.     elif measurement == 'PERIMETER':
048.         Bc = ia870.iasecross()
049.         for i in xrange(1,n+1):
050.            aux = fr == i
051.            grad = aux - ia870.iaero(aux,Bc)
052.            if option == 'DATA': y.append(grad.sum())
053.            else:
054.                y[aux] = grad.sum()
055. 
056.     elif measurement == 'CIRCULARITY':
057.         Bc = ia870.iasecross()
058.         area = np.bincount(fr.ravel())
059.         perim = []
060.         for i in xrange(1,n+1):
061.            aux = fr == i
062.            grad = aux - ia870.iaero(aux,Bc)
063.            perim.append(grad.sum())
064.            if option != 'DATA':
065.                y[aux] = 4*np.pi*area[i]/(perim[i-1]**2)
066.         if option == 'DATA':
067.             perim = np.array(perim)
068.             y = 4*np.pi*area[1::]/(perim**2)
069. 
070.     elif measurement == 'ASPECTRATIO':
071.         for i in xrange(1,n+1):
072.             aux = (fr==i)
073.             col, = np.nonzero(aux.any(0))
074.             row, = np.nonzero(aux.any(1))
075.             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))
076.             else:
077.                 y[aux] = 1.*(min(col[-1]-col[0],row[-1]-row[0])+1)/(max(col[-1]-col[0],row[-1]-row[0])+1)
078. 
079.     elif measurement == 'COMPACTNESS':
080.         for i in xrange(1,n+1):
081.             aux  = (fr==i)
082.             xind,yind = np.nonzero(aux)
083.             area = len(xind)
084.             centroid = [xind.sum()/area,yind.sum()/area]
085.             m20 = ((1.*xind-centroid[0])**2).sum()/area
086.             m02 = ((1.*yind-centroid[1])**2).sum()/area
087.             compactness = area/(2*np.pi*(m20+m02))
088.             if option == 'DATA': y.append(compactness)
089.             else               : y[aux] = compactness
090. 
091.     elif measurement == 'ECCENTRICITY':
092.         for i in xrange(1,n+1):
093.             aux  = (fr==i)
094.             xind,yind = np.nonzero(aux)
095.             area = len(xind)
096.             centroid = [xind.sum()/area,yind.sum()/area]
097.             m11 = ((1.*xind-centroid[0])*(yind-centroid[1])).sum()/area
098.             m20 = ((1.*xind-centroid[0])**2).sum()/area
099.             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

01. from ia870 import iablob
02. 
03. fr=uint8([
04.    [1,1,1,0,0,0],
05.    [1,1,1,0,0,2],
06.    [1,1,1,0,2,2]])
07. d_area=iablob(fr,'area','data')
08. print 'd_area=',d_area
09. 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'