Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab: How to bend line in image

I have a image(png format) in hand. The lines that bound the ellipses (represent the nucleus) are over straight which are impractical. How could i extract the lines from the image and make them bent, and with the precondition that they still enclose the nucleus.

The following is the image:
enter image description here

After bending

enter image description here

EDIT: How can i translate the Dilation And Filter part in answer2 into Matlab language? I can't figure it out.

like image 537
Elsie Avatar asked Nov 01 '11 07:11

Elsie


People also ask

How do you break a line in Matlab?

c = newline creates a newline character. newline is equivalent to char(10) or sprintf('\n') . Use newline to concatenate a newline character onto a character vector or a string, or to split text on newline characters.

How do I draw a line on an image in Matlab?

Display the image. imshow(I); Draw a Line ROI on the image. roi = drawline('Color','r');

What does '@' mean in Matlab?

Description: The @ symbol forms a handle to either the named function that follows the @ sign, or to the anonymous function that follows the @ sign. You can also use @ to call superclass methods from subclasses.


1 Answers

Ok, here is a way involving several randomization steps needed to get a "natural" non symmetrical appearance.

I am posting the actual code in Mathematica, just in case someone cares translating it to 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]

enter image description here

(*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] 

enter image description here

(*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*)]
 ]

The result is:

enter image description here

Edit

For the Mathematica oriented reader, a functional code for the last loop could be easier (and shorter):

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]
like image 137
Dr. belisarius Avatar answered Oct 13 '22 21:10

Dr. belisarius