La mia prospettiva matematica è corretta?


24

Ho dei compiti in cui devo calcolare e tracciare alcuni punti usando una trasformazione prospettica, ma non sono sicuro che i miei risultati siano corretti, dal momento che il grafico 3D che utilizza le coordinate della Fotocamera è molto diverso dal grafico 2D che utilizza le coordinate dell'immagine . Potete aiutarmi a capire cosa c'è che non va?

Questo è ciò che viene dato: la fotocamera si trova nel punto W T C = [ - 1 , 1 , 5 ] T , specificato in coordinate mondiali (in metri). Il sistema di coordinate della telecamera viene ruotato attorno all'asse Y del riferimento mondiale di θ = 160 o , quindi la sua matrice di rotazione è w R c = [ c o s ( θ ) 0 s i n ( θ ) 0 1 0 - s i n (WTC=[1,1,5]Tθ=160owRc=[cos(θ)0sin(θ)010sin(θ)0cos(θ)]

I parametri della fotocamera sono: , s x = s y = 0,01 m m / p x , o x = 320 p x , o y = 240 p xf=16mmsx=sy=0.01mm/pxox=320pxoy=240px

Punti campione (in coordinate mondiali):

WP1=[1,1,0.5]T

WP2=[1,1.5,0.5]T

WP3=[1.5,1.5,0.5]T

WP4=[1.5,1,0.5]T

Devo calcolare e tracciare i punti nelle coordinate della fotocamera e nelle coordinate dell'immagine, quindi ho scritto il seguente codice in Octave:

%camera intrinsic parameters
f = 16
Sx = 0.01
Sy = 0.01
Ox = 320
Oy = 240

%given points, in world coordinate
wP1 = transpose([1, 1, 0.5])
wP2 = transpose([1, 1.5, 0.5])
wP3 = transpose([1.5, 1.5, 0.5])
wP4 = transpose([1.5, 1, 0.5])

% camera translation matrix
wTc = transpose([-1, 1, 5])

% rotation angle converted to rad
theta = 160 / 180 * pi

%camera rotation matrix
wRc = transpose([cos(theta), 0, sin(theta); 0, 1, 0; -sin(theta), 0, cos(theta)])

%transform the points to homogeneous coordinates
wP1h = [wP1; 1]
wP2h = [wP2; 1]
wP3h = [wP3; 1]
wP4h = [wP4; 1]

%separate each line of the rotation matrix
R1 = transpose(wRc(1 , :))
R2 = transpose(wRc(2 , :))
R3 = transpose(wRc(3 , :))

%generate the extrinsic parameters matrix
Mext = [wRc, [-transpose(R1) * wTc; -transpose(R2) * wTc; -transpose(R3) * wTc]]

%intrinsic parameters matrix
Mint = [-f/Sx, 0, Ox; 0, -f/Sy, Oy; 0, 0, 1]

% calculate coordinates in camera coordinates
cP1 = wRc * (wP1 - wTc)
cP2 = wRc * (wP2 - wTc)
cP3 = wRc * (wP3 - wTc)
cP4 = wRc * (wP4 - wTc)

% put coordinates in a list for plotting

x = [cP1(1), cP2(1), cP3(1), cP4(1), cP1(1)]
y = [cP1(2), cP2(2), cP3(2), cP4(2), cP1(2)]
z = [cP1(3), cP2(3), cP3(3), cP4(3), cP1(3)]

%plot the points in 3D using camera coordinates
plot3(x, y, z, "o-r")

pause()

% calculate the points in image coordinates
iP1 = Mint * (Mext * wP1h)
iP2 = Mint * (Mext * wP2h)
iP3 = Mint * (Mext * wP3h)
iP4 = Mint * (Mext * wP4h)

%generate a list of points for plotting
x = [iP1(1) / iP1(3), iP2(1) / iP2(3), iP3(1) / iP3(3), iP4(1) / iP4(3), iP1(1) / iP1(3)]
y = [iP1(2) / iP1(3), iP2(2) / iP2(3), iP3(2) / iP3(3), iP4(2) / iP4(3), iP1(2) / iP1(3)]

plot(x, y, "o-r")

pause()

E queste sono le trame che ho avuto dalla sceneggiatura: mi aspettavo che fossero in qualche modo simili, ma non sembrano così.

Trama 3D

Tracciare le coordinate della telecamera

Trama 2D

Tracciare le coordinate dell'immagine


8
+1 per mostrare che le domande a casa possono essere domande di alta qualità. :)
Martin Ender,

2
Come sottolineato su meta, questa domanda merita una buona risposta. Non ne ho uno anch'io, ma sono felice di dare un po 'della mia reputazione a qualcuno che lo fa.
trichoplax,

@trichoplax il problema è che è fatto in matlab.
joojaa,

@joojaa ah buon punto. Se nessun esperto di matlab interviene durante il periodo di taglie, prenderò in considerazione l'apprendimento di Octave per vedere se è abbastanza vicino per trovare una soluzione.
trichoplax,

1
Non è molto chiaro per me cosa dovrebbe significare la prima immagine. Il secondo è dal punto di vista della fotocamera, e dopo una parte posteriore della stima dell'inviluppo penso che appaia corretta.
Julien Guertault,

Risposte:


8

Identificare i tuoi assi in entrambe le figure e aggiungere la posizione della telecamera alla tua prima figura ti aiuterebbe a capire cosa sta succedendo.

xyz

[0,0,1][0,1,0]

0.016Sx=Sy=0.00010.00001

[1,1,x]z=0.5xtun'n(160°)(5-0.5)=1.64 ...X=-10.64yy

Un buon modo per verificare la tua risposta è usare un modellatore 3D esistente come Blender: Scena 3D in Blender fai attenzione al sistema di coordinate di Blender, ad esempio il vettore predefinito della fotocamera è [0, 0, -1]. Ecco il rendering: Rendering in Blender Focal è stato impostato su un altro valore per rendere la sfera più visibile. Quindi vediamo che i due punti inferiori si trovano sulla riga centrale dell'immagine e i punti sono leggermente a destra dell'immagine.

Ho implementato i tuoi compiti in Python:

import numpy as np

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D


# Parameters
f_mm = 0.016
f_px = f_mm / 0.00001
t_cam = np.array([[-1., 1., 5.]]).T
t_cam_homogeneous = np.vstack((t_cam, np.array([[0]])))
theta = 160. * np.pi / 180.
ox = 320
oy = 240
# Rotation and points are in homogeneous coordinates
rot_cam = np.array([[np.cos(theta), 0, np.sin(theta)],
                    [0, 1, 0],
                    [-np.sin(theta), 0, np.cos(theta)]])
points = np.array([[1, 1, 0.5, 1],
                   [1, 1.5, 0.5, 1],
                   [1.5, 1.5, 0.5, 1],
                   [1.5, 1, 0.5, 1]]).T

# Compute projection matrix using intrinsics and extrinsics
intrinsics = np.array([[f_px, 0, ox],
                       [0, f_px, oy],
                       [0, 0, 1]])
extrinsics = np.hstack((rot_cam, rot_cam.dot(-t_cam)))

rot_cam2 = np.identity(4); rot_cam2[:3,:3] = rot_cam
camera_coordinates = rot_cam2.dot(points - t_cam_homogeneous)
camera_coordinates = camera_coordinates[:3,:] / camera_coordinates[3,:]

# Perform the projection
projected_points = intrinsics.dot(camera_coordinates)
projected_points = projected_points[:2,:] / projected_points[2,:]
projected_points[0,:] = -projected_points[0,:] # Inverted x-axis because camera is pointing toward [0, 0, 1]

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(points[0,:], points[1,:], points[2,:], label="Points")
ax.scatter(t_cam[0], t_cam[1], t_cam[2], c="red", label="Camera")
ax.set_xlabel("X axis"); ax.set_ylabel("Y axis"); ax.set_zlabel("Z axis")
plt.title("World coordinates")
plt.legend()
plt.savefig('world_coordinates.png', dpi=300, bbox_inches="tight")

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(camera_coordinates[0,:], camera_coordinates[1,:], camera_coordinates[2,:], label="Points")
ax.scatter(0, 0, 0, c="red", label="Camera")
ax.set_xlabel("X axis"); ax.set_ylabel("Y axis"); ax.set_zlabel("Z axis")
plt.title("Camera coordinates")
plt.legend()
plt.savefig('camera_coordinates.png', dpi=300, bbox_inches="tight")

plt.figure()
plt.scatter(projected_points[0,:], projected_points[1,:])
plt.xlabel("X axis"); plt.ylabel("Y axis")
plt.title("Image coordinates")
plt.savefig('image_coordinates.png', dpi=300, bbox_inches="tight")

plt.show()

Questo mi dà queste cifre: Rispettivamente: coordinate mondiali, coordinate della telecamera, coordinate della telecamera ruotate per adattarsi leggermente all'orientamento della telecamera (si noti che qui il vettore della telecamera va verso il punto di vista della figura, non "inserisce" la figura) e le coordinate dell'immagine.Coordinate mondiali Coordinate della fotocamera Coordinate della telecamera ruotate Coordinate dell'immagine

Quindi vediamo che le coordinate verticali per i punti inferiori sono correttamente sulla riga centrale (240) e che i punti sono sul lato destro dell'immagine (valore orizzontale> 320).

-f/Sxy[0,0,1]X

[0,-1,0]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.