Reputation: 13663
Suppose I have the landmark points on a face, as follows :
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 :
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,
Here are the coordinates of an example landmark set:
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
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
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
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