Vision tridimensionelle

Pour supprimer les avertissements énervants...

Off[General::spell1]

Soit le modele de camera suivant (en geometrie projective):

Voici comment illustrer ce modele de camera en 3D.

Fonctions de base

Dans cette section, on declare les fonction de base qui sont utilisee souvent.

Extraire une sous-matrice

sousmatrice[m_, r1_, r2_, c1_, 
          c2_] := Take[#, {c1, c2}] &   /@  
          Take[m, {r1, r2}];

m = Partition[Table[i, {i, 1, 16}], 4]; m // MatrixForm

sousmatrice[m, 1, 3, 2, 4] // MatrixForm

sousmatrice[m, 1, 3, 1, 3] // MatrixForm

sousmatrice[m, 1, 3, 4, 4] // MatrixForm

Matrice de changement d'echelle 3D (4x4)

scaleMatrix[v_] := DiagonalMatrix[{v, v, v, 1}];

scaleMatrix[{sx_, sy_, sz_}] := 
        DiagonalMatrix[{sx, sy, sz, 1}];

scaleMatrix[a] // MatrixForm

scaleMatrix[{a, b, c}] // MatrixForm

Matrice de translation 3D (4x4)

transMatrix[v_] := 
        Transpose[{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, 
            Append[v, 1]}];

transMatrix[{a, b, c}] // MatrixForm

Matrice de rotation arbitraire 3D (4x4)

\(\(rotMatrix[a_, u_] := 
        Block[{m, s, x, y, z, 
            nu}, \((
\ \ \ \ \ \ \ \ {x, y, z} = 
              u/Sqrt[u . u]; 
\ \ \ \ \ \ \ \ s = {{0, \(-z\), y}, {z, 
                  0, \(-x\)}, {\(-y\), x, 
                  0}}; 
\ \ \ \ \ \ \ \ nu = {{x}, {y}, {z}}; 
\ \ \ \ \ \ \ \ m = nu . Transpose[nu] + 
                Cos[a] \((IdentityMatrix[3] - nu . Transpose[nu])\) + 
                Sin[a] s; 
\ \ \ \ \ \ 
\ \ \ \ \ \ \ \ Join[\(Append[#, 
                    0] &\)\  /@ \ 
                m, {{0, 0, 0, 1}}]
\ \ \ \ \ \ \ \ )\)];\)\)

\({rotMatrix[a, {1, 0, 0}] // MatrixForm, 
	
      rotMatrix[a, {0, 1, 0}] // MatrixForm, 
	
      rotMatrix[a, {0, 0, 1}] // MatrixForm}\)

Matrice de parametres internes (passe de camera -> image)

Centre de l'image (cx,cy), distance focal (fx,fy)

internMatrix[cx_, cy_, fx_, 
          fy_] := {{fx, 0, cx, 0}, {0, fy, cy, 0}, {0, 0, 1, 0}, {0, 0, 0, 
            1}};

internMatrix[128, 128, 256, 256] // MatrixForm

Homogenize (passe de projectif a euclidien)

h[v_] := Delete[v, -1]/v[[-1]];

h[{x, y, h}]

h[{x, y, z, h}]

Projection d'un point 3D vers un point 2D

La matrice m peut etre une 3x4 ou 4x4

projete[{x_, y_, z_}, m_] := 
        h[Take[m . {x, y, z, 1}, 3]];

Graphiques

Creation d'une systeme d'axe (x,y,z)

axes[] := axes[IdentityMatrix[4]];

\(axes[rt_] := 
      Module[{p, q, 
            r}, \((
			p = {{0, 0, 0, 1}, {1, 0, 0, 1}, {0, 1, 0, 1}, {0, 
                  0, 1, 1}}; 
			q = \(\((h[rt . #])\) &\)\  /@ \ 
                p; 
			r = \(\((h[
                      rt . scaleMatrix[{1.1, 1.1, 1.1}] . #])\) &\)\  /@ \ 
                p; 
			Graphics3D[{
			Thickness[0.015], 
			Line[
                  q[\([{1, 2}]\)]], 
			Line[
                  q[\([{1, 3}]\)]], 
			Line[
                  q[\([{1, 4}]\)]], 
			Text["X", 
                  r[\([2]\)]], 
			Text["Y", 
                  r[\([3]\)]], 
			Text["Z", 
                  r[\([4]\)]]
			}]
		)\)]\  /; \ 
        Dimensions[rt] == {4, 4}\)
axes[rt_] := 
      axes[Append[rt, {0, 0, 0, 1}]]  /;  
        Dimensions[rt] == {3, 4}

Show[axes[]];

\(\(Show[axes[], 
	
        axes[transMatrix[{1, 1, 1}] . rotMatrix[Pi/4, {1, 0, 0}]], 
	
        axes[transMatrix[{2, 0, 1}] . rotMatrix[Pi/4, {0, 1, 1}] . 
            scaleMatrix[{0.5, 0.5, 0.2}]], 
\ \ \ \ \ axes[
          Take[transMatrix[{1, 0, 3}] . rotMatrix[\(-Pi\)/4, {1, 1, 0}], 
            3]]
];\)\)

Affichage de points

h3[p_] := p  /;  Length[p] == 3;
h3[p_] := h[p]  /;  Length[p] == 4;

On peut utiliser des points 3D euclidiens ou projectifs

affichePoints[ps_, opts___] := 
      Graphics3D[{PointSize[0.015], opts, 
          Point  /@  h3  /@  ps}]

Show[
      affichePoints[
        Partition[Table[Random[], {i, 1, 21}], 
          3]]]
Show[
      affichePoints[Partition[Table[Random[], {i, 1, 21}], 3], 
        RGBColor[1, 0, 0], PointSize[0.05]]]

afficheLines[base_, ps_, opts___] := 
      Graphics3D[{Thickness[0.001], 
          RGBColor[0, 0, 
            0], Line[{base, #}] & /@  h3  /@  ps}]

Show[
      afficheLines[{0, 0, 0}, 
        Partition[Table[Random[], {i, 1, 21}], 3]]]

Fonctions principales

Geometrie de camera

Affiche la geometrie de la camera, pour une taille d'image connue et une matrice de projection m (3x4 ou 4x4)

Idee:
   On "deprojete" les coins de l'image, et l'origine est directement la translation de im.
   La distance entre le plan de projection et l'origine est donne par f. On doit choisir f en fonction de l échelle des points 3d (si ils sont affichés) et des caméras (lorsqu il y en a plusieurs).

Important:
  A partir d une matrice m seule, il est impossible de déduire la taille de l image. On doit donc donner l information au moment de l affichage (imgx, imgy)

geomCameraTrans[m_] := 
        Module[{im}, (
im = 
              Inverse[If[Dimensions[m] == {3, 4}, 
                  Append[m, {0, 0, 0, 1}], m]]; 
im[[{1, 
                  2, 3}, 4]]
)];

\(\(geomCamera[imgx_, imgy_, f_, m_] := 
        Module[{orig, coins, cs, 
            im}, \((
			im = 
              Inverse[If[Dimensions[m] == {3, 4}, 
                  Append[m, {0, 0, 0, 1}], m]]; 
			orig = 
              Flatten[sousmatrice[im, 1, 3, 4, 4]]; 
			coins = {{0, 0, 
                  f, 1}, {f*imgx, 0, f, 1}, {f*imgx, f*imgy, f, 1}, {0, 
                  f*imgy, f, 1}}; 
			cs = \(Take[im . #, 3] &\)\  /@ \ 
                coins; 
			Graphics3D[{\(Line[{orig, #}] &\)\  /@ \ cs, 
                Polygon[cs]}]
			)\)];\)\)

Affiche la camera, plus des points 3D (p3d) relies avec des lignes , plus des points 2D (p2d)

geomCameraPoints[imgx_, imgy_, f_, m_, p3d_, p2d_] := 
        Module[{pos}, (
pos = 
              geomCameraTrans[
                m]; 
{
geomCamera[imgx, 
                imgy, f, 
                m], 
(afficheLines  @@  
                      Join[{pos}, #]) &  /@  
                p3d, 
(affichePoints  @@  #) &  /@  p3d, 
(affichePoints  @@  #) &  /@  
                p2d
}
)];

Test

Creation de quelques points 3D a projeter

\(\(p = 
        Table[{
			Random[Real, {15, 25}], 
			Random[
              Real, {15, 25}], 
			Random[Real, {15, 25}]}, {i, 1, 
            12}];\)\)
p // MatrixForm

s0 = 
      Show[axes[scaleMatrix[10]], 
        Graphics3D[{PointSize[0.025], Point  /@  p}]]

Fabrique une matrice camera m test

Pas de rotation, pas de translation
Seulement une image 256x256 (angle de vue 90 degres)

campos = {2, 2, 2};

mext = N[rotMatrix[Pi/4, {1, -1, 0}] . transMatrix[-campos]]; 
    mext // MatrixForm

mint = internMatrix[100, 100, 200, 200]; mint // MatrixForm

m = mint . mext; m // MatrixForm

Juste pour etre sûr.... la colone 4 de l inverse doit donner la translation

im = Inverse[m];
im // MatrixForm

Projete tous les points sur le plan z=1 de la camera

pcam = Append[projete[#, m], 1] &  /@  p;
N[pcam] // MatrixForm

"Deprojete" les points images vers la scene

pcamscene = (Take[im . Append[#, 1], 3]) &  /@  (10*
              pcam);
pcamscene // MatrixForm

\(\(Show[s0, Graphics3D[{PointSize[0.035], Point\  /@ \ pcamscene}], 
	
        Graphics3D[\(Line[{campos, #}] &\) /@ \ p], 
	
        geomCamera[200, 200, 10, m], 
	PlotRange -> All, 
        ViewPoint -> {\(-0.75\), 1, 0.2}];\)\)

\(\(Show[geomCameraPoints[200, 200, 10, m, {{p}}, {{pcamscene}}], 
	
        PlotRange -> All, ViewPoint -> {\(-0.75\), 1, 0.2}];\)\)

Show[
      geomCameraPoints[200, 200, 10, 
        m, {{p, PointSize[0.02], RGBColor[0, 1, 1]}}, {{pcamscene, 
            RGBColor[1, 0, 0]}, {pcamscene*1.1, 
            RGBColor[0, 0, 1]}}]]