【问题标题】:Matlab: How to bend line in imageMatlab:如何弯曲图像中的线
【发布时间】:2011-11-01 07:10:12
【问题描述】:

我手头有一张图片(png 格式)。限制椭圆(代表原子核)的线过于笔直,这是不切实际的。我怎样才能从图像中提取线条并使它们弯曲,并且前提是它们仍然包围着细胞核。

以下是图片:

弯曲后

编辑:如何将 answer2 中的 Dilation And Filter 部分翻译成 Matlab 语言?我想不通。

【问题讨论】:

  • 你说的是黑线吗?
  • 在这种情况下,“弯曲”是什么意思。您能否在图像中选择一条线并绘制“弯曲”后的样子?
  • 请看我的编辑。谢谢。
  • @Ivy 取决于您需要多少这些,但老实说,这种类型的最佳模型似乎是从您的示例中的真实图像派生的阈值/简化图像。
  • @John 我认为可以从核心椭圆模拟某种随机增长,但我仍然无法理解。

标签: matlab image-processing line


【解决方案1】:

好的,这是一种涉及获得“自然”非对称外观所需的多个随机化步骤的方法。

我将实际代码发布在 Mathematica 中,以防有人关心将其翻译成 Matlab。

(* A preparatory step: get your image and clean it*)
i = Import@"http://i.stack.imgur.com/YENhB.png";
i1 = Image@Replace[ImageData[i], {0., 0., 0.} -> {1, 1, 1}, {2}];
i2 = ImageSubtract[i1, i];
i3 = Inpaint[i, i2]

(*Now reduce to a skeleton to get a somewhat random starting point.  
The actual algorithm for this dilation does not matter, as far as we 
get a random area slightly larger than the original elipses *)
id = Dilation[SkeletonTransform[
             Dilation[SkeletonTransform@ColorNegate@Binarize@i3, 3]], 1] 

(*Now the real random dilation loop*)
(*Init vars*)
p = Array[1 &, 70]; j = 1;
(*Store in w an image with a different color for each cluster, so we 
can find edges between them*)
w = (w1 = 
      WatershedComponents[
       GradientFilter[Binarize[id, .1], 1]]) /. {4 -> 0} // Colorize;
(*and loop ...*)
For[i = 1, i < 70, i++,
 (*Select edges in w and dilate them with a random 3x3 kernel*)
 ed = Dilation[EdgeDetect[w, 1], RandomInteger[{0, 1}, {3, 3}]];
 (*The following is the core*)
 p[[j++]] = w =
   ImageFilter[  (* We apply a filter to the edges*)
    (Switch[
          Length[#1],  (*Count the colors in a 3x3 neighborhood of each pixel*)
          0, {{{0, 0, 0}, 0}},          (*If no colors, return bkg*)
          1, #1,                        (*If one color, return it*)
          _, {{{0, 0, 0}, 0}}])[[1, 1]] (*If more than one color, return bkg*)&@
      Cases[Tally[Flatten[#1, 1]], 
       Except[{{0.`, 0.`, 0.`}, _}]] & (*But Don't count bkg pixels*),
    w, 1,
    Masking -> ed,       (*apply only to edges*)
    Interleaving -> True (*apply to all color chanels at once*)]
 ]

结果是:

编辑

对于面向 Mathematica 的读者,最后一个循环的功能代码可能更容易(而且更短):

NestList[
 ImageFilter[  
   If[Length[#1] ==  1, #1[[1, 1]], {0, 0, 0}] &@
     Cases[Tally[Flatten[#1, 1]], Except[{0.` {1, 1, 1}, _}]] & , #, 1,
   Masking      -> Dilation[EdgeDetect[#, 1], RandomInteger[{0, 1}, {3, 3}]],  
   Interleaving -> True ] &,
 WatershedComponents@GradientFilter[Binarize[id,.1],1]/.{4-> 0}//Colorize, 
5]

【讨论】:

  • 您上面使用的算法,如果我的理解是正确的,您可以为分水岭区域分配不同的颜色,一旦膨胀相遇,它将返回背景颜色为黑色的边缘。它在 Mathematica 中效果很好。现在我正在尝试在matlab中应用这种方法,希望我能做到。谢谢。
  • @Ivy 是的。注意随机化部分。如果你不这样做,你最终会得到一个漂亮的方形格子拼布。祝你好运!
  • @Ivy 用户 Amro 是将 Mathematica 转换为 Matlab 的艺术大师......以防万一
  • 感谢您的信任投票,但翻译起来很难(我自己还在学习 Mathematica)...无论如何,我会尽快查看并报告。非常好的解决方案顺便说一句 +1
  • @Amro 你在很大程度上值得我表扬!无论如何,如果您正在学习 Mma,请记得查看 SO 中的 Mma 标签问题和答案。有很多知识渊博的用户可以向他们学习。
【解决方案2】:

您的输入是 Voronoi 图。您可以使用另一个距离函数而不是欧几里得函数重新计算它。

这是 Mathematica 中使用曼哈顿距离的示例(i3 是您的输入图像,没有线条):

ColorCombine[{Image[
   WatershedComponents[
    DistanceTransform[Binarize@i3, 
      DistanceFunction -> ManhattanDistance] ]], i3, i3}]

编辑

我正在使用另一种算法(初步结果)。你怎么看?

【讨论】:

  • OP 想要更多栩栩如生的细胞。即 less 像 Voronoi 图。查看示例照片,您会看到一些细胞具有更大的压力或其他原因,并且会凸出并挤压其他细胞。
  • @John 我明白这一点。我试图让事情变得简单。如果工作允许,我会再试一次。
  • 不错!我会关注这个帖子。这是一个很好的问题。
  • @John 觉得我的新画怎么样?我还在研究一些细节!
  • 这真是太棒了。我喜欢它!
【解决方案3】:

这是我想出来的,不是直接翻译@belisarius代码,但应该够接近了..

%# read image (indexed image)
[I,map] = imread('http://i.stack.imgur.com/YENhB.png');

%# extract the blobs (binary image)
BW = (I==1);

%# skeletonization + dilation
BW = bwmorph(BW, 'skel', Inf);
BW = imdilate(BW, strel('square',2*1+1));

%# connected components
L = bwlabel(BW);
imshow(label2rgb(L))

%# filter 15x15 neighborhood
for i=1:13
    L = nlfilter(L, [15 15], @myFilterFunc);
    imshow( label2rgb(L) )
end

%# result
L(I==1) = 0;                %# put blobs back
L(edge(L,'canny')) = 0;     %# edges
imshow( label2rgb(L,@jet,[0 0 0]) )

myFilterFunc.m

function p = myFilterFunc(x)
    if range(x(:)) == 0
        p = x(1);                %# if one color, return it
    else
        p = mode(x(x~=0));       %# else, return the most frequent color
    end
end

结果:

这是过程的动画:

【讨论】:

  • +1 不错。我的回答中使用了掩蔽来提供额外的随机化步骤。无论如何,我认为这已经足够开始了。恭喜!
  • @Amro: 相邻部分花费时间......无论如何,这真的很酷!
猜你喜欢
  • 2011-12-20
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
  • 2019-12-10
  • 2013-08-13
相关资源
最近更新 更多