After reading this post, I could make the rotated image on x,y,z axis using following code:
import numpy as np
import cv2
def get_3d_rotation_matrix(width, height, theta, phi, gamma, dx, dy, dz):
w, h = width, height
d = np.sqrt(w ** 2 + h ** 2)
focal = f = d / (2 * np.sin(gamma) if np.sin(gamma) != 0 else 1)
dz = focal
# Projection 2D -> 3D matrix
A1 = np.array([[1, 0, -w / 2],
[0, 1, -h / 2],
[0, 0, 1],
[0, 0, 1]])
# Rotation matrices around the X, Y, and Z axis
RX = np.array([[1, 0, 0, 0],
[0, np.cos(theta), -np.sin(theta), 0],
[0, np.sin(theta), np.cos(theta), 0],
[0, 0, 0, 1]])
RY = np.array([[np.cos(phi), 0, -np.sin(phi), 0],
[0, 1, 0, 0],
[np.sin(phi), 0, np.cos(phi), 0],
[0, 0, 0, 1]])
RZ = np.array([[np.cos(gamma), -np.sin(gamma), 0, 0],
[np.sin(gamma), np.cos(gamma), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]])
# Composed rotation matrix with (RX, RY, RZ)
R = np.dot(np.dot(RX, RY), RZ)
# Translation matrix
T = np.array([[1, 0, 0, dx],
[0, 1, 0, dy],
[0, 0, 1, dz],
[0, 0, 0, 1]])
# Projection 3D -> 2D matrix
A2 = np.array([[f, 0, w / 2, 0],
[0, f, h / 2, 0],
[0, 0, 1, 0]])
# Final transformation matrix
return np.dot(A2, np.dot(T, np.dot(R, A1)))
def get_image_3d_rotated(image, theta, phi, gamma, dx, dy, dz):
height, width, _ = image.shape
rtheta, rphi, rgamma = np.deg2rad(theta), np.deg2rad(phi), np.deg2rad(gamma)
mat = get_3d_rotation_matrix(width, height, rtheta, rphi, rgamma, dx, dy, dz)
return cv2.warpPerspective(image.copy(), mat, (width, height))
if __name__ == '__main__':
image = cv2.imread('1.jpg')
rotated_img = get_image_3d_rotated(image, 15, 16, 17, 0, 0, 0)
My question is, where I know 3d rotation angle of the image, is there way to get rectified image like original? I tried to re-rotated the warped image with negative degrees on each x,y,z axis, but I couldn't get satisfied result.
Warped image rotated 15 degree on x-axis, 16 degree y-axis, 17 degree z-axis:
Re-rotated image 2 with -15 degree on x-axis, -16 degree y-axis, -17 degree z-axis:
But the third image still looks tilted towards the y-axis.