Ist meine Perspektive Mathe richtig?

24

Ich habe eine Hausaufgabe, in der ich einige Punkte mithilfe einer bestimmten Transformation berechnen und plotten muss, aber ich bin nicht sicher, ob meine Ergebnisse korrekt sind, da die 3D-Darstellung mit Kamerakoordinaten sehr anders aussieht als die 2D-Darstellung mit den Bildkoordinaten . Kannst du mir helfen zu verstehen, was los ist?

Dies ist gegeben: Die Kamera befindet sich am Punkt W T C = [ - 1 , 1 , 5 ] T , angegeben in Weltkoordinaten (in Metern). Das Kamerakoordinatensystem wird um die Y-Achse der Weltreferenz um & thgr ; = 160 ° gedreht , so dass seine Drehmatrix w R c = [ c o s ( & thgr; ) 0 s i n ( & thgr; ) 0 1 0 - s i n ist (WTC=[-1,1,5]Tθ=160OwRc=[cOs(θ)0sichn(θ)010-sichn(θ)0cOs(θ)]

Kameraparameter sind: , 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

Beispielpunkte (in Weltkoordinaten):

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

Ich muss die Punkte in Kamerakoordinaten und in Bildkoordinaten berechnen und plotten, also habe ich den folgenden Code in Octave geschrieben:

%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()

Und dies sind die Handlungen, die ich aus dem Drehbuch erhalten habe: Ich hatte erwartet, dass sie sich etwas ähneln, aber sie sehen nicht so aus.

3D-Darstellung

Zeichnen Sie die Kamerakoordinaten ein

2D-Plot

Zeichnen Sie in Bildkoordinaten

Vitor
quelle
8
+1 für das Zeigen, dass Hausaufgabenfragen qualitativ hochwertige Fragen sein können. :)
Martin Ender
2
Wie auf Meta hingewiesen, verdient diese Frage eine gute Antwort. Ich habe selbst keinen, aber ich bin froh, jemandem, der dies tut, einen Teil meines Rufs zu geben.
Trichoplax
@ Trichoplax Das Problem ist, dass es in Matlab gemacht wird.
Joojaa
@ Joojaa ah guter Punkt. Wenn während der Kopfgeldperiode keine Matlab-Experten einspringen, werde ich Octave lernen, um zu prüfen , ob dies nah genug ist, um eine Lösung zu finden.
Trichoplax
1
Mir ist nicht klar, was das erste Bild bedeuten soll. Der zweite ist aus der Sicht der Kamera, und nach einem Rückblick auf die Umschlagschätzung denke ich, dass er korrekt aussieht.
Julien Guertault

Antworten:

8

Indem Sie Ihre Achsen in beiden Figuren identifizieren und die Kameraposition zu Ihrer ersten Figur hinzufügen, können Sie besser verstehen, was vor sich geht.

xyz

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

0,016Sx=Sy=0,00010,00001

[-1,1,x]z=0,5xteinn(160°)(5-0,5)=1,64 ...x=-10,64yy

Eine gute Möglichkeit, Ihre Antwort zu überprüfen, ist die Verwendung eines vorhandenen 3D-Modellierers wie Blender: 3D-Szene in Blender Seien Sie vorsichtig mit dem Blender-Koordinatensystem, z. B. mit dem Standardkameravektor [0, 0, -1]. Hier ist das Rendering: Rendern Sie in Blender Focal wurde auf einen anderen Wert gesetzt, um die Kugel besser sichtbar zu machen. Wir sehen also, dass sich die beiden unteren Punkte in der mittleren Reihe des Bildes befinden und die Punkte etwas rechts vom Bild.

Ich habe deine Hausaufgaben in Python umgesetzt:

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()

Daraus ergeben sich folgende Zahlen: Jeweils: Weltkoordinaten, Kamerakoordinaten, Kamerakoordinaten , die so gedreht werden, dass sie leicht zur Kameraausrichtung passen (beachten Sie, dass der Kameravektor in Richtung des Ansichtspunkts der Figur geht und die Figur nicht "eingibt") und Bildkoordinaten.Weltkoordinaten Kamerakoordinaten Kamerakoordinaten gedreht Bildkoordinaten

Wir sehen also, dass die vertikalen Koordinaten für die unteren Punkte korrekt in der mittleren Zeile (240) und die Punkte auf der rechten Seite des Bildes liegen (horizontaler Wert> 320).

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

[0,-1,0]

Soravux
quelle