CTPv 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,205 @@
1
+ import numpy as np
2
+ import os
3
+ from ..Plucker.Line import Line
4
+
5
+ class RadialDistortion:
6
+ """Handles radial distortion parameters for a camera model."""
7
+
8
+ def __init__(self, k1=0, k2=0, k3=0):
9
+ self.k1 = k1
10
+ self.k2 = k2
11
+ self.k3 = k3
12
+
13
+ def set_from_list(self, coeffs):
14
+ if len(coeffs) != 3:
15
+ raise ValueError("List must contain exactly three elements.")
16
+ self.k1, self.k2, self.k3 = coeffs
17
+
18
+
19
+ class IntrinsicMatrix:
20
+ """Encapsulates intrinsic parameters of a pinhole camera model."""
21
+
22
+ def __init__(self):
23
+ self.fx = None
24
+ self.fy = None
25
+ self.cx = None
26
+ self.cy = None
27
+ self.s = 0
28
+ self.width = None
29
+ self.height = None
30
+ self.RadialDistortion = RadialDistortion()
31
+ self._MatlabIntrinsics = np.zeros((3, 3))
32
+ self._OpenCVIntrinsics = np.zeros((3, 3))
33
+ self.pixel_size = None # e.g., 0.0034 mm
34
+ self.info = None # e.g., camera ID or lens metadata
35
+
36
+ @property
37
+ def MatlabIntrinsics(self):
38
+ """
39
+ generation call method for returning Matlab matrix format of intrinsic parameters of a camera
40
+ Returns:
41
+ I = 3x3 matrix
42
+ [ fx 0 cx ]
43
+ [ 0 fy cy ]
44
+ [ 0 0 1 ]
45
+
46
+ """
47
+ I = np.zeros((3, 3))
48
+ I[0, 0] = self.fx
49
+ I[1, 1] = self.fy
50
+ I[2, 0] = self.cx
51
+ I[2, 1] = self.cy
52
+ I[2, 2] = 1
53
+ return I
54
+
55
+ @MatlabIntrinsics.setter
56
+ def MatlabIntrinsics(self, I):
57
+ """
58
+ Extraction call method for extracting Matlab matrix format of intrinsic parameters of a camera to local class,
59
+ parameters are registered to every parameter as per the following structure.
60
+ I = [ fx 0 cx ]
61
+ [ 0 fy cy ]
62
+ [ 0 0 1 ]
63
+
64
+ """
65
+ self.fx = I[0, 0]
66
+ self.fy = I[1, 1]
67
+ self.cx = I[2, 0]
68
+ self.cy = I[2, 1]
69
+ self.s = I[1, 0]
70
+
71
+ @property
72
+ def OpenCVIntrinsics(self):
73
+ """
74
+ generation call method for returning OpenCV matrix format of intrinsic parameters of a camera
75
+ Returns:
76
+ I = 3x3 matrix
77
+ [ fx 0 cx ]
78
+ [ 0 fy cy ]
79
+ [ 0 0 1 ]
80
+
81
+ """
82
+ I = np.zeros((3, 3))
83
+ I[0, 0] = self.fx
84
+ I[1, 1] = self.fy
85
+ I[0, 2] = self.cx
86
+ I[1, 2] = self.cy
87
+ I[2, 2] = 1
88
+ return I
89
+
90
+ @OpenCVIntrinsics.setter
91
+ def OpenCVIntrinsics(self, I):
92
+ """
93
+ Extraction call method for extracting OpenCV matrix format of intrinsic parameters of a camera to local class,
94
+ parameters are registered to every parameter as per the following structure.
95
+ I = [ fx 0 cx ]
96
+ [ 0 fy cy ]
97
+ [ 0 0 1 ]
98
+
99
+ """
100
+ self.fx = I[0, 0]
101
+ self.fy = I[1, 1]
102
+ self.cx = I[0, 2]
103
+ self.cy = I[1, 2]
104
+ self.s = 0
105
+
106
+ @property
107
+ def focal_length_mm(self):
108
+ """Returns focal length in mm."""
109
+ if self.pixel_size is None:
110
+ raise ValueError('Pixel size not set!')
111
+ return self.fx * self.pixel_size, self.fy * self.pixel_size
112
+
113
+ @property
114
+ def PerspectiveAngle(self):
115
+ """Returns horizontal or vertical perspective angle in degrees."""
116
+ if self.width is None:
117
+ raise ValueError('Set width first.')
118
+
119
+ aspectRatio = self.width / self.height
120
+ if aspectRatio > 1:
121
+ return 2 * np.arctan(self.width / (2 * self.fx)) * 180 / np.pi
122
+ else:
123
+ return 2 * np.arctan(self.height / (2 * self.fy)) * 180 / np.pi
124
+
125
+ @PerspectiveAngle.setter
126
+ def PerspectiveAngle(self, p):
127
+ if self.width is None:
128
+ raise ValueError('Set width first.')
129
+
130
+ aspectRatio = self.width / self.height
131
+ if aspectRatio > 1:
132
+ self.fx = (self.width / 2) / np.tan(p / 2)
133
+ self.fy = self.fx
134
+ else:
135
+ self.fy = (self.height / 2) / np.tan(p / 2)
136
+ self.fx = self.fy
137
+
138
+ self.cx = self.width / 2
139
+ self.cy = self.height / 2
140
+
141
+ def CameraParams2Intrinsics(self, CameraParams):
142
+ try:
143
+ self.width = CameraParams.ImageSize[1]
144
+ self.height = CameraParams.ImageSize[0]
145
+ except AttributeError:
146
+ print('Camera not open, set resolution manually.')
147
+ self.MatlabIntrinsics = CameraParams.IntrinsicMatrix
148
+
149
+ def Intrinsics2CameraParams(self):
150
+ P = {
151
+ 'IntrinsicMatrix': self.MatlabIntrinsics,
152
+ 'ImageSize': [self.height, self.width]
153
+ }
154
+ if self.RadialDistortion:
155
+ P['RadialDistortion'] = self.RadialDistortion
156
+ return P
157
+
158
+ def ScaleIntrinsics(self, Scale):
159
+ """Scales all intrinsic parameters and image size by a given factor."""
160
+ self.fx *= Scale
161
+ self.fy *= Scale
162
+ self.cx *= Scale
163
+ self.cy *= Scale
164
+ self.width *= Scale
165
+ self.height *= Scale
166
+
167
+ def save_intrinsics_to_json(self, filename):
168
+ """Serialize camera intrinsics to a JSON file."""
169
+ import json
170
+ directory = os.path.dirname(filename)
171
+ if directory:
172
+ os.makedirs(directory, exist_ok=True)
173
+
174
+ data = {
175
+ 'OpenCVIntrinsics': self.OpenCVIntrinsics.tolist(),
176
+ 'RadialDistortion': {
177
+ 'k1': self.RadialDistortion.k1,
178
+ 'k2': self.RadialDistortion.k2,
179
+ 'k3': self.RadialDistortion.k3
180
+ },
181
+ 'width': self.width,
182
+ 'height': self.height,
183
+ 'pixel_size': self.pixel_size,
184
+ 'info': self.info
185
+ }
186
+ with open(filename, 'w') as f:
187
+ json.dump(data, f, indent=4)
188
+
189
+ def load_intrinsics_from_json(self, filename):
190
+ """Load camera intrinsics from a JSON file."""
191
+ import json
192
+ with open(filename, 'r') as f:
193
+ data = json.load(f)
194
+
195
+ self.OpenCVIntrinsics = np.array(data['OpenCVIntrinsics'])
196
+ self.RadialDistortion.set_from_list([
197
+ data['RadialDistortion']['k1'],
198
+ data['RadialDistortion']['k2'],
199
+ data['RadialDistortion']['k3']
200
+ ])
201
+ self.width = data['width']
202
+ self.height = data['height']
203
+ self.pixel_size = data['pixel_size']
204
+ self.info = data['info']
205
+ return self
File without changes