Get (x, y) points from the image pixel positions
curve = Import["https://i.sstatic.net/WG8W9.png"];
Get points from the image. For RGB images, use PixelValuePositions
and Black to locate pixel positions, or use 0 with single-channel images.
(*for RGB images*)
xy = DeleteDuplicatesBy[
NumericalSort[PixelValuePositions[curve, Black, .5]], First];
(*for single-channel images*)
curve2 = ColorSeparate[curve, "I"];(*make a 1-channel image*)
xy = DeleteDuplicatesBy[
NumericalSort[PixelValuePositions[curve2, 0, .5]], First];
Demonstrate various methods to fit a model to the (x, y) data
1. Use FindFormula to make a piece-wise fit
fit = FindFormula[xy, x, TargetFunctions->{Times, Plus, Power}];
Show[{ListLinePlot[xy],
Plot[fit, {x, Min[First/@xy], Max[First/@xy]},
PlotStyle->Red]}]
2. Assuming a circle fits the (x, y) data, use three points to find the center and radius
pts = xy[[{1, Round@Length[xy]/2, -1}]]
(*{{34, 78}, {156, 175}, {279, 78}}*)
circle = CircleThrough[pts];
center = RegionCentroid[circle];
radius = Last@circle;
Graphics[{circle,
Point[xy],
PointSize[Scaled[.02]], Blue, Point[center], Red, Point[pts]}]
3. Use Bspline and Bezier modeling
Find a function definition with BSplineFunction
:
f = BSplineFunction[xy];
Show[{Graphics[{Point[xy], PointSize[Scaled[.02]]}],
ParametricPlot[f[t], {t, 0, 1}, PlotStyle->Red]}]
Or use BezierCurve
to plot a spline curve:
Graphics[{Point[xy], Red, BezierCurve[xy]}]
4. Fitting using Fit, FindFit, etc.
Demonstrate Fit
using quadratic and quartic models
quad = Fit[xy, {1, x, x^2}, x]
(*25.3532 + 1.72048x - 0.00950413 x^2*)
quart = Fit[xy, {1, x, x^2, x^3, x^4}, x]
(*-17.13974517615123 + 4.458526401451207 x - 0.0657189150882205 x^2 + 0.00045398967260661826 x^3 - 1.2540520088334156*^-6 x^4*)
{x1, xn} = First/@xy[[{1, -1}]];
Show[ListPlot[xy, PlotStyle->Black],
Plot[{quad, quart}, {x, x1, xn}, PlotStyle->{{Thick, Red}, {Thick, Blue}}]]
5. LinearModelFit provides information that compares the fitted models
lm1 = LinearModelFit[xy, {1, x, x^2}, x];
lm1[{"BestFit", "RSquared", "ANOVATable"}] // Column
lm2 = LinearModelFit[xy, {1, x, x^2, x^3, x^4}, x];
lm2[{"BestFit", "RSquared", "ANOVATable"}] // Column
{x1, xn} = First/@xy[[{1, -1}]];
Show[ListPlot[xy, PlotStyle->Black],
Plot[{lm1[x], lm2[x]}, {x, x1, xn}, PlotStyle->{{Thick, Red}, {Thick, Blue}}]]