ČESKÉ VYSOKÉ UČENÍ TECHNICKÉ
fakulta elektrotechnická
Semestrální práce z předmětu
Počítačové vidění pro informatiku
Vypracovali: David Vilímek
Martin Šaroun
Martin Čadík
Zadání:
Pomocí Vámi zvolených bodů, určete fundamentální matici Q, epipóly, nakreslete epipoláry. Dále pomocí předložených matic z kalibrovaných kamer provést reprojekci rekonstruovaných bodů a pohled na 3D body. Poté z fundamentální matice spočtěte projektivní matice kamer a proveďte opět reprojekci. Odhadnět
e matici H a pomocí této matice transformujte body a vytvořte 3D pohled. Požijte program MATLAB.Řešení:
Vždy napíši nejprve teorii poté odpovídající kód a poté obrázky.
u1, u2..jsou vektory bodů v prvním a druhém pohledu
K1, K2..jsou kalibrační matice
kamerS(T), R.. jsou další matice určující postavení kamer
u1T*K1-T*S(T)*R-1*K2-1*u2=0
u1T*Q*u2=0
u1T*l 1=0, l 2*u2=0
(u1i, v1i, 1)*Q*(u2i, v2i, 1)T=0
(u1i* u2i, u1i* v2i, u1i, v1i* u2i, v1i* v2i, v1i, u2i, v2i, 1)* Q11
Q12
Q13
Q21
i=8 Q22 = 0
Q23
Q31
Q32
Q33
Stačí tedy 8 bodů.
Epipoláry
(u1i, v1i, 1)* l 1=0
u1i* l 11+ v1i *l 12+ l 13=0
x*a+y*b+c=0
load kostky2.cor -mat
a = CORR_EXCHANGE.d.corr;
u = [a(:,1,1) a(:,1,2) ones(12,1)]; %prvni obraz x,y - j, i
uc = [a(:,2,1) a(:,2,2) ones(12,1)]; %druhy obraz x,y - j, i
figure;
im1=(imread('k1.jpg'));
imshow(im1);
axis([-2000 2000 -2000 2000]);
hold;
plot(u(:,1),u(:,2),'*g');
hold off;
figure;
im2=(imread('k2.jpg'));
imshow(im2);
axis([-1000 1000 -1000 1000]);
hold;
plot(uc(:,1),uc(:,2),'*g');
hold off;
count = size(u,1);
A=[u(:,1).*uc(:,1), u(:,1).*uc(:,2), u(:,1), u(:,2).*uc(:,1), u(:,2).*uc(:,2), u(:,2), uc(:,1), uc(:,2), ones(size(u,1),1)];
[U,S,V] = svd(A);
S(9,9) = 0;
A2 = U*S*V';
% vypocet Q
q = null(A2);
Q = reshape(q, [3 3])';
[ux,s,v] = svd(Q);
s(3,3) = 0;
Qsvd = ux*s*v';
u1=[u(:,2) u(:,1) ones(size(u,1),1)];
uc1=[uc(:,2) uc(:,1) ones(size(uc,1),1)];
lambda1 = []; %v prvnim obrazku
lambda2 = []; %v druhem obrazku
for i = 1:count
lambda1 = [lambda1; (Q*uc(i,:)')'];
lambda2 = [lambda2; u(i,:)*Q];
end;
b1 = [];
b2 = [];
k = 5000;
for i = 1 : count
b1 = [b1 [k; -k]]; %x1 x2
b2 = [b2 [-(lambda1(i,3)+k*lambda1(i,1))/lambda1(i,2); -(lambda1(i,3)-k*lambda1(i,1))/lambda1(i,2)]]; %y1 y2
end
figure(1);
hold on;
axis([0 2600 0 700]);
axis on;
plot(b1, b2);
e1 = null(Qsvd');
e1 = e1/e1(3,1);
plot(e1(1,1),e1(2,1),'k*');
b1 = [];
b2 = [];
k = 5000;
for i = 1 : count
b1 = [b1 [k; -k]]; %x1 x2
b2 = [b2 [(-lambda2(i,3)-k*lambda2(i,1))/lambda2(i,2); (-lambda2(i,3)+k*lambda2(i,1))/lambda2(i,2)]]; %y1 y2
end
figure(2);
hold on;
axis([0 1600 -100 600]);
axis on;
plot(b1, b2);
e2 = null(Qsvd);
e2 = e2/e2(3,1);
plot(e2(1,1),e2(2,1),'k*');
Nyní reprojekce "do světových" souřadnic se zadaných matic pro kamery a zobrazení 3D
a 1*u1=P1*X
a 2*u2=P2*X
My počítáme X
load pointcal_mat;
A1 = P1(1:3, 1:3);
b1 = P1(:, 4);
A2 = P2(1:3, 1:3);
b2 = P2(:, 4);
A11 = inv(A1);
A22 = inv(A2);
u1=[u1(:,2) u1(:,1) u1(:,3)];
uc1=[uc1(:,2) uc1(:,1) uc1(:,3)];
X1 = [];
X2 = [];
for i = 1:count
Au1 = A11 * u1(i,:)';
Ab1 = A11 * b1;
Au2 = A22 * uc1(i,:)';
Ab2 = A22 * b2;
LEFT = [ Au1'*Au1, -Au2'*Au1; Au1'*Au2, -Au2'*Au2 ];
RIGHT = [ (Ab1'-Ab2')*Au1; (Ab1'-Ab2')*Au2 ];
alphas = inv(LEFT) * RIGHT;
X1 = [ X1; [alphas(1) * Au1 - Ab1; 1]' ];
X2 = [ X2; [alphas(2) * Au2 - Ab2; 1]' ];
end;
%presny bod jako prumer obou prumetu
X = (X1 + X2) / 2;
figure(3);
plot3(X(:,1), X(:,2), X(:,3), '*');
grid on;
axis equal;
%normalizace na 3.slozku == 1
newPoints1 = ( (P1*X') ./ ([1;1;1]*[P1(3,:) * X']) )';
newPoints2 = ( (P2*X') ./ ([1;1;1]*[P2(3,:) * X']) )';
%zobrazeni pretransformovanych bodu
%pause;
figure(1);
hold on;
plot(newPoints1(:,1),newPoints1(:,2),'y*'); % zobrazeni bodu
figure(2);
hold on;
plot(newPoints2(:,1),newPoints2(:,2),'y*'); % zobrazeni bodu
3D pohled na body
Máme u1, u2
, tak že platí a 1*u1=P1*X, a 2*u2=P2*X a fundamentální matici Qu1T*Q*u2=0
(P1*Xi)T*Q*(P2*Xi)=0
Xi T *P1 T *Q*P2*Xi=0
a 1i*u1i=P1*Xi=(I3|O3)*Xi
a 2i*u2i=P2*Xi
Xi T *(I3|O3)T *Q*P2*Xi=0
Xi =(x T x ) T , P2=(A | b), b =e2
(x T x ) *(I3|O3)T *Q*(A | b)* (x T x ) T =0
x T*Q*A* x + x T*Q*b*x =0
x T*Q*A* x =0
pak Q*A je antisymetrická
q1
q2
q3 a1 a1
q2 q1 a2 =0, W* a2 =0, hod(W)=5
q3 q2 a3 a3
q3 q1
%volba P1 = [ I3 O3 ]
myP1 = [1 0 0 0;
0 1 0 0;
0 0 1 0 ];
%vypocet P2 = [ A b ] ---
myb = e2; % e2 = P1 * c1 = b
%sestaveni matice W
f1 = Q(1, :);
f2 = Q(2, :);
f3 = Q(3, :);
f0 = zeros(1, 3); %same nuly
W = [ f1 f0 f0;
f0 f2 f0;
f0 f0 f3;
f2 f1 f0;
f0 f3 f2;
f3 f0 f1 ];
%vypocet pomocne matice A pomoci SVD z W
[ U, D, V ] = svd(W);
pomA = V(:, 6:9); %baze W (9x4), matice A (jako radkovy vektor) je LK radkovych vektoru teto baze
%vypocet nejvhodnejsich koeficientu (alfa) pro zisk A - chceme co nejmene singularni => male rozdily v singul. cislech
%zkousime maxRuns-krat nahodne volit koeficienty, bereme nejlepsi
maxRuns = 1000; %kolikrat zkousim
koef = rand(4,1); %nahodne koeficienty (4x1)
testA = pomA * koef; %dosud nejlepsi matice
myA = reshape(testA, 3, 3);
D = svd(myA); %!vraci vektor singul. cisel (diagonalu D)
bestRegul = D(end)/D(1); %dosud nejlepsi hodnota singularity (chceme co nejblizsi nejmensi a nejvetsi cislo-hodnoty na diag klesaji
for i=1:maxRuns
koef = rand(4,1);
testA = pomA * koef;
testA = reshape(testA, 3, 3);
D = svd(testA);
pomRegul = D(end)/D(1);
if (pomRegul > bestRegul)
bestRegul = pomRegul;
myA = testA;
end;
end;
%sestaveni P2
myP2 = [ myA myb ];
A1 = myP1(1:3, 1:3);
b1 = myP1(:, 4);
A2 = myP2(1:3, 1:3);
b2 = myP2(:, 4);
A11 = inv(A1);
A22 = inv(A2);
%vypocet bodu "ve svete" z rovnice - viz papir (bez nej ani ranu)
X1 = [];
X2 = [];
for i = 1:count
Au1 = A11 * u1(i,:)';
Ab1 = A11 * b1;
Au2 = A22 * uc1(i,:)';
Ab2 = A22 * b2;
LEFT = [ Au1'*Au1, -Au2'*Au1; Au1'*Au2, -Au2'*Au2 ];
RIGHT = [ (Ab1'-Ab2')*Au1; (Ab1'-Ab2')*Au2 ];
alphas = inv(LEFT) * RIGHT;
X1 = [ X1; [alphas(1) * Au1 - Ab1; 1]' ];
X2 = [ X2; [alphas(2) * Au2 - Ab2; 1]' ];
end;
%presny bod jako prumer obou prumetu
myX = (X1 + X2) / 2;
newPoints1 = ( (myP1*myX') ./ ([1;1;1]*[myP1(3,:) * myX']) )';
newPoints2 = ( (myP2*myX') ./ ([1;1;1]*[myP2(3,:) * myX']) )';
%zobrazeni pretransformovanych bodu
%pause;
figure(1);
hold on;
plot(newPoints1(:,1),newPoints1(:,2),'r*'); % zobrazeni bodu
figure(2);
hold on;
plot(newPoints2(:,1),newPoints2(:,2),'r*'); % zobrazeni bodu
A jako poslední
spočteme matici H a to zm i*X1i=H*X2i
X = X(2:6,:);
myX = myX(2:6,:);
Z = [];
move = 0;
%pro pet bodu
for i = 1:5
bod = move + i;
rX = X(bod, :); %bod ve scene - radkovy vektor
smyX = -myX(bod, :)';%bod v rekonstrukci - sloupcovy vektor
rZ = zeros(1,4); %nuly v radku
sZ = zeros(4,1); %nuly ve sloupci
left = [];
right = [];
%pro pet sloupcu leve
for j = 1:5
if (i == j)
left = [left, smyX];
else
left = [left, sZ];
end;
end;
%pro ctyri ctyr-sloupce prave
for j = 1:4
columnRight = [];
%pro ctyri radky prave
for k = 1:4
if (j == k)
columnRight = [ columnRight; rX ];
else
columnRight = [ columnRight; rZ ];
end;
end;
right = [right, columnRight];
end;
Z = [ Z; [left, right] ];
end;
% vypocet mi-cek a matice H
test = null(Z);
mis = test(1:5);
H = reshape(test(6:21), 4, 4)';
% prepocet nasi rekonstrukce do sceny pomoci H matice ---------------------------------
%vypocet realXi = inv(H) * MIi * myXi pro body, pro ktere mame MIi
myRealX = [];
for i = 1:size(mis)
bod = move + i;
newX = inv(H) * mis(i) * (myX(bod,:)');
myRealX = [ myRealX; newX' ];
end;
%zobrazeni vypoctenych bodu
figure(3);
hold on;
plot3(myRealX(:,1), myRealX(:,2), myRealX(:,3), 'g*');
% zobrazeni nasich bodu v realnem svete (transformaci pres H) zpet realnymi kamerami ----------
% prepocet bodu (alfa*u = P*X1) s normalizaci na 3.slozku == 1
newPoints1 = ( (P1*myRealX') ./ ([1;1;1]*[P1(3,:) * myRealX']) )';
newPoints2 = ( (P2*myRealX') ./ ([1;1;1]*[P2(3,:) * myRealX']) )';
%zobrazeni pretransformovanych bodu
figure(1);
hold on;
plot(newPoints1(:,1),newPoints1(:,2),'m*'); % zobrazeni bodu
figure(2);
hold on;
plot(newPoints2(:,1),newPoints2(:,2),'m*'); % zobrazeni bodu
Závěr:
Pro dva jednoduché obrazy jsme pomocí fundamentální matice Q popsali epipolární geometrii scény. Z této matice jsme následně vypočítali epipolární čáry a epipóly, které jsme zobrazili
do grafu, viz výše.Dále jsme provedli rekonstrukci scény pomocí korespondujících bodů a poté následnou reprojekci. Reprojekce ze zadaných matic P
i (ze zkalibrovaných kamer) je velice přesná na rozdíl od reprojekce získané pomocí námi vypočtených matic, kde si správně odpovídá pětice bodů, ze kterých je matice H získána, ostatní body mají drobné odchylky, jejichž velikost je závislá např. na volbě korespondečních bodů.Proto jsme poté zkoumali závislost odchylek na volbě vstupních bodů. Je zřejmé, že odchylka velice roste v případě, že mezi vstupními body je takový, jehož souřadnice jsou zadány s hrubou nepřesností, a to i pro ostatní body zadané relativně přesně.