Playing with conic sections in homogeneous coordinates

Contents

Preparation

First, we create an empty image and display it (will be our "canvas")

figure(1)
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,100,'filled');
click 5 points, then enter

x and y are now column vectors.

x
y
x =

  196.0000
  432.0000
  341.0000
  144.0000
   94.0000


y =

  146.0000
  253.0000
  399.0000
  282.0000
  182.0000

Estimation of conic parameters

using the technique shown in "Multiple View Geometry", page 9. questo equivale ad impostare il sistema lineare in cui la conica passa per 5 punti

A=[x.^2 x.*y y.^2 x y ones(size(x))]

% 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.
N = null(A);
A =

   1.0e+05 *

    0.3842    0.2862    0.2132    0.0020    0.0015    0.0000
    1.8662    1.0930    0.6401    0.0043    0.0025    0.0000
    1.1628    1.3606    1.5920    0.0034    0.0040    0.0000
    0.2074    0.4061    0.7952    0.0014    0.0028    0.0000
    0.0884    0.1711    0.3312    0.0009    0.0018    0.0000

Let's assign the values to variables and build the 3x3 conic matrix (which is symmetrical)

cc = N(:, 1);
[a b c d e f]=deal(cc(1),cc(2),cc(3),cc(4),cc(5),cc(6));
% here is the matrix of the conic
C=[a b/2 d/2; b/2 c e/2; d/2 e/2 f]

% Remark: since the right null space has dimension one,
% the system admits an infinite number of solutions
% however, these can be expressed as lambda * n, where n
% lambda \in R and n = null(A).
% thus, they all corresponds to the same conic.
C =

    0.0000   -0.0000   -0.0003
   -0.0000    0.0000   -0.0044
   -0.0003   -0.0044    1.0000

Draw the conic

We pick every pixel, and compute the incidence relation.

im=zeros(500,500);
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.

figure(1)
imshow(im > 0);
scatter(x,y, 100, 'filled');

N.B: if we provide only 4 points, N is a matrix

which contains in each column a generator of the null space

N = null(A(1 : 4, :));

% then, any vector living in the null space give rise to a conic
% passing throguh those 4 points

Let's assign the values to variables and build the 3x3 conic matrix (which is symmetrical)

cc = N(:, 2);
% cc = N(:, 1) + N(:, 2); % another example, any linear combination is fine
[a b c d e f]=deal(cc(1),cc(2),cc(3),cc(4),cc(5),cc(6));
% here is the matrix of the conic
C_four =[a b/2 d/2; b/2 c e/2; d/2 e/2 f]
C_four =

    0.0000    0.0000   -0.0030
    0.0000   -0.0000   -0.0011
   -0.0030   -0.0011    1.0000

Draw the conic

We pick every pixel, and compute the incidence relation.

im_four=zeros(500,500);
for i=1:500
    for j=1:500
        im_four(i,j)=[j i 1]*C_four*[j i 1]';
    end
end

figure(2),
imshow(im_four > 0);
hold on
scatter(x(1 : 4), y(1 : 4), 100, 'filled');
hold off

Tangent lines

Let's draw the tangents to our points: the tangent line in homogeneous coordinates is l the line tangent to C at the line x is defined as l = C*x

% this is the line tangent to the first point
l1 = C * [x(1); y(1); 1];
% here I compute all the tangent lines simultaneously
% stacking all the vectors in the columns of the matrix l
l=C*[x y ones(size(x))]'
l =

    0.0003    0.0019   -0.0010   -0.0019   -0.0013
   -0.0025   -0.0023    0.0029    0.0019   -0.0003
    0.3081   -0.2258   -0.8345   -0.2685    0.1810

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,:));
theta = theta';
figure(1), hold on
plot([x-cos(theta)*100 x+cos(theta)*100]',...
    [y-sin(theta)*100 y+sin(theta)*100]','b-','LineWidth',5);

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 =

  -2.7756e-16


ans =

  -2.8866e-15


ans =

  -1.1102e-16


ans =

   7.7716e-16


ans =

   6.3838e-16