Message Boards Message Boards

0
|
3987 Views
|
7 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Pruning removes an extra point

7 Replies

Hi Max,

In the end, I want to convert the line to a vector object, ...

I am not sure about your intention, but maybe this helps:

I start with an object like this (coming from the new and useful function Canvas):

enter image description here

Then I basically use ComponentMeasurements to calculate the data needed for a vector representation:

img = Binarize[Image @@ obj];
cm = ComponentMeasurements[ColorNegate[img], {"Centroid", "Orientation"}];
arrows = With[{v = {Cos[#2], Sin[#2]}, l = 25}, {#1 + l v, #1 - l v}] & @@@ cm[[All, 2]];
Show[img, Graphics[{Red, Arrow /@ arrows}]]

enter image description here

Liebe Gruesse ins schoene Freiburg! -- Henrik

POSTED BY: Henrik Schachner

Hello Max,

ahh, I see what you meant! Now - just as a footnote - here is another attempt (using your example array arr from above):

img = Image[arr, ImageSize -> 400];
pts = ImageValuePositions[img, 1];
endPts = ImageCorners[img, MaxFeatures -> 2];
{start, end} = Flatten[Position[pts, #] & /@ endPts];
order = Last@FindShortestTour[pts, start, end];
GraphicsColumn[{Show[img, Graphics[{Red, Thick, Line[pts[[order]]]}]],
   Show[img, Graphics[{Red, Thick, BSplineCurve[pts[[order]]]}]]}]

enter image description here

Maybe this is in a way helpful, regards -- Henrik

POSTED BY: Henrik Schachner

Hi Max, somehow your problem keeps me occupied! Here come two more ideas which - I think - can deal with branches. As test image I am using this image:

enter image description here

The first option is to use FindShortestTour and remove any resulting long jumps (the code should be self explaining):

testImg = << "testImg.txt";
pts = ImageValuePositions[testImg, 1];
ptso = pts[[Last@FindShortestTour[pts]]];
bigJumps = Select[MapIndexed[{First[#2], #1} &, 
    BlockMap[EuclideanDistance @@ # &, ptso, 2, 1]], Last[#] > 5 &];
splitIndx = First /@ bigJumps;
Set[ptso[[#]], "marker"] & /@ splitIndx;
ptso1 = SequenceSplit[ptso, {"marker"}];
Graphics[{Red, Thick, Line /@ ptso1}]

The other option is to "hijack" the function ImageGraphics, which results in a tightly enclosing line:

ig = ImageGraphics[testImg, Method -> "Exact"];
igPts = Cases[Normal[ig], FilledCurve[__], Infinity][[2, 1, 1, 1, 1]];
Manipulate[Graphics[{Line[igPts[[;; n]]]}, Frame -> True, 
  PlotRange -> CoordinateBounds[igPts]], {n, 1, Length[igPts], 1}]

Does that help? Regards -- Henrik

Attachments:
POSTED BY: Henrik Schachner

Hello Henrik,

the ImageGraphics function is generating the outline, but I want to trace the line itself from one end to the other. And although FindShortestTour is elegant, it is quite slow. I have tens of images with around 1000-2000 lines each. So ideally it should vectorize one line within tens of milliseconds. Less than a second is still acceptable.

In the end, the goal is to have a distribution of angles present in all the lines and see if there is a preference for a certain angle; so it is essential to smoothen the lines a bit to not only get 0°; 45° and 90°.

Max

enter image description here

Hi Max,

In the end, the goal is to have a distribution of angles present in all the lines and see if there is a preference for a certain angle;

OK - new attempt! Maybe you can use GradientOrientationFilter; the result is an image consisting of the directional gradient data, ranging between -Pi/2 and +Pi/2: these data can be examined statistically (let img be the image above):

cnImg = ColorNegate@img;
gof = GradientOrientationFilter[cnImg, 3];
Histogram[gof // ImageData // Flatten, PlotRange -> {All, {0, 30000}}]

enter image description here

The big bar in the middle is just the background; but you see that two directions seem to be prominent.

Does that now got into the right direction? Regards -- Henrik

POSTED BY: Henrik Schachner

Good evening Henrik, your code looks quite good and is very fast. I think the two prominent directions are artefacts though. If I rotate the image by a random value, the peaks remain where they are. Probably the gradient function treats certain angles with a preference. This is also true for my algorithm but not to that extent. If I play with the cutoff for the refinement of the subdivision (the value 0.5 in the function "splt"), the algorithm also allows bigger deviations from the exact line, therefore also more variations in the angle of the line. I assume it is indeed a difficult issue to get a true representation of the real angular distribution, i.e. the ground truth of the underlying data, which is what we try to obtain.

We use a SEM to look at structures on a cell surface and want to test the hypothesis that they are aligned with the orientation of the tissue. First, I obtained the outline of the structures with U-Net, then I determined their center line with SkeletonTransform and Thinning. Actually I did not really phrase it correctly previously; it is not so much about finding a preferential direction but more about determining if there is an alignment with the orientation of the tissue. For this image, the anterior/posterior axis of the sample is at 18 deg, counted from the horizontal direction counterclockwise. We would assume a preference of the structures to align either parallel or perpendicular to the axis.

Good night,

Max

enter image description here

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract