1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 | import numpy as np
import cv2
import matplotlib.pyplot as plt
# Reference:
# 1. : http://stackoverflow.com/questions/17087446/how-to-calculate-perspective-transform-for-opencv-from-rotation-angles
# 2. : http://jepsonsblog.blogspot.tw/2012/11/rotation-in-3d-using-opencvs.html
camera_parameters = {
"width": 640,
"height": 512,
"focal_x": 0.8645801943826472,
"focal_y": 0.8645801943826472,
"c_x": -0.005689562165298415,
"c_y": -0.0037807145404085553,
"k1": -0.2967016615133813,
"k2": 0.08663139457756042,
"p1": 0.0008407777901525121,
"p2": 8.959107030007158e-05,
"k3": 0.023342862058067047
}
class ImageTransformer(object):
""" Perspective transformation class for image
with shape (height, width, #channels) """
def __init__(self, image_path, shape = None):
self.image_path = image_path
self.image = cv2.imread(image_path)
self.height = self.image.shape[0]
self.width = self.image.shape[1]
self.num_channels = self.image.shape[2]
""" Wrapper of Rotating a Image """
def rotate_along_axis(self, rtheta=0, rphi=0, rgamma=0, dx=0, dy=0, dz=0):
# Get ideal focal length on z axis
# NOTE: Change this section to other axis if needed
d = np.sqrt(self.height**2 + self.width**2)
self.focal = d / (2 * np.sin(rgamma) if np.sin(rgamma) != 0 else 1)
dz = self.focal
# Get projection matrix
mat = self.get_M(rtheta, rphi, rgamma, dx, dy, dz)
return cv2.warpPerspective(self.image.copy(), mat, (self.width, self.height))
""" Get Perspective Projection Matrix """
def get_M(self, theta, phi, gamma, dx, dy, dz):
w = self.width
h = self.height
f = self.focal
c_x = (camera_parameters["c_x"] + 0.5) * camera_parameters["width"]
c_y = (camera_parameters["c_y"] + 0.5) * camera_parameters["height"]
f_x = camera_parameters["focal_x"] * camera_parameters["width"]
f_y = camera_parameters["focal_y"] * camera_parameters["height"]
# Projection 2D -> 3D matrix
A1 = np.array([ [1, 0, -c_x],
[0, 1, -c_y],
[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)
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, c_x, 0],
[0, f, c_y, 0],
[0, 0, 1, 0]])
# Final transformation matrix
return np.dot(A2, np.dot(T, np.dot(R, A1)))
img_path = '@437100@4221736@0.585299@-0.101259@0.638664@374.0050048828@37275@.jpg'
image = cv2.imread(img_path)
yaw, pitch, roll = np.float32(img_path.split("@")[3]), np.float32(img_path.split("@")[4]), np.float32(img_path.split("@")[5])
it = ImageTransformer(img_path)
rotated_img = it.rotate_along_axis(rtheta=roll, rphi=pitch, rgamma=yaw)
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.subplot(122)
plt.imshow(cv2.cvtColor(rotated_img, cv2.COLOR_BGR2RGB))
plt.title('Orthophoto')
plt.show()
|