내 관점 수학이 맞습니까?


24

pespective 변환을 사용하여 일부 점을 계산하고 플롯 해야하는 숙제가 있지만 카메라 좌표를 사용하는 3d 플롯이 이미지 좌표를 사용하는 2d 플롯과 매우 다르게 보이므로 결과가 올바른지 확실하지 않습니다. . 무엇이 잘못되었는지 이해하도록 도와 줄 수 있습니까?

카메라는 지점에 있으며 세계 좌표 (미터)로 지정되어 있습니다. 카메라 좌표계는 월드 기준의 Y 축을 중심으로 회전하므로 회전 행렬은 θ = 160 O w R C = [ C O S ( θ ) 0 s의 I N ( θ ) 0 1 0 - s의 I를 N ( θ ) 0 C O S ( θ ) ]기음=[1,1,5]θ=160영형아르 자형기음=[기음영형에스(θ)0에스나는(θ)010에스나는(θ)0기음영형에스(θ)]

카메라 매개 변수는 다음과 같습니다 : , , ,s x = s y = 0.01 m m / p x o x = 320 p x o y = 240 p x에프=16에스엑스=에스와이=0.01/엑스영형엑스=320엑스영형와이=240엑스

샘플 포인트 (세계 좌표) :

1=[1,1,0.5]

2=[1,1.5,0.5]

=[1.5,1.5,0.5]

4=[1.5,1,0.5]

카메라 좌표와 이미지 좌표의 점을 계산하고 플롯해야하므로 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()

그리고 이것들은 내가 대본에서 얻은 음모입니다.

3D 플롯

카메라 좌표로 플롯

2D 플롯

이미지 좌표로 플롯


8
숙제 질문이 고품질의 질문 일 수 있음을 보여주는 +1 :)
Martin Ender

2
마찬가지로 메타에 지적 이 질문에 좋은 답변을받을만한입니다. 나는 나 자신이 없지만, 나는 누군가에게 나의 명성의 일부를 기쁘게 생각합니다.
trichoplax

@ trichoplax 문제는 matlab에서 수행된다는 것입니다.
joojaa

@joojaa 아 좋은 지적. 현상금 기간 동안 matlab 전문가가 개입하지 않으면 Octave 를 학습 하여 솔루션을 찾기에 충분히 가까운 지 확인하는 것이 좋습니다.
trichoplax

1
첫 번째 이미지가 무엇을 의미하는지는 분명하지 않습니다. 두 번째는 카메라의 관점에서 볼 수 있으며 봉투 추정의 뒤에서 나는 그것이 올바르게 보인다고 생각합니다.
Julien Guertault

답변:


8

두 그림에서 축을 식별하고 첫 번째 그림에 카메라 위치를 추가하면 진행 상황을 이해하는 데 도움이됩니다.

엑스와이

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

0.016에스엑스=에스와이=0.00010.00001

[1,1,엑스]=0.5엑스에이(160°)(50.5)=1.64 ...엑스=10.64와이보낸 두 지점으로 좌표 및 좌표가 회전에 의해 변경되지 않고, 여전히 이미지의 중앙 행을 의미하는 변환 후 동일한 좌표를 끝낼 것이다.와이

답변을 확인하는 좋은 방법은 Blender와 같은 기존 3D 모델러를 사용하는 것 블렌더의 3D 장면 입니다. Blender의 좌표계에주의하십시오 (예 : 기본 카메라 벡터는) [0, 0, -1]. 렌더링은 다음과 같습니다. 블렌더에서 렌더링 초점이 구를 더 잘 보이도록 다른 값으로 설정되었습니다. 따라서 하단의 두 지점이 이미지의 중간 행에 있고 지점이 이미지의 오른쪽에 약간 있음을 알 수 있습니다.

파이썬으로 숙제를 구현했습니다.

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

이는 각각 나름의 수치를 산출합니다. 각각 : 월드 좌표, 카메라 좌표, 카메라 좌표가 약간 카메라 방향 에 맞게 회전되었습니다 (여기서는 카메라 벡터가 도형 시점을 향해 가고, 도형을 "입력하지 않음").세계 좌표 카메라 좌표 카메라 좌표 회전 이미지 좌표

따라서 하단 지점의 수직 좌표가 가운데 행 (240)에 올 바르고 지점이 이미지의 오른쪽에 있습니다 (가로 값> 320).

-f/Sxy[0,0,1]엑스

[0,1,0]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.