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

Method convert_to_equirectangular

python/examples/panorama_sfm.py:307–427  ·  view source on GitHub ↗

Convert a reconstruction built from the rig of perspective virtual cameras back to one equirectangular camera/image per input panorama. The output reconstruction references the original panorama images with the native EQUIRECTANGULAR camera model. Frame poses, 3D points, and

(
        self, reconstruction: pycolmap.Reconstruction
    )

Source from the content-addressed store, hash-verified

305 raise ValueError(f"Unknown virtual camera for image {image_name!r}.")
306
307 def convert_to_equirectangular(
308 self, reconstruction: pycolmap.Reconstruction
309 ) -> pycolmap.Reconstruction:
310 """Convert a reconstruction built from the rig of perspective virtual
311 cameras back to one equirectangular camera/image per input panorama.
312
313 The output reconstruction references the original panorama images with
314 the native EQUIRECTANGULAR camera model. Frame poses, 3D points, and
315 all keypoints (including those without a 3D observation) are carried
316 over by re-projecting the perspective keypoints onto the panorama
317 through the same spherical mapping used for rendering, so the result is
318 a valid, bundle-adjustable reconstruction.
319 """
320 if self._camera is None or self._pano_size is None:
321 raise RuntimeError("No panorama was rendered yet.")
322 pano_width, pano_height = self._pano_size
323
324 equirect = pycolmap.Reconstruction()
325 equirect_camera = pycolmap.Camera.create_from_model_id(
326 camera_id=1,
327 model=pycolmap.CameraModelId.EQUIRECTANGULAR,
328 focal_length=0.0,
329 width=pano_width,
330 height=pano_height,
331 )
332 equirect.add_camera_with_trivial_rig(equirect_camera)
333
334 # The rig reference sensor is virtual camera 0 (see
335 # create_pano_rig_config), so rig_from_world == cam0_from_world and
336 # pano_from_world = pano_from_cam0 @ cam0_from_world. The virtual
337 # cameras share the panorama center, hence the zero translation.
338 pano_from_ref = pycolmap.Rigid3d(
339 pycolmap.Rotation3d(
340 cast(NDArray3x3, self.cams_from_pano_rotation[0])
341 ),
342 cast(NDArray3x1, np.zeros((3, 1), dtype=np.float64)),
343 ).inverse()
344
345 # Group the registered virtual cameras by frame. All virtual cameras of
346 # a frame observe the same panorama and share its pose, so we can
347 # accumulate their keypoints into a single equirectangular image.
348 images_by_frame: dict[int, list[pycolmap.Image]] = (
349 collections.defaultdict(list)
350 )
351 for image in reconstruction.images.values():
352 if image.has_pose:
353 images_by_frame[image.frame_id].append(image)
354
355 # Maps an image_id of a virtual camera to a dict from its old point2D
356 # index to the (new point2D index, pano_name) in the equirectangular
357 # image, so we can later rebuild the 3D point tracks.
358 old_to_new_point2D: dict[int, dict[int, tuple[int, str]]] = {}
359 pano_to_image_id: dict[str, int] = {}
360
361 frame_images = sorted(
362 images_by_frame.values(),
363 key=lambda images: self.split_image_name(images[0].name)[1],
364 )

Callers 1

run_perspectiveFunction · 0.80

Calls 6

split_image_nameMethod · 0.95
spherical_img_from_camFunction · 0.85
Rigid3dMethod · 0.80
TrackMethod · 0.80
ReconstructionMethod · 0.45
ImageMethod · 0.45

Tested by

no test coverage detected