我试图将显示一些 E的显微镜明视场图像分段。大肠杆菌细菌。 我正在使用的图片类似于这个图片(即使这个图片是通过相位对比获得的):
我的问题是,在运行我的分割功能(下面的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中的第一部分代码包括平面拟合和减法。
答案 0 :(得分:1)
此处可以使用与this related stackoverflow answer中描述的方法类似的方法。
它基本上是这样的:
为您的图像设定阈值
对阈值图像应用距离变换
阈值距离转换,以便只留下每个细菌的一小部分“种子”部分
标记这些种子,给每个种子一个不同的灰色 (还为背景添加标记的种子)
使用这些种子和距离转换图像执行分水岭算法,以获得细菌的分离轮廓
查看链接的答案,了解一些可以更清晰的图片。
答案 1 :(得分:0)
一些想法:
我没有完整的食谱,但即便是这个非常简单的事情似乎也提供了很多有趣的信息:
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')
这给出了:
这表明,如果使用具有固定轮廓的轮廓跟踪技术,您将获得相当漂亮的扩张和侵蚀起点。因此,阈值处理有两个不同之处:
答案 2 :(得分:0)
有一天skimage Watershed segmentation对我来说比任何OpenCV样本都更有用。它使用了从Cellprofiler项目借用的一些代码(基于python的工具,用于复杂的细胞图像分析)。提示:使用Euclidean distance transform from opencv,它比scipy实现更快。此外,peak_local_max
函数具有 distance 参数,这对于精确的单个细胞区分非常有用。我认为这个函数在查找细胞峰值时比粗糙阈值更稳健(因为细胞强度可能不同)。
您可以找到scipy分水岭实施,但它有奇怪的行为。