Fwd: Skeleton to fragmented line selection

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Fwd: Skeleton to fragmented line selection

BROUILLY NICOLAS
Dear list,

I have a curved line (of 1 px width) obtained from skeletonise. And I want to make it a segmented line of 14 key points (of known coordinates) and made of 13 segments of the same length. To finally be able to measure the angles between all these segments.

Obviously I don't want to do it by hand…

My first attempts were :

1. To do "Create selection" and "Area to line". But to do so I need to dilate my selection and I don't want to. Plus it makes a U-shaped line with two parts in which the angles aren't exactly the ones of the skeleton. And then I still need to extract the coordinates of the 14 points.

2. To save my binary image as "Text image". This might work but I don't know how to recover the coordinates of each 255 points and make it a line.roi file. Plus, it might be complicated because I may have several points for the same X or Y coordinate…

To illustrate, i put two images :
The first image is my raw image, the second one is the kind of image I'd like to obtain. Actually, I even only need the coordinates of the 13 points that are found along the original curve. So it's a bit like 1. I want all the coordinates of each white points along the curve in the raw image, 2. I want to know the length L of this line in pixels, 3. I need to divide this length by 13 (L/13=N), 4. obtain a number N and 5. gather the coordinates of the 14 points separated by this number N of points in my original image.

I hope no-one asked this exact question before and that someone will be able to guide me,

Thank you !

[cid:[hidden email]][cid:[hidden email]]

Nicolas Brouilly, PhD Student
Equipe Gieseler, "Pathologies du muscle chez C. elegans"

Centre de Génétique et de Physiologie Moléculaires et Cellulaires
UMR CNRS 5534
Université Claude Bernard Lyon 1
Bâtiment Gregor Mendel, 5ème étage
16, rue Raphaël Dubois
F-69622 Villeurbanne Cedex

[hidden email]<mailto:[hidden email]>
Lab : +0033 (0)4 72 43 29 48
Cel : +0033 (0)6 42 91 53 19


Image 1.tif (26K) Download Attachment
Image 2.tif (26K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Skeleton to fragmented line selection

Michael Schmid
Hi Nicholas,

looks like a task where you have to write a macro or plugin.

Erode a copy of the image with 1 iteration, count=7 in the binary  
options, and subtract it from the original. This gives you the end  
points; you can get their coordinates e.g. with 'Analyze Particles'  
or 'Find Maxima'.

Then you have to start at one of the end points of the original image  
and scan all its 8 neighbors (except the one visited just before) in  
a loop, to see where the line continues.

For scanning the neighbors, you can use two arrays with the offsets  
to the neighboring pixels
   X_OFFSET = newArray(  0,  1,  1,  1,  0, -1, -1, -1 );
   Y_OFFSET = newArray( -1, -1,  0,  1,  1,  1,  0, -1 );

and the loop over the neighbors would be roughly like this:
   for (i=0; i<8; i++) {
     if (firstPoint || x+X_OFFSET[i] != lastX || y+Y_OFFSET[i] !=  
lastY) {
       neighbor = getPixel(x+X_OFFSET[i], y+Y_OFFSET[i]);
       if (neighbor == 255) {
         //enter new coordinates into an array
       }
     }
   }
   // if no new coordinates are found, you are done.

Then you have the coordinates in a well-ordered list, and you can  
select part of it.

Michael
________________________________________________________________

On 7 Dec 2011, at 17:02, BROUILLY NICOLAS wrote:

> Dear list,
>
> I have a curved line (of 1 px width) obtained from skeletonise. And  
> I want to make it a segmented line of 14 key points (of known  
> coordinates) and made of 13 segments of the same length. To finally  
> be able to measure the angles between all these segments.
>
> Obviously I don't want to do it by hand…
>
> My first attempts were :
>
> 1. To do "Create selection" and "Area to line". But to do so I need  
> to dilate my selection and I don't want to. Plus it makes a U-
> shaped line with two parts in which the angles aren't exactly the  
> ones of the skeleton. And then I still need to extract the  
> coordinates of the 14 points.
>
> 2. To save my binary image as "Text image". This might work but I  
> don't know how to recover the coordinates of each 255 points and  
> make it a line.roi file. Plus, it might be complicated because I  
> may have several points for the same X or Y coordinate…
>
> To illustrate, i put two images :
> The first image is my raw image, the second one is the kind of  
> image I'd like to obtain. Actually, I even only need the  
> coordinates of the 13 points that are found along the original  
> curve. So it's a bit like 1. I want all the coordinates of each  
> white points along the curve in the raw image, 2. I want to know  
> the length L of this line in pixels, 3. I need to divide this  
> length by 13 (L/13=N), 4. obtain a number N and 5. gather the  
> coordinates of the 14 points separated by this number N of points  
> in my original image.
>
> I hope no-one asked this exact question before and that someone  
> will be able to guide me,
>
> Thank you !
>
> [cid:[hidden email]][cid:
> [hidden email]]
>
> Nicolas Brouilly, PhD Student
> Equipe Gieseler, "Pathologies du muscle chez C. elegans"
>
> Centre de Génétique et de Physiologie Moléculaires et Cellulaires
> UMR CNRS 5534
> Université Claude Bernard Lyon 1
> Bâtiment Gregor Mendel, 5ème étage
> 16, rue Raphaël Dubois
> F-69622 Villeurbanne Cedex
>
> [hidden email]<mailto:[hidden email]>
> Lab : +0033 (0)4 72 43 29 48
> Cel : +0033 (0)6 42 91 53 19
>
Reply | Threaded
Open this post in threaded view
|

Re: Skeleton to fragmented line selection

BROUILLY NICOLAS
Hi Michael and list members,

Thank you Michael for this help ! Your idea was the fastest one I think.

I followed your advice and ended with the following macro. The problem now is that I lose a point each time I have a new raw of aligned pixels (345 points of value 255 in the example image but only 283 values of X and Y coordinates in my final arrays) and I can't find from where this bug come…

The example image is attached.

And here is my macro :

// Close everything before you start

run("Close All")

// Be able to print an array

function printArray(a) {
      print("");
      for (i=0; i<a.length; i++)
          print(i+": "+a[i]);
  }

// Treat the image

open();
name=getTitle()
rename("Image1");
run("Make Binary");
run("Duplicate...", "title=[Image2]");
selectWindow("Image1");
run("Options...", "iterations=1 count=7 black edm=Overwrite do=Erode");
imageCalculator("Subtract create", "Image2","Image1");
selectWindow("Result of Image2");

// Get "Head" and "Tail" points

run("Find Maxima...", "noise=10 output=[Point Selection]");
getSelectionCoordinates(x, y);

HEADX=x[1];
HEADY=y[1];
TAILX=x[0];
TAILY=y[0];

// To know the length of the skeleton

selectWindow("Image1");
getHistogram(values, counts, 256);
INFO=newArray(counts[255]);
LENG=lengthOf(INFO);
print(LENG)
COORDX=newArray(LENG);
COORDY=newArray(LENG);

// To scan the neighboors

selectWindow("Image1");

X_OFFSET = newArray(  0,  1,  1,  1,  0, -1, -1, -1 );
Y_OFFSET = newArray( -1, -1,  0,  1,  1,  1,  0, -1 );

for (j=0; j<LENG; j++)  {

for (i=0; i<8; i++) {

    if (HEADX+X_OFFSET[i] != TAILX || HEADY+Y_OFFSET[i] != TAILY)
{
      neighbor = getPixel(HEADX+X_OFFSET[i], HEADY+Y_OFFSET[i]);
      if (neighbor == 255)
{
COORDX[j]=HEADX;
COORDY[j]=HEADY;
//print(HEADY+Y_OFFSET[i]);
setPixel(HEADX, HEADY, 100);
HEADX=HEADX+X_OFFSET[i];
HEADY=HEADY+Y_OFFSET[i];

}
}
     }

}

printArray(COORDX);
printArray(COORDY);


Thank you for any good advice (again).

Nico


Image 1.tif (26K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Skeleton to fragmented line selection

Michael Schmid
Hi Nico,

you after finding a new point, you have to quit (break) the inner loop
over i. Otherwise, it continues to search for neighbors from the new
position, and if the direction changes it may find a neighbor of the
neighbor.
Then it will write two points to the same array position, but, of course,
only one is kept.

if (neighbor == 255) {
  COORDX[j]=HEADX;
  COORDY[j]=HEADY;
  setPixel(HEADX, HEADY, 100);
  HEADX=HEADX+X_OFFSET[i];
  HEADY=HEADY+Y_OFFSET[i];
  i=8; // break (quit the loop)
}


Michael
___________________________________________________________________


On Sun, December 11, 2011 17:52, BROUILLY NICOLAS wrote:

> Hi Michael and list members,
>
> Thank you Michael for this help ! Your idea was the fastest one I think.
>
> I followed your advice and ended with the following macro. The problem now
> is that I lose a point each time I have a new raw of aligned pixels (345
> points of value 255 in the example image but only 283 values of X and Y
> coordinates in my final arrays) and I can't find from where this bug come…
>
> The example image is attached.
>
> And here is my macro :
>
> // Close everything before you start
>
> run("Close All")
>
> // Be able to print an array
>
> function printArray(a) {
>       print("");
>       for (i=0; i<a.length; i++)
>           print(i+": "+a[i]);
>   }
>
> // Treat the image
>
> open();
> name=getTitle()
> rename("Image1");
> run("Make Binary");
> run("Duplicate...", "title=[Image2]");
> selectWindow("Image1");
> run("Options...", "iterations=1 count=7 black edm=Overwrite do=Erode");
> imageCalculator("Subtract create", "Image2","Image1");
> selectWindow("Result of Image2");
>
> // Get "Head" and "Tail" points
>
> run("Find Maxima...", "noise=10 output=[Point Selection]");
> getSelectionCoordinates(x, y);
>
> HEADX=x[1];
> HEADY=y[1];
> TAILX=x[0];
> TAILY=y[0];
>
> // To know the length of the skeleton
>
> selectWindow("Image1");
> getHistogram(values, counts, 256);
> INFO=newArray(counts[255]);
> LENG=lengthOf(INFO);
> print(LENG)
> COORDX=newArray(LENG);
> COORDY=newArray(LENG);
>
> // To scan the neighboors
>
> selectWindow("Image1");
>
> X_OFFSET = newArray(  0,  1,  1,  1,  0, -1, -1, -1 );
> Y_OFFSET = newArray( -1, -1,  0,  1,  1,  1,  0, -1 );
>
> for (j=0; j<LENG; j++)  {
>
> for (i=0; i<8; i++) {
>
>     if (HEADX+X_OFFSET[i] != TAILX || HEADY+Y_OFFSET[i] != TAILY)
> {
>       neighbor = getPixel(HEADX+X_OFFSET[i], HEADY+Y_OFFSET[i]);
>       if (neighbor == 255)
> {
> COORDX[j]=HEADX;
> COORDY[j]=HEADY;
> //print(HEADY+Y_OFFSET[i]);
> setPixel(HEADX, HEADY, 100);
> HEADX=HEADX+X_OFFSET[i];
> HEADY=HEADY+Y_OFFSET[i];
>
> }
> }
>      }
>
> }
>
> printArray(COORDX);
> printArray(COORDY);
>
>
> Thank you for any good advice (again).
>
> Nico
>
>