Message Boards Message Boards

0
|
6091 Views
|
8 Replies
|
1 Total Likes
View groups...
Share
Share this post:

[?] Fit a cubic spline to the centerline data points?

Posted 4 years ago

I've the following image,

enter image description here

I'm using ImageGraphics command to obtain the data points of the centerline in the above image. However, the output contains disconnected pixels. I would like to generate a smoothed output image and fit a cubic spline to the data points for importing into CAD. Could someone suggest how this can be done?

POSTED BY: Natash A
8 Replies

Hi Natash,

well, yes, of course, qua construction there are discontinuities:

Manipulate[
 Graphics[BezierCurve /@ cleanLinePoints[[;; n]], 
  PlotRange -> {{0, 550}, {0, 160}}, ImageSize -> Large], {n, 1, 
  Length[cleanLinePoints], 1}]

enter image description here

As described above my approach was to create a single line (using FindShortestTour) and to delete the jumps then. One can change the outcome of FindShortestTour by choosing a different order of the points which go into this function. You just have to play around a bit; I found using e.g.

pixelPos = SortBy[pixelPos, EuclideanDistance[{100, 100}, #] &];
order = Last[FindShortestTour[pixelPos]];

a somewhat better partitioning:

enter image description here

Try to be ceative!

POSTED BY: Henrik Schachner

Hi Natash,

sorry, my bad, I did not meant to use BezierCurve, but:

graphics = Graphics[BSplineCurve /@ cleanLinePoints]

But this does not make any difference; given your input data (a coarse grained image), the curves (along the line of pixels) are as smooth as they can be. And because we have a vector graphic here, it does not make much sense to apply filters for images. But since you are starting the whole procedure from an image, you maybe should try to get a clean high quality image for this first.

Regarding the export - does

mgr = DiscretizeGraphics[graphics];    
Export["foo.dxf", mgr]

work for you?

POSTED BY: Henrik Schachner
Posted 4 years ago

Hi Henrik,

Thanks a lot. The dxf export works well. However, I see some discontinuities in the geometry created after importing dxf file.enter image description here

I observe these discontinuities in the output of graphics = Graphics[BSplineCurve /@ cleanLinePoints] too.

I am also attaching the original image that I started with (here) for your kind reference. The image presented in the very beginning of this post is the centerline of a section of the original image.

POSTED BY: Natash A
Posted 4 years ago

Hi Henrik,

Thanks a lot for the detailed illustration, I tried to smooth the curves obtained in the final output by doing the following

out =  Graphics[BezierCurve /@ cleanLinePoints]
smooth = Erosion[CurvatureFlowFilter[Dilation[out, 1], 10], 1]

If my understanding is correct, cleanLinePoints contains the [x,y] coordinate positions of the white pixels. Could you please suggest how this can be exported in DXF format? I would like to import the DXF format in CAD to create a 3D geometry.

Also, I would like to know how to fit a cubic spline to the data points (x,y coordinates).

POSTED BY: Updating Name

Hi Natash,

I think you would rather need ImageMesh:

img = Binarize@
   Import["https://community.wolfram.com//c/portal/getImageAttachment?filename=ske3.png&userId=1555685"];

mesh = ImageMesh[img]

enter image description here

From this BoundaryMeshRegion line segments can be extracted (and viewed):

lines = MeshPrimitives[mesh, 1];

Manipulate[
 Graphics[lines[[;; n]], PlotRange -> {{0, 550}, {0, 160}}], {n, 1, Length[lines], 1}]

Obviously this structure is regarded as a two dimensional thing, and consequently the lines describe its boundary (and appear to run around twice ...). Furthermore some elements of the image border were detected.

enter image description here

But it should not be difficult to select the needed parts.

Does that help? Regards -- Henrik

Addendum/Edit:

Here comes a better solution: I start by cleaning up you original image by padding, then I calculate the positions of the white pixels. The problem now is that they are not ordered along a line. This can be improved by using FindShortestTour. Now the problem is that this gives a single line and there are necessarily jumps.

img1 = ImagePad[img, -1];
pixelPos = PixelValuePositions[img1, 1];
order = Last[FindShortestTour[pixelPos]];
Graphics[Line[pixelPos[[order]]]]

enter image description here

But with a little effort those long distances between two successive points can be detected and eliminated (... most likely there is a more elegant way of doing this):

longLineIndex = 
  Select[MapIndexed[{First[#2], EuclideanDistance @@ #1} &, 
     Partition[pixelPos[[order]], 2, 1]], Last[#] > 10 &][[All, 1]];
lineSequenceIndex = Partition[Join[{1}, longLineIndex, {Length[order]}], 2, 1];
lineSequenceIndex = Join[{lineSequenceIndex[[1]]}, {#1 + 1, #2} & @@@ lineSequenceIndex[[2 ;;]]];
cleanLinePoints = pixelPos[[order]][[Span @@ #]] & /@ lineSequenceIndex;
Graphics[BezierCurve /@ cleanLinePoints]

enter image description here

POSTED BY: Henrik Schachner
Posted 4 years ago

Sorry, I understand BeizierCurve command is used to fit a polynomial. But I am not sure how the degree of the polynomial is defined here. I'd like to fit a cubic spline. I'd also like to know how the splines can be exported.

POSTED BY: Natash A
Posted 4 years ago

Sorry, I understand BeizierCurve command is used to fit a polynomial. But I am not sure how the degree of the polynomial is defined here. I'd like to fit a cubic spline. I'd also like to know how the splines can be exported for importing in CAD.

POSTED BY: Natash A
Posted 4 years ago

Crossposted here.

POSTED BY: Rohit Namjoshi
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