在 Petri 罐中计数菌落

10

我有一堆装满小圆点的培养皿,想在Matlab中进行数数。这可以可靠地批量完成吗?

例如,这个培养皿有352个菌落。

输入图像描述

我尝试过ImageJ,但需要剪裁掉边框并且结果不稳定。您有什么建议吗?


我已经很久没有做过这样的事情或使用Matlab了 - 但是难道你不需要使用边缘检测吗?肯定有很多预先编写好的脚本可供使用。 - benedict_w
有这个工具:NICE可以完成这项任务,但我无法打开它。它抱怨缺少某个dll文件。 - HCAI
尝试下载/安装.dll文件?检查您的Matlab版本是否正确,等等。 - benedict_w
@benedict_w 我需要特定的Matlab编译器运行时才能运行该应用程序吗?它会覆盖我当前的安装吗? - HCAI
请将示例图像中的殖民地数量作为“真实值”进行计数。 - reve_etrange
@reve_etrange 用手数了352个菌落。 - HCAI
3个回答

14

我解决这个问题的方法如下:

  1. 使用Hough变换识别对应于培养皿的圆。
  2. 使用Otsu方法进行全局阈值处理,限定在培养皿内部。
  3. 将原始图像的区域最大值作为菌落数量计数,这些最大值在分割后的图像中表示。

这个文件交换工具箱为我们提供了一个可用的环形Hough变换。从那里开始很简单:

function [count,colonies,bw] = colony_count(I)

I = rgb2gray(im2double(I)); %# Color-to-gray conversion.
[m,n] = size(I);

%# Uncomment this if you have might have some images with light background
%# and dark colonies. It will invert any that seem that way.
%#if graythresh(I) < 0.5
%#    I = imcomplement(I);
%#end

bw = I > graythresh(I); %# Otsu's method.
radii = 115:1:130; %# Approx. size of plate, narrower range = faster.
h = circle_hough(bw,radii,'same','normalise'); %# Circular HT.
peaks = circle_houghpeaks(h, radii, 'npeaks', 10); %# Pick top 10 circles.

roi = true(m,n);
for peak = peaks
    [x, y] = circlepoints(peak(3)); %# Points on the circle of this radius.
    x = x + peak(1); %# Translate the circle appropriately.
    y = y + peak(2);
    roi = roi & poly2mask(x,y,m,n); %# Cumulative union of all circles.
end

%# Restrict segmentation to dish. The erosion is to make sure no dish pixels
%# are included in the segmentation.
bw = bw & bwmorph(roi,'erode');

%# Colonies are merged in the segmented image. Observing that colonies are 
%# quite bright, we can find a single point per colony by as the regional
%# maxima (the brightest points in the image) which occur in the segmentation.
colonies = imregionalmax(I) & bw;

%# Component labeling with 4-connectivity to avoid merging adjacent colonies.
bwcc = bwconncomp(colonies,4);
count = bwcc.NumObjects;

我们使用这段代码的方式如下:

I = imread('http://i.stack.imgur.com/TiLS3.jpg');
[count,colonies,mask] = colony_count(I);

我还上传了colony_count函数到文件交换中心。 如果您有一张图片无法正常工作,但您认为应该可以,请在那里留言。

计数为359,我想这非常接近。 您可以检查分割(mask)和菌落标记(colonies)以查看出错的地方:

%# Leave out the changes to mask to just see the colony markers.
%# Then you can see why we are getting some false colonies.
R = I; R(mask) = 255; R(colonies) = 0;
G = I; G(mask) = 0; G(colonies) = 255;
B = I; B(mask) = 0; B(colonies) = 0;
RGB = cat(3,R,G,B);
imshow(RGB);

这也是检查自动处理的任何数据的随机样本的好理由。一般而言,方法在您开发它的样本数据上可以完美运行,但部分数据可能违反了您的假设。 - Li-aung Yip
@reve_etrange 这个程序非常好用!谢谢!实际上,它比手动计数法更好,因为生长在一起的菌落很难被人眼单独识别。48,000个菌落数手动计数...而用Matlab却可以计数数百万个!多么美妙的世界啊!你会把这个程序放在文件交换平台上吗? - HCAI
我尝试了几张库存图片,例如1,发现代码对半径变量非常敏感。您如何判断这个变量应该是多少?它是指以像素为单位的生长区域半径吗? - HCAI
@reve_etrange 实际上这是我在网上找到的一张图片。你认为有没有办法自动检测盘子边缘的半径并减少反射?这将是一个非常受欢迎的文件! - HCAI
2
非常好的回答。只是想评论一下,图像处理工具箱的最新版本(12a)内置了一个新的圆形霍夫变换函数。 - Sam Roberts
显示剩余6条评论

2
您可以使用一种称为连通性组件标记的技术来区分图像中的不同对象。首先,您需要通过某种阈值处理方法使图像二进制化。最后,通过两次扫描每个像素行来完成标记。我们正在寻找对象像素,即具有值1的像素。
在从左到右的扫描中: 对于每个像素p:如果p是对象像素,则从上方或左侧复制标签。如果p是背景像素或p具有标签,则不执行任何操作。
在从右到左的扫描中: 对于每个像素p:如果p是对象像素,则从右侧复制标签,如果存在标签,否则设置新标签。如果p是背景像素或p具有标签,则不执行任何操作。如果存在标签并且p右侧的像素具有不同的标签,则做出记录。
例如(来自http://webstaff.itn.liu.se/~bjogu/TNM087-2012/Fo7-2012-AH.pdf讲座幻灯片):
当您扫描整个图像时,请合并您已经注意到的所有标签(它们连接到相同的对象),然后计算不同标签的数量,您将得到计数。

我理解你所描述的过程。我的图像增加了一个培养皿边界的难度,这是很烦人的,特别是因为它的颜色与斑点相似... 是否可以在不进行物理去除的情况下消除它? - HCAI
讲解得很清楚,伙计! - Jeru Luke

1
我会这样做:
1. 将图像转换为二值图像,可以使用一些强度阈值来完成。请注意,点是较亮的,因此在进行阈值处理后,您可能需要执行1-binaryImage操作。我不知道为什么您说它们是黑色的,但无论它们是什么颜色,都是相同的思路。
2. 然后,您可以使用Hough变换并绘制rho和theta直方图
3. 在该直方图上,您可以对半径== rho 进行第二个阈值处理。 补充:

通过Hough变换在灰度图像中检测具有不同半径的圆


为什么要使用霍夫变换?这里没有需要检测的直线。 - Niki
从维基百科中@nikie:“在数字图像的自动化分析中,通常会出现检测简单形状(如直线、圆或椭圆)的子问题。” - 0x90
你是不是使用了错误的链接?如果我按照你答案中的Hough变换链接,它明确表示“使用hough函数来检测图像中的线条”。 - Niki
@nikie 我还添加了一个模块,使用霍夫变换来检测圆形。 - 0x90

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接