首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Matlab:如何在图像中弯曲直线

Matlab:如何在图像中弯曲直线
EN

Stack Overflow用户
提问于 2011-11-01 07:10:12
回答 3查看 1.6K关注 0票数 5

我手上有一张图片(png格式)。连接椭圆的线(代表原子核)是超过直线的,这是不切实际的。我如何从图像中提取出这些线,使它们弯曲,前提是它们仍然包围着细胞核。

下图如下:

弯曲后

编辑:如何将answer2中的扩展和部分转换为Matlab语言?我搞不懂。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-07 04:19:59

好的,这里有一种方法,需要几个随机化步骤才能得到“自然”的非对称外观。

我把实际的代码发布在Mathematica中,以防有人关心把它翻译到Matlab中。

代码语言:javascript
复制
(* 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]

代码语言:javascript
复制
(*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] 

代码语言:javascript
复制
(*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的读取器来说,最后一个循环的函数代码可能更容易(而且更短):

代码语言:javascript
复制
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]
票数 7
EN

Stack Overflow用户

发布于 2011-11-01 14:57:38

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

下面是数学中使用曼哈顿距离的一个例子(i3是您输入的没有线条的图像):

代码语言:javascript
复制
ColorCombine[{Image[
   WatershedComponents[
    DistanceTransform[Binarize@i3, 
      DistanceFunction -> ManhattanDistance] ]], i3, i3}]

编辑

我正在使用另一种算法(初步结果)。你认为如何?

票数 7
EN

Stack Overflow用户

发布于 2011-11-12 22:07:58

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

代码语言:javascript
复制
%# 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

代码语言:javascript
复制
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

结果:

下面是这个过程的动画:

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7963459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档