jeff
jeff

Reputation: 13663

How to extend a set of points in MATLAB

Suppose I have the landmark points on a face, as follows :

enter image description here

and I want to calculate (estimate) the upper boundaries from them, by selecting the outer chin landmarks and extending them, so I want to achieve new points like this : enter image description here

So I want to "follow" the curve that is generated by points 1,2 and 3, and put equi-distant points on top, so that I can crop the image using the boundary function of MATLAB.

I guess I need to fit a 2nd order polynomial to the data points, but I'm not sure how. So how can I generate these points?

Thanks for any help,

Edit

Here are the coordinates of an example landmark set:

image: enter image description here

Landmarks (1:3 , i.e. left) :

   x         y  
431.1901  547.9975
438.7422  611.0103
451.4842  668.0488

Landmarks (17:-1:15 , i.e. right)

   x         y  
876.6581  509.5234
878.1327  568.9854
880.7731  619.5879

Edit 2

Here is a complete set of coordinates of the 17 chin landmarks:

   1.0e+03 *

    1.1974    1.3956
    1.2266    1.5488
    1.2554    1.6876
    1.2766    1.8245
    1.3266    1.9530
    1.4098    2.0648
    1.5420    2.1567
    1.6719    2.2222
    1.8180    2.2444
    1.9585    2.1991
    2.0642    2.1208
    2.1761    2.0351
    2.2575    1.9243
    2.3038    1.7937
    2.3191    1.6580
    2.3376    1.5264
    2.3537    1.3825

Upvotes: 2

Views: 219

Answers (1)

lhcgeneva
lhcgeneva

Reputation: 1981

You can use fit_ellipse() from File Exchange created by Ohad Gal.

You need to slightly modify it, so it also returns the plot handle which you are going to use to extract the data. For this, change the header to

function [ellipse_t, h] = fit_ellipse( x,y,axis_handle )

and add

     h = gca;

to the bottom of the file.

Then do

close all;
clear all;
landmarks = [1.1974    1.3956; 1.2266    1.5488; 1.2554    1.6876;
             1.2766    1.8245; 1.3266    1.9530; 1.4098    2.0648
             1.5420    2.1567; 1.6719    2.2222; 1.8180    2.2444
             1.9585    2.1991; 2.0642    2.1208; 2.1761    2.0351
             2.2575    1.9243; 2.3038    1.7937; 2.3191    1.6580
             2.3376    1.5264; 2.3537    1.3825];

[e, h] = fit_ellipse(landmarks(:, 1), landmarks(:, 2), gcf);
ch=get(h,'Children');
x=get(ch,'Xdata');
y=get(ch,'Ydata');
plot(x,y);
hold on;
x_l = landmarks(:, 1);
y_l = landmarks(:, 2);
plot(x_l, y_l);
m = min(landmarks(:, 2)); %Get the smallest y value from your landmarks
y_subset = y(y<m);
x_subset = x(y<m);
plot(x_subset, y_subset, 'r.', 'MarkerSize', 10)
axis equal;

which produces

enter image description here

Here, red points are your new sample points. Also note, that in your case obviously the y axis is inverted, because you are displaying an image. This does not change anything in the code though.

Alternatively, if speed is important: Comment out the draw section at the very bottom of fit_ellipse(). Change the function header to

function [ellipse_t, rotated_ellipse] = fit_ellipse( x,y )

and use the following code:

[e, r] = fit_ellipse(landmarks(:, 1), landmarks(:, 2));
x = r(1, :);
y = r(2, :);
x_l = landmarks(:, 1);
y_l = landmarks(:, 2);
m = min(landmarks(:, 2)); %Get the smallest y value from your landmarks
y_subset = y(y<m);
x_subset = x(y<m);

Upvotes: 3

Related Questions