Apakah perspektif matematika saya benar?

24

Saya punya pekerjaan rumah di mana saya harus menghitung dan memplot beberapa poin menggunakan transformasi pespektif, tetapi saya tidak yakin hasil saya benar, karena plot 3d menggunakan koordinat Kamera terlihat sangat berbeda dari plot 2d menggunakan koordinat gambar . Bisakah Anda membantu saya memahami apa yang salah?

Inilah yang diberikan: Kamera berada pada titik W T C = [ - 1 , 1 , 5 ] T , ditentukan dalam koordinat dunia (dalam meter). Sistem koordinat kamera diputar di sekitar sumbu Y dari referensi dunia oleh , sehingga matriks rotasinya adalahWTC=[1,1,5]Tw R c = [ c o s ( θ ) 0 s i n ( θ ) 0 1 0 - s i n ( θ ) 0 c o s ( θ ) ]θ=160owRc=[cos(θ)0sin(θ)010sin(θ)0cos(θ)]

Parameter kamera adalah: , s_x = s_y = 0,01 mm / px , o_x = 320 px , o_y = 240pxs 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

Poin sampel (dalam koordinat dunia):

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

Saya harus menghitung dan memplot poin dalam koordinat kamera dan dalam koordinat gambar, jadi saya menulis kode berikut dalam Oktaf:

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

Dan ini adalah plot yang saya dapatkan dari skrip: Saya berharap mereka agak mirip, tetapi mereka tidak terlihat begitu.

Plot 3D

Plot dalam koordinat kamera

Plot 2D

Plot dalam koordinat gambar

Vitor
sumber
8
+1 untuk menunjukkan bahwa pertanyaan pekerjaan rumah bisa menjadi pertanyaan berkualitas tinggi. :)
Martin Ender
2
Seperti yang ditunjukkan pada meta , pertanyaan ini layak mendapatkan jawaban yang bagus. Saya sendiri tidak memilikinya, tetapi saya senang memberikan beberapa reputasi saya kepada seseorang yang memilikinya.
trichoplax
@trichoplax masalahnya adalah bahwa hal itu dilakukan di matlab.
joojaa
@ joojaa ah poin bagus. Jika tidak ada ahli matlab yang masuk selama periode hadiah, saya akan mempertimbangkan belajar Oktaf untuk melihat apakah itu cukup dekat untuk menemukan solusi.
trichoplax
1
Bagi saya tidak terlalu jelas apa arti gambar pertama. Yang kedua adalah dari sudut pandang kamera, dan setelah estimasi belakang amplop saya pikir itu terlihat benar.
Julien Guertault

Jawaban:

8

Mengidentifikasi sumbu Anda di kedua gambar dan menambahkan posisi kamera ke angka pertama Anda akan membantu Anda memahami apa yang terjadi.

xyz

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

0.016Sx=Sy=0.00010.00001

[1,1,x]z=0.5xx = - 1 0,64 y ytan(160°)(50.5)=1.64...x=10.64ykoordinat sebagai dua titik, dan karena koordinat tidak diubah oleh rotasi, mereka harus tetap berakhir pada koordinat yang sama setelah transformasi, artinya pada baris tengah gambar.y

Cara yang baik untuk memeriksa jawaban Anda adalah dengan menggunakan pemodel 3D yang sudah ada seperti Blender: Adegan 3D di Blender Berhati-hatilah dengan sistem koordinat Blender, misalnya vektor kamera defaultnya [0, 0, -1]. Inilah rendernya: Render dalam Blender Focal diatur ke nilai lain untuk membuat bola lebih terlihat. Jadi kita melihat bahwa dua titik bawah berada di baris tengah gambar dan titik-titiknya sedikit di sebelah kanan gambar.

Saya menerapkan pekerjaan rumah Anda dengan 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()

Ini menghasilkan angka-angka itu: Masing-masing: Koordinat dunia, Koordinat kamera, Koordinat kamera diputar agar pas sedikit dengan orientasi kamera (perhatikan bahwa di sini vektor kamera mengarah ke sudut pandang gambar, itu tidak "memasukkan" gambar) dan koordinat gambar.Koordinat dunia Koordinat kamera Koordinat kamera diputar Koordinat gambar

Jadi kita melihat bahwa koordinat vertikal untuk titik-titik bawah benar di baris tengah (240) dan titik-titiknya ada di sisi kanan gambar (nilai horizontal> 320).

Saya percaya satu bug yang Anda miliki adalah bahwa Anda menemukan nilai X negatif, sehingga Anda meniadakan focals ( -f/Sxy) dalam matriks intrinsik untuk mengompensasi. Masalahnya di sini adalah kita mengasumsikan bahwa kamera pada awalnya mengarah ke (jika tidak, rotasi 160 ° tidak akan mengarah ke titik). Jika Anda melihatnya seperti itu, sumbu meningkat ketika menuju ke kiri , kebalikan dari sumbu ini harus diambil.x[0,0,1]x

Kedua hasil kami tampaknya mirip dengan saya, hanya saja Anda menduga vektor untuk kamera (sebenarnya kedua sumbu dicerminkan karena Anda meniadakan kedua fokus), dan melakukan perhitungan dalam mm bukannya meter.[0,1,0]

Soravux
sumber