NA/NI max-tree implementation

C++ Code

OK

SWIG header

OK [C/C++ extension is up-to-date]

Python Wrapper

001. import numpy as np
002. from iamxt.se2off import se2off
003. from iamxt.max_tree_c_01 import counting_sort_c, union_find2d_c, canonicalize_c
004. 
005. def max_tree_na_ni(f, Bc):
006.     off = se2off(Bc) # Array of offsets
007.     parent = np.empty(f.size, dtype = np.int32)
008.     parent[:] = -1
009.     zpar = np.empty(f.size, dtype = np.int32)
010. 
011.     flat_img = f.ravel()
012.     S_rev = counting_sort_c(flat_img)
013.     H,W = f.shape
014.     union_find2d_c(H,W,off,parent,zpar,S_rev,flat_img)
015.     canonicalize_c(flat_img,parent,S_rev)
016.     node_index = np.empty(f.shape, dtype = np.int32)
017.     node_index[:] = -1
018.     node_array = computeNodeArray2d_c(parent,flat_img,S_rev,node_index)
019.     node_array = node_array.T.copy()
020.     return parent,S_rev,node_array,node_index
021. 
022. 
023. def clone(self):
024.     mxt = copy.deepcopy(self)
025.     return mxt
026. 
027. def compact(self, to_remove,lut):
028.     N = self.node_array.shape[1]
029.     parent = self.node_array[0,:]
030.     # compute index offset in lut
031.     index_fix = to_remove.astype(np.int32).cumsum()
032.     lut = lut - index_fix[lut]
033.     self.node_array[0,:] = lut[parent]
034.     self.node_index = lut[self.node_index]
035. 
036.     self.node_array = self.node_array[:,~to_remove]
037.     if not self.node_array.flags.contiguous:
038.         self.node_array = np.ascontiguousarray(self.node_array, dtype = np.int32)
039.     return self
040. 
041. def compact2(self, to_remove, lut):
042.     N = self.node_array.shape[1]
043.     parent = self.node_array[0,:]
044.     index_fix = to_remove.astype(np.int32).cumsum()
045.     lut = (lut - index_fix[lut]).astype(np.int32)
046.     self.node_array[0,:] = lut[parent]
047.     lut_node_index(lut,self.node_index)
048. 
049.     nodes_kept = np.nonzero(~to_remove)[0].astype(np.int32)
050.     new_node_array = np.empty((self.node_array.shape[0],nodes_kept.size), dtype = np.int32)
051.     new_node_array2 = np.empty((self.node_array.shape[0],nodes_kept.size), dtype = np.int32)
052. 
053.     remove_node_array_lines(nodes_kept,new_node_array,self.node_array)
054.     self.node_array = new_node_array
055.     return self
056. 
057. 
058. 
059. 
060. def contractDR(self, to_keep):
061.     to_keep[0] = True # The root can never be removed
062.     N = self.node_array.shape[1]
063.     lut = np.arange(N, dtype = np.int32)
064.     contract_dr_aux_c(to_keep.astype(np.int32),lut,self.node_array[0,:])
065.     self.compact(~to_keep,lut)
066.     return self
067. 
068. def contractDR2(self, to_keep):
069.     to_keep[0] = True # The root can never be removed
070.     N = self.node_array.shape[1]
071.     lut = np.arange(N, dtype = np.int32)
072.     contract_dr_aux_c(to_keep.astype(np.int32),lut,self.node_array[0,:])
073.     self.compact2(~to_keep,lut)
074.     return self
075. 
076. def getImage(self):
077.     newlevel = self.node_array[1,:].astype(np.uint8)
078.     return newlevel[self.node_index].reshape(self.shape)
079. 
080. def getImage2(self):
081.     out_img = np.zeros(self.node_index.shape, dtype = np.uint8)
082.     get_image_aux_c(self.node_array[1],self.node_index,out_img)
083.     return out_img
084. 
085. def computeHeight(self):
086.     parent = self.node_array[0,:]
087.     level  = self.node_array[1,:]
088.     height = np.zeros(level.size,dtype = np.int32)
089.     compute_height_aux_c(parent,level,height)
090.     return height
091. 
092. class MaxTreeICIP2015:
093. 
094.     clone = clone
095.     getImage = getImage
096.     getImage2 = getImage2
097.     compact = compact
098.     compact2 = compact2
099.     contractDR = contractDR
100.     contractDR2 = contractDR2
101. 
102.     computeHeight = computeHeight
103. 
104.     def __init__(self,img = None, Bc = None):
105.         _,_,self.node_array,self.node_index, = max_tree_na_ni(img,Bc)
106.         self.Bc = Bc
107.         self.shape = img.shape
1. from na_ni import *
2. import numpy as np
3. 
4. img = adreadgray('lenina.pgm')
5. Bc = np.ones((3,3), dtype = bool)
6. mxt = MaxTreeICIP2015(img,Bc)
7. 
8. mxt.contractDR2(mxt.node_array[2,:]>80)