def write_instant_ngp_file(
        cls, ofp, cameras, ref_centroid_shift=None, op=None
    ):
        """Write cameras and points as :code:`Instant-NGP` json file."""
        log_report("INFO", f"Write Instant-NGP json file: {ofp}", op)

        cls._ensure_consistent_values(cameras)
        reference_camera = cameras[0]
        cx, cy = reference_camera.get_principal_point()
        focal_length = reference_camera.get_focal_length()
        width = float(reference_camera.width)
        height = float(reference_camera.height)
        fl_x = focal_length
        fl_y = focal_length
        camera_angle_x = math.atan(width / (fl_x * 2)) * 2
        camera_angle_y = math.atan(height / (fl_y * 2)) * 2

        json_data = {
            "camera_angle_x": camera_angle_x,
            "camera_angle_y": camera_angle_y,
            "fl_x": fl_x,
            "fl_y": fl_y,
            "cx": cx,
            "cy": cy,
            "w": width,
            "h": height,
        }

        if ref_centroid_shift is not None:
            json_data["ref_centroid_shift"] = ref_centroid_shift.to_list()

        json_frames = []
        for camera in cameras:
            blender_name = camera.get_relative_fp()
            blender_stem = blender_name.split("_")[0]
            instant_fn = os.path.join("images", f"{blender_stem}.jpg")

            rotation_mat = camera.get_rotation_as_rotation_mat()
            camera_center_vec = camera.get_camera_center()

            # As stated in self.parse_instant_ngp_json_file() it is necessary
            # to convert the camera coordinate system from computer vision to
            # computer graphics convention, i.e. inverting the y and z axis
            # of the rotation matrix.
            rotation_mat = invert_y_and_z_axis(rotation_mat)

            # camera_to_world_mat = [R^T    c]
            #                       [0      1]
            camera_to_world_mat = np.identity(4, dtype=float)
            camera_to_world_mat[0:3, 0:3] = rotation_mat.transpose()
            camera_to_world_mat[0:3, 3] = camera_center_vec

            camera_to_world_list = camera_to_world_mat.tolist()
            json_frame = {
                "file_path": instant_fn,
                "transform_matrix": camera_to_world_list,
            }

            json_frames.append(json_frame)
        json_data["frames"] = json_frames

        with open(ofp, "w") as f:
            json.dump(json_data, f, indent=4)
Write cameras and points as :code:`Instant-NGP` json file.
photogrammetry_importer/file_handlers/instant_ngp_file_handler.py