MCPcopy Create free account
hub / github.com/colmap/colmap / process

Method process

python/examples/panorama_sfm.py:220–297  ·  view source on GitHub ↗
(self, pano_name: str)

Source from the content-addressed store, hash-verified

218 self._rays_in_cam: npt.NDArray[np.floating] | None = None
219
220 def process(self, pano_name: str) -> None:
221 pano_path = self.pano_image_dir / pano_name
222 try:
223 pano_pil_image = PIL.Image.open(pano_path)
224 except PIL.Image.UnidentifiedImageError:
225 logging.info(f"Skipping file {pano_path} as it cannot be read.")
226 return
227
228 pano_exif = pano_pil_image.getexif()
229 gpsonly_exif = PIL.Image.Exif()
230 gpsonly_exif[PIL.ExifTags.IFD.GPSInfo] = pano_exif.get_ifd(
231 PIL.ExifTags.IFD.GPSInfo
232 )
233
234 pano_image = np.asarray(pano_pil_image)
235 pano_height, pano_width, *_ = pano_image.shape
236 if pano_width != pano_height * 2:
237 raise ValueError("Only 360° panoramas are supported.")
238
239 with self._lock:
240 if self._camera is None: # First image, precompute rays once.
241 self._camera = create_virtual_camera(
242 pano_width=pano_width,
243 pano_height=pano_height,
244 hfov_deg=self.render_options.hfov_deg,
245 vfov_deg=self.render_options.vfov_deg,
246 )
247 for rig_camera in self.rig_config.cameras:
248 rig_camera.camera = self._camera
249 self._pano_size = (pano_width, pano_height)
250 self._rays_in_cam = get_virtual_camera_rays(self._camera)
251 else: # Later images, verify consistent panoramas.
252 if (pano_width, pano_height) != self._pano_size:
253 raise ValueError(
254 "Panoramas of different sizes are not supported."
255 )
256
257 for cam_idx, cam_from_pano_r in enumerate(self.cams_from_pano_rotation):
258 assert self._rays_in_cam is not None
259 rays_in_pano = self._rays_in_cam @ cam_from_pano_r
260 xy_in_pano = spherical_img_from_cam(self._pano_size, rays_in_pano)
261 xy_in_pano = xy_in_pano.reshape(
262 self._camera.width, self._camera.height, 2
263 ).astype(np.float32)
264 xy_in_pano -= 0.5 # COLMAP to OpenCV pixel origin.
265 x_coords, y_coords = np.moveaxis(xy_in_pano, [0, 1, 2], [2, 1, 0])
266 image = cv2.remap(
267 pano_image,
268 x_coords,
269 y_coords,
270 cv2.INTER_LINEAR,
271 borderMode=cv2.BORDER_WRAP,
272 )
273 # We define a mask such that each pixel of the panorama has its
274 # features extracted only in a single virtual camera.
275 closest_camera = np.argmax(
276 rays_in_pano @ self.cam_centers_in_pano.T, -1
277 )

Callers

nothing calls this directly

Calls 3

create_virtual_cameraFunction · 0.85
get_virtual_camera_raysFunction · 0.85
spherical_img_from_camFunction · 0.85

Tested by

no test coverage detected