Search code examples
pythonimage-processingimage-segmentationmahotasndimage

microscopy image segmentation: bacteria segmentation with python


I am trying to segment some microscopy bright-field images showing some E. coli bacteria. The picture I am working with resembles this one (even if this one is obtained with phase contrast):

microscopy bright-field image

my problem is that after running my segmentation function (OtsuMask below) I cannot distinguish dividing bacteria (you can try my code below on the sample image). This means that I get one single labeled region for a couple of bacteria which are joined by their end, instead of two different labeled images. The boundary between two dividing bacteria is too narrow to be highlighted by the morphological operations I perform on the thresholded image, but I guess there must be a way to achieve my goal.

Any ideas/suggestions?

import scipy as sp
import numpy as np
from scipy import optimize
import mahotas as mht
from scipy import ndimage
import pylab as plt


def OtsuMask(img,dilation_size=2,erosion_size=1,remove_size=500):

    img_thres=np.asarray(img)
    s=np.shape(img)    
    p0=np.array([0,0,0])

    p0[0]=(img[0,0]-img[0,-1])/512.    
    p0[1]=(img[1,0]-img[1,-1])/512.
    p0[2]=img.mean()

    [x,y]=np.meshgrid(np.arange(s[1]),np.arange(s[0]))

    p=fitplane(img,p0)    
    img=img-myplane(p,x,y)    


    m=img.min()
    img=img-m
    img=abs(img)
    img=img.astype(uint16)

    """perform thresholding with Otsu"""
    T = mht.thresholding.otsu(img,2)
    print T
    img_thres=img
    img_thres[img<T*0.9]=0
    img_thres[img>T*0.9]=1


    img_thres=-img_thres+1  

    """morphological operations"""
    diskD=createDisk(dilation_size)
    diskE=createDisk(erosion_size)

    img_thres=ndimage.morphology.binary_dilation(img_thres,diskD)   

    labeled_im,N=mht.label(img_thres)
    label_sizes=mht.labeled.labeled_size(labeled_im)
    labeled_im=mht.labeled.remove_regions(labeled_im,np.where(label_sizes<remove_size))    


    figure();
    imshow(labeled_im)

    return labeled_im

def myplane(p,x,y):

    return p[0]*x+p[1]*y+p[2] 

def res(p,data,x,y):

    a=(data-myplane(p,x,y));

    return array(np.sum(np.abs(a**2)))

def fitplane(data,p0):

    s=shape(data);

    [x,y]=meshgrid(arange(s[1]),arange(s[0]));
    print shape(x), shape(y)

    p=optimize.fmin(res,p0,args=(data,x,y));
    print p
    return p


def createDisk( size ):
    x, y = np.meshgrid( np.arange( -size, size ), np.arange( -size, size ) )
    diskMask = ( ( x + .5 )**2 + ( y + .5 )**2 < size**2)
    return diskMask

THE FIRST PART OF THE CODE IN OtsuMask CONSIST OF A PLANE FITTING AND SUBTRACTION.


Solution

  • A similar approach to the one described in this related stackoverflow answer can be used here.

    It goes basically like this:

    • threshold your image, as you have done

    • apply a distance transform on the thresholded image

    • threshold the distance transform, so that only a small 'seed' part of each bacterium remains

    • label these seeds, giving each one a different shade of gray
      (also add a labeled seed for the background)

    • execute the watershed algorithm with these seeds and the distance transformed image, to get the separatd contours of your bacteria

    Check out the linked answer for some pictures that will make this much clearer.