Monday, June 25, 2012

Neighbourhood in a labelled image

Image segmentation can yield labelled images, where the different labels correspond to the objects of interest ( chromosomes, a nuclei ). 


It can be necessary to consider particles in the neighbourhood of a given particle. 
The following 4x4 labelled image (a numpy array) is made of four particles:
  • first particle : light blue (value or label=1)
  • second particle : green (value=2)
  • third particle : orange (value=3)
  • fourth particle : red (value=4)
  • background : dark blue (value = 0)

Considering a 3x3 domain (in fact a structuring element), the neighbour particle of the first particle is the 'orange' particle. The 'orange' particle has two neighbours, the 'light blue' and the 'green' particle .

The following python script takes a label image (from the above example) and returns a dictionary, where  in the  key/value pair, the key corresponds to a chosen particle and the value to a set containing the label value of the neighbouring particles:

{1: set([0, 3]), 2: set([0, 3, 4]), 3: set([0, 1, 2]), 4: set([0, 2])}
The calculated dictionary is closed to an adjacency list.


# -*- coding: utf-8 -*-
"""
Created on Mon Jun 25 10:26:01 2012

@author: Jean-Patrick Pommier
"""

import numpy as np
import mahotas as mh
import pylab as plb 

def makelabelarray():
    label = np.array([[0,1,0,0],
                     [1,0,0,2],
                     [3,0,2,2],
                     [0,2,0,4]])
    return label

def findneighborhoods(label,neighborhood):
    ''' given a labelled image, should return the adjacency list
        of particles, for a given neighborhood:
        
        neighborhood=np.array([1,1,1],[1,1,1],[1,1,1])
        
        The background (0), is kept as a particle neighbor 
        No fancy indexing
    '''
    #make the labels list
    labmax = label.max()
    #print labmax
    neighb_dic = {} # a dictionnary containing particle label as key and neighborhood
    for i in range(1,labmax+1):
        mask = (label ==i)
        #print mask
        dilated = mh.dilate(mask,n)
        neighbor = np.logical_and(dilated, np.logical_not(mask))
        #print neighbor
#==============================================================================
#         #Done without fancy indexing
#==============================================================================
        flatlab = np.ndarray.flatten(label)
        flatneighborhood = np.ndarray.flatten(neighbor)        
        flatneighbors = flatlab[flatneighborhood]
        flatneighbors.sort()
        #set is a trick so that each value of the neighborhoods is present only once
        neighb_dic[i] = set(flatneighbors)
        #print np.nonzero(flatneighbors)
    return neighb_dic
        
if __name__ == "__main__":
    a = makelabelarray()
    n = np.array([[1,1,1],[1,1,1],[1,1,1]])
    print findneighborhoods(a, n)
    plb.imshow(a,interpolation = 'nearest')
    plb.show()