2

我正在尝试分割一些显示一些大肠杆菌的显微镜明场图像。我正在使用的图片类似于这张(即使这张是通过相位对比获得的):

显微明场图像

我的问题是,在运行我的分割功能(下面的 OtsuMask)后,我无法区分分裂的细菌(您可以在示例图像上尝试我的代码)。这意味着我得到了两个细菌的一个标记区域,它们的末端连接在一起,而不是两个不同的标记图像。两个分裂细菌之间的边界太窄,无法通过我在阈值图像上执行的形态学操作来突出显示,但我想一定有一种方法可以实现我的目标。

有什么想法/建议吗?

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

OtsuMask 中代码的第一部分由平面拟合和减法组成。

4

3 回答 3

1

可以在此处使用与此相关 stackoverflow 答案中描述的方法类似的方法。

它基本上是这样的:

  • 像您所做的那样阈值您的图像

  • 在阈值图像上应用距离变换

  • 阈值距离变换,因此每个细菌只剩下一小部分“种子”

  • 标记这些种子,给每个种子一个不同的灰色阴影
    (也为背景添加一个标记的种子)

  • 使用这些种子和距离变换图像执行分水岭算法,以获得细菌的分离轮廓

查看链接的答案以获取一些可以使这一点更清晰的图片。

于 2014-07-14T20:08:04.147 回答
0

有一天,skimage 分水岭分割对我来说比任何 OpenCV 样本都更有用。它使用了一些从Cellprofiler项目(基于 python 的复杂细胞图像分析工具)借来的代码。提示:使用来自 opencv 的欧几里得距离变换,它比 scipy 实现更快。peak_local_max函数还具有距离参数,可用于精确的单细胞区分。我认为这个功能在寻找细胞峰方面比粗鲁的阈值更强大(因为细胞的强度可能会有所不同)。

你可以找到 scipy 分水岭实现,但它有奇怪的行为。

于 2014-09-10T22:41:19.060 回答
0

一些想法:

  1. Otsu 可能不是一个好的选择,因为您甚至可以使用固定阈值(您的细菌是黑色的)。
  2. 用任何方法对图像进行阈值化都会删除很多有用的信息。

我没有完整的食谱给你,但即使是这个非常简单的东西似乎也能提供很多有趣的信息:

import matplotlib.pyplot as plt
import cv2

# cv2 is only used to read the image into an array, use only green channel
bact = cv.imread("/tmp/bacteria.png")[:,:,1]

# draw a contour image with fixed threshold 50
fig = plt.figure()
ax = fig.add_subplot(111)
ax.contourf(bact, levels=[0, 50], colors='k')

这给出了:

在此处输入图像描述

这表明,如果您使用具有固定轮廓的轮廓跟踪技术,您将获得非常漂亮的膨胀和腐蚀起点。因此,阈值的两个差异:

  1. 轮廓比简单的黑白阈值处理使用更多的灰度信息。
  2. 固定阈值似乎适用于这些图像,如果需要光照校正,Otsu 不是最佳选择。
于 2014-07-14T19:03:56.350 回答