Počítačové vidění pro informatiku

Úloha druhá: Rekonstrukce obrazu
Autoři: Petr Přibyl, Jakub Heindrych, Radek Matouch


Obsah: Zadání
  Výběr bodů
  Určení fundamentální matice
  Výpočet epipólů a epipolár
  Rekonstrukce bodů scény
  extract.m a kostky.m - soubory se zdrojovým kódem



Zadání

Úkolem bylo provést rekonstrukci scény ze dvou obrazů. K dispozici jsme měli nástroj CORRGUI pro pohodlné nalezení korespondujících bodů a práce probíhala v prostředí Matlab 5.3 pro Windows. Po vyřešení úlohy bylo úkolem sestavit tuto zprávu. Jako výchozí pohledy kamer jsme použili následující dva obrazy:
prvni obraz druhy obraz



Výběr korespondujících bodů

Jak již bylo řešeno, k nalezení a určení bodů jsme použili nástroj CORRGUI. Body jsme bohužel zadávali dvakrát, neboť při prvním zadání 19 bodů jsme po delším bádání zjistili, že někde v postupu nastala chyba a bodu nejsou zaneseny a určeny správně. Při druhém pokusu jsme určili již jen 15 bodů, nicméně i tento počet se ukázal jako zcela postačující. Body jsme získali ze struktury uložené z programu CORRGUI následujícím kódem:

load kostky2.mat;
CORR = CORR_EXCHANGE;
points1 = CORR.d.corr(20:34,:,1);
points2 = CORR.d.corr(20:34,:,2);
q1 = points1;
q2 = points2;
Q1=[q1(:,1) q2(:,1)];
Q2=[q1(:,2) q2(:,2)];

Je nutno dodat, že tento kód je poskládaný z opraveného souboru extract.m a z našeho kódu. Výsledné souřadnice bodů jsou uloženy v maticích Q1(pro body z prvního obrázku) a Q2(pro body z druhého obrázku) Korespondující body leží vždy ve stejném řádku matic. Na následujících obrázcích jsou vidět body, které jsme zvolili pro určení korespondence.
prvni obraz druhy obraz



Určení fundamentální matice

Fundamentální matici F jsme spočetli nejprve pro 8 bodů a teprve potom pro všech 15 bodů, abychom mohli porovnat rozdíl. Ten byl značný, při použití všech patnácti bodů se vše znatelně zpřesnilo. Výsledky pro fundamentální matici určenou 8 body jsme však do zprávy nezahrnuli. Fundamentální matice musí splňovat následující rovnici:

ut.Q.u' = 0

Prvky fundamentální matice jsme získali jako nulový prostor matice M, jenž má následující tvar:
fundamentalni matice
Nulový prostor jsme určili pomocí SVD jako řešení rovnice

rovnice

Vlivem chyb a nepřesností má nalezená matice F hodnost 3, oproti požadované hodnosti 2. Toho docílíme svd rozkladem matice F, vynulováním nejmenšího singulárního čísla a opětovným složením (vynásobením) matic. Pro celý postup opět uvádím kód pro Matlab.

% vektor vybranych bodu
indexy = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19];

% soustava pro nalezeni prvku fundamentalni matice
matice = zeros(15,9);
for i=1:15
   matice(i,1) = Q1(indexy(i),1)* Q2(indexy(i),1);
   matice(i,2) = Q1(indexy(i),1)* Q2(indexy(i),2);
   matice(i,3) = Q1(indexy(i),1);
   matice(i,4) = Q1(indexy(i),2)* Q2(indexy(i),1);
   matice(i,5) = Q1(indexy(i),2)* Q2(indexy(i),2);
   matice(i,6) = Q1(indexy(i),2);
   matice(i,7) = Q2(indexy(i),1);
   matice(i,8) = Q2(indexy(i),2);
   matice(i,9) = 1;
end
[U, S, V] = svd(matice);

% vytvorime fundamentalni matici
F = reshape (V(:, 9), 3, 3)';
[U, S, V] = svd(F);
S(3,3) = 0;
F = U * S * V';




Výpočet epipólů a epipolár

Epipólje bod, v němž je na obraze vidět druhá kamera. Splňuje následující rovnice:

e1.F = 0
F.e2t = 0

Určení epipólů je o to jednodušší, že již máme provedený SVD rozklad fundamentální matice, stačí tedy vzít patřičné sloupce matic U a V a znormalizovat je třetí souřadnicí:

e1 = U(:, 3) ./ U(3, 3);
e2 = V(:, 3) ./ V(3, 3);

Epipoláry jsou přímky, které se při zobrazení kamerou zobrazí do jediného bodu. Při pohledu druhou kamerou je vidíme jako paprsky potínající se právě v epipólu. Naším úkolem bylo tedy spočítat rovnice epipolár pro zvolené body a zobrazir je do pohledu druhé kamery. Parametry přímek spočteme z rovnic

l1= F . u'
l2= u'T . F

Jakmile máme tyto paramtery, není problém z rovnice přímky dopočítat kde dvěma zvoleným x souřadnicím y a těmito dvěma body nechat projít přímku. Kód, který toto dělá pro první kameru uvedu zde, celý kód je možno si prohlédnout ve výpisu, jenž přikládám ke zprávě.

for i=1:15
   ep1 = F * [Q2(i, 1) Q2(i, 2) 1]';
   nula = [Q1(1, :) 1] * ep1;
   nula = 0;
   x1 = 0;
   x3 = 3000;
   y1 = (nula-ep1(3) - x1 * ep1(1)) / ep1(2);
   y3 = (nula-ep1(3) - x3 * ep1(1)) / ep1(2);
   line([x1 x3]', [y1 y3]');
end

Nakonec je možno zhlédnout výsledné obrázky:

obrazek s epipolarama
obrazek s epipolarama




Rekonstrukce bodů scény

Parametry kamery jsou známé, proto pouze načteme projekční matice kamer z externího souboru. Chceme-li nyní určit souřadnice bodů v prostoru, je nutno určit řešení následujících rovnic:

ai1.ui1= P1 . Xi
ai2.ui2= P2 . Xi

K řešení si sestavíme pomocnou matici A a řešení získáme jako její nulový prostor. Toto řešení je nutno dále normalizovat čtvrtou souřadnicí. Vše je opět vidět v kódu:

%nacteme projekcni matice obou kamer
load pointcal_mat;

% sestaveni matice pro nalezeni souradnic bodu v prostoru
matice2 = zeros(4,4);
body = zeros(15,3);
for i=1:15
  matice2(1, :) = [Q1(i,1) * P1(3, 1) - P1(1, 1)
    Q1(i,1) * P1(3, 2) - P1(1, 2)
    Q1(i,1) * P1(3, 3) - P1(1, 3)
    Q1(i,1) * P1(3, 4) - P1(1, 4)]';
  matice2(2, :) = [Q1(i,2) * P1(3, 1) - P1(2, 1)
    Q1(i,2) * P1(3, 2) - P1(2, 2)
     Q1(i,2) * P1(3, 3) - P1(2, 3)
     Q1(i,2) * P1(3, 4) - P1(2, 4)]';
  matice2(3, :) = [Q2(i,1) * P1(3, 1) - P2(1, 1)
    Q2(i,1) * P1(3, 2) - P2(1, 2)
    Q2(i,1) * P1(3, 3) - P2(1, 3)
    Q2(i,1) * P1(3, 4) - P2(1, 4)]';
  matice2(4, :) = [Q2(i,2) * P1(3, 1) - P2(2, 1)
    Q2(i,2) * P1(3, 2) - P2(2, 2)
     Q2(i,2) * P1(3, 3) - P2(2, 3)
     Q2(i,2) * P1(3, 4) - P2(2, 4)]';
  [U, S, V] = svd(matice2);
  body(i,:) = V(1:3, 4)' ./ V(4, 4);
end

Zbývá již jen tyto body zobrazit:

figure(2);
for i=1:15
  plot3(body(i,1), body(i,2), body(i,3), '*');
  hold on;
  grid on;
  axis equal;
end

Výsledkem celého postupu jsou body z rekonstruované scény: