【发布时间】:2013-12-19 20:20:41
【问题描述】:
我有这样的图像:
我要做的是在不同颜色的两个部分之间找到这个单元格的外边缘和单元格的内边缘。
但是这张图片包含了很多我认为的细节,有没有什么办法可以简化这张图片,去掉那些小边缘,找到我想要的边缘?
我试过matlab提供的edge函数。但它只能找到外部边缘,并受到那些细节边缘的干扰。
【问题讨论】:
标签: matlab image-processing edge-detection
我有这样的图像:
我要做的是在不同颜色的两个部分之间找到这个单元格的外边缘和单元格的内边缘。
但是这张图片包含了很多我认为的细节,有没有什么办法可以简化这张图片,去掉那些小边缘,找到我想要的边缘?
我试过matlab提供的edge函数。但它只能找到外部边缘,并受到那些细节边缘的干扰。
【问题讨论】:
标签: matlab image-processing edge-detection
这是一项非常具有挑战性的工作,因为边界模糊,红色和绿色强度之间的差异很小。如果你想非常精确地实现分割并满足一些医疗要求,Shai 的 k-means 加graph cuts 可能是极少数的选择之一(EM algorithm 可能是一个替代方案)。如果您有一个包含许多相似图像的大型数据库,一些machine learning methods 可能会有所帮助。否则,我只是写了一个非常简单的代码,为您粗略地提取内部红色区域。边界不是那么准确,因为还包括了一些绿色区域。
I1=I;
I=rgb2hsv(I);
I=I(:,:,1); % the channel with relatively large margin between green and red
I=I.*(I<0.25);
I=imdilate(I, true(5));
% I=imfill(I,'holes'); depends on what is your definition of the inner boundary
bw=bwconncomp(I);
ar=bw.PixelIdxList;
% find the largest labeled area,
n=0;
for i=1:length(ar)
if length(ar{i})>n
n=length(ar{i});
num=i;
end
end
bw1=bwlabel(I);
bwfinal(:,:,1)=(bw1==num).*double(I1(:,:,1));
bwfinal(:,:,2)=(bw1==num).*double(I1(:,:,2));
bwfinal(:,:,3)=(bw1==num).*double(I1(:,:,3));
bwfinal=uint8(bwfinal);
imshow(bwfinal)
【讨论】:
在我看来,图像中有三种主色:
1. 蓝色背景(但在单元格内也显示为“噪音”)
2. grenn-ish 细胞的一部分
3. red-ish - 单元格的第二部分
如果这三种颜色足够明显,您可以尝试使用 k-means 和 Graph cut 对图像进行分割。
第一阶段 - 使用 k-means 将每个像素与三种主色中的一种相关联。将 k-means 应用于图像的颜色(每个像素是您选择的颜色空间中的 3 向量)。使用k=3 运行 k-means,保持每个像素与质心的距离。
第二阶段 - 将单元格与背景分开。使用图切割进行二元分割。每个像素的数据成本要么是到背景颜色的距离(如果像素被标记为“背景”),要么是到其他两种颜色的最小距离(如果像素被标记为“前景”)。使用图像对比度设置平滑项的成对权重。
第三阶段 - 将细胞的两个部分分开。再次使用 graph-cut 进行二元分割,但这次只对上一阶段标记为“单元格”的像素起作用。对于所有标签,k 均值分配给背景但被标记为单元格的像素的数据项应该为零(这些是单元格内的“噪声”像素)。
您可能会发现我的matlab wrapper for graph-cuts 对这项任务很有用。
【讨论】: