Question

I am trying to fit a B-spline to a set of ordered discrete data points which represent pixels of a contour extracted from an image.

While the below code works fine for some simple shapes, but not for others (please see attached image for examples). Why does this happen, and what would be a better way to approach this problem?

I am quite new to differential geometry, appreciate any insights or inputs. Thanks.

% data contains two columns representing x,y coordinates of pixels
x = data(:, 1); 
y = data(:, 2); 
plot(x, y, 'bo');
fittedmodel = fit(x, y, 'cubicinterp');
plot(fittedmodel, 'r-');

example

Was it helpful?

Solution

What went wrong?

You have two sets of numbers x and y with the same number of elements in both sets.
You assume:
a. That there is a function f such that f( x_i ) = y_i for all pairs x_i,y_i in your sets.
b. That the points in the set are ordered: that is, if you follow the curve of f(x) then x_i "comes before" x_{i+1}.

While these assumptions hold for the "correct fit" example you have. They are no longer valid for the "incorrect fit" example.
As you can see for yourself, the input contour on the top cannot be expressed as y = f(x) since there are values of x for which there are two possible corresponding values of y (see the definition of mathematical function). The fit you got is the closest thing to a mathematical function y = f(x) that can be given the pairs x,y you gave (the red curve has the property of each x having only one y value).

What can you do?

In most cases when you try and fit a 2D curve you search for a parametric curve: that is, you introduce an auxilary parameter t such that each point along the curve can be represented as [x(t), y(t)] for some 0<=t<=1.
Now, if assumption b holds (and by looking at your examples, I'm not certain it is), what you can do is

 t = linspace( 0, 1, numel(x) ); % define the parameter t
 fitX = fit( t, x, 'cubicinterp'); % fit x as a function of parameter t
 fitY = fit( t, y, 'cubicinterp'); % fit y as a function of parameter t
 plot( fitX, fitY, 'r-' ); % plot the parametric curve
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top