Playing with conic sections in homogeneous coordinates
Contents
Preparation
First, we create an empty image and display it (will be our "canvas")
im=zeros(500,500);
imshow(im);
hold on;
Data input: enter five points (then enter)
disp('click 5 points, then enter'); [x y]=getpts; scatter(x,y,25,'filled');
click 5 points, then enter
x and y are now column vectors.
x y
x = 193.0000 95.0000 126.0000 214.0000 402.0000 y = 351.0000 250.0000 132.0000 105.0000 272.0000
Estimation of conic parameters
using the technique shown in "Multiple View Geometry", page 31.
A=[x.^2 x.*y y.^2 x y ones(size(x))]
A =
1.0e+05 *
Columns 1 through 5
0.3725 0.6774 1.2320 0.0019 0.0035
0.0902 0.2375 0.6250 0.0009 0.0025
0.1588 0.1663 0.1742 0.0013 0.0013
0.4580 0.2247 0.1102 0.0021 0.0010
1.6160 1.0934 0.7398 0.0040 0.0027
Column 6
0.0000
0.0000
0.0000
0.0000
0.0000
A is 5x6: we find the parameter vector (containing [a b c d e f]) as the right null space of A. This returns a vector cc such that A*cc=0. Note that this expresses the fact that the conic passes through all the points we inserted.
cc=null(A);
Let's assign the values to variables and build the 3x3 conic matrix (which is symmetrical)
[a b c d e f]=deal(cc(1),cc(2),cc(3),cc(4),cc(5),cc(6)); C=[a b/2 d/2; b/2 c e/2; d/2 e/2 f]
C =
0.0000 -0.0000 -0.0021
-0.0000 0.0000 -0.0031
-0.0021 -0.0031 1.0000
Draw the conic
We pick every pixel, and compute the incidence relation.
for i=1:500 for j=1:500 im(i,j)=[j i 1]*C*[j i 1]'; end end
Let's draw black for pixels less than zero, white for pixels greater than 0.
imshow(im>0);
scatter(x,y,25,'filled');
Improvements
Let's draw the tangents to our points: the tangent line in homogeneous coordinates is l
l=C*[x y ones(size(x))]'
l =
-0.0009 -0.0018 -0.0011 0.0000 0.0017
0.0020 0.0006 -0.0014 -0.0021 0.0001
-0.5162 0.0111 0.3153 0.2114 -0.7161
in order to draw it we find its angle, then plot a line of length 200 around it. In order to write less lines of code, I'm doing a bit of hacks with matrices and vectors here: theta will be a column vector of angles, and with a single plot command I'll plot all the lines. Check out the documentation of plot to understand what's happening.
theta=atan2(-l(1,:),l(2,:)) plot([x-cos(theta')*100 x+cos(theta')*100]',[y-sin(theta')*100 y+sin(theta')*100]','b-','LineWidth',5);
theta =
0.4356 1.2299 2.4781 -3.1321 -1.5074
Let's also draw the pole of the line at the infinity w.r.t. the conic.
linf=[0 0 1]';
center=inv(C)*linf;
center=center/center(3);
scatter(center(1),center(2),25,'filled');
Let's compute the dual conic and check that all the tangent lines we computed previously actually satisfy the relation (up to numeric precision issues).
Cstar=inv(C); l(:,1)'*Cstar*l(:,1) l(:,2)'*Cstar*l(:,2) l(:,3)'*Cstar*l(:,3) l(:,4)'*Cstar*l(:,4) l(:,5)'*Cstar*l(:,5)
ans = 1.1102e-16 ans = 4.1633e-16 ans = -2.7756e-16 ans = -8.3267e-17 ans = 1.1449e-16