ds_msp.ops¶
Model-agnostic services built on top of any CameraModel: undistortion (Undistorter) and
pose estimation (solve_pnp, solve_pnp_ransac). See
Undistort images and
Solve PnP on a fisheye for task recipes.
ds_msp.ops ¶
Model-agnostic services: undistortion, pose estimation, and chart reprojection.
Chart ¶
Base class: a chart is an output grid plus a bijection with unit rays.
Source code in ds_msp/ops/reproject.py
pixel_to_ray ¶
Map chart pixel coordinates to unit bearing rays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
ndarray
|
Chart pixel coordinates, any common broadcastable shape |
required |
v
|
ndarray
|
Chart pixel coordinates, any common broadcastable shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Unit-norm rays, shape |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Always, on the base class. Concrete charts override this. |
Source code in ds_msp/ops/reproject.py
ray_to_pixel ¶
Map unit bearing rays to chart pixel coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rays
|
ndarray
|
Rays, shape |
required |
Returns:
| Name | Type | Description |
|---|---|---|
uv |
ndarray
|
Chart pixel coordinates, shape |
valid |
ndarray
|
Boolean mask, shape |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Always, on the base class. Concrete charts override this. |
Source code in ds_msp/ops/reproject.py
Cylindrical ¶
Bases: Chart
Cylinder chart: same azimuth column as the sphere, row linear in tan(elevation).
Source code in ds_msp/ops/reproject.py
pixel_to_ray ¶
See :meth:Chart.pixel_to_ray. Row v maps through tan(elevation).
Source code in ds_msp/ops/reproject.py
ray_to_pixel ¶
See :meth:Chart.ray_to_pixel. valid requires z > 0 (front
hemisphere of the azimuth branch; the cylinder projection is undefined
past ±90° from the forward axis).
Source code in ds_msp/ops/reproject.py
Equirectangular ¶
Bases: Chart
Unit-sphere chart: column linear in azimuth, row linear in elevation (full sphere).
Source code in ds_msp/ops/reproject.py
pixel_to_ray ¶
See :meth:Chart.pixel_to_ray. Covers the full sphere; never invalid.
Source code in ds_msp/ops/reproject.py
ray_to_pixel ¶
See :meth:Chart.ray_to_pixel. valid is always all-True.
Source code in ds_msp/ops/reproject.py
Pinhole ¶
Bases: Chart
Rectilinear (gnomonic) chart — a virtual pinhole, valid only for the front hemisphere.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
Output chart size, pixels. |
required |
height
|
int
|
Output chart size, pixels. |
required |
hfov_deg
|
float
|
Horizontal field of view, degrees. Must be |
90.0
|
R
|
ndarray of shape (3, 3)
|
Rotation from the chart's local look direction into the camera frame
( |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in ds_msp/ops/reproject.py
pixel_to_ray ¶
See :meth:Chart.pixel_to_ray. Never invalid (every pixel has a ray).
Source code in ds_msp/ops/reproject.py
ray_to_pixel ¶
See :meth:Chart.ray_to_pixel. valid requires the ray to lie in
front of the chart plane (z > 1e-9 in the chart's rotated frame).
Source code in ds_msp/ops/reproject.py
TangentImage ¶
Bases: Chart
A gnomonic patch tangent to the sphere at center (a unit ray) — a low-distortion
perspective view of one region. Tile these (cubemap / icosahedron) to cover a wide FOV with
near-frontal, straight-edged content. Equivalent to a Pinhole oriented at center.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
center
|
ndarray of shape (3,)
|
Look direction of the patch, in camera-frame coordinates. Need not be unit-norm; it is normalized internally. |
required |
fov_deg
|
float
|
Horizontal field of view of the (square) patch, degrees. Must be
|
required |
size
|
int
|
Output patch width and height, pixels (square). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in ds_msp/ops/reproject.py
pixel_to_ray ¶
Undistorter ¶
Undistort images/points from any model into a pinhole view.
Model-agnostic counterpart to :meth:ds_msp.model.DoubleSphereCamera.undistort_image:
works with any :class:~ds_msp.core.contracts.CameraModel. Caches the resampling map by
output K_new (recomputed only when a different K_new is requested), so repeated
calls with the same target intrinsics reuse the cached (mapx, mapy).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
CameraModel
|
The calibrated camera to undistort from. |
required |
width
|
int
|
Output (rectified) image size, pixels. |
required |
height
|
int
|
Output (rectified) image size, pixels. |
required |
Examples:
>>> import numpy as np
>>> from ds_msp.models import DoubleSphereModel
>>> model = DoubleSphereModel.sample()
>>> img = np.zeros((1080, 1920, 3), dtype=np.uint8)
>>> und = Undistorter(model, 1920, 1080)
>>> img_rect, K_new = und.undistort_image(img) # works with any CameraModel
>>> img_rect.shape, K_new.shape
((1080, 1920, 3), (3, 3))
Source code in ds_msp/ops/undistort.py
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
distort_points ¶
Inverse of :meth:undistort_points: map rectified pixels back to distorted ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
ndarray of shape (N, 2)
|
Rectified pinhole pixels, in the |
required |
K_new
|
ndarray of shape (3, 3)
|
The intrinsics |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
uv |
ndarray of shape (N, 2)
|
Distorted pixels in the original (source) image. |
valid |
ndarray of shape (N,), bool
|
|
Source code in ds_msp/ops/undistort.py
maps ¶
Build (or return the cached) cv2.remap lookup for a target K_new.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
K_new
|
ndarray of shape (3, 3)
|
Target pinhole intrinsics for the rectified output. Defaults to
:meth: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
mapx |
ndarray of shape (height, width), float32
|
Source-image |
mapy |
ndarray of shape (height, width), float32
|
Source-image |
K_new |
ndarray of shape (3, 3)
|
The intrinsics the maps were built for (echoes the input, or the computed default). |
Source code in ds_msp/ops/undistort.py
new_K ¶
Build a balanced pinhole intrinsic matrix for the output image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
balance
|
float
|
Field-of-view/border trade-off in |
0.5
|
Returns:
| Type | Description |
|---|---|
ndarray of shape (3, 3)
|
The new pinhole |
Source code in ds_msp/ops/undistort.py
undistort_image ¶
Resample a distorted img into a rectified pinhole view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
ndarray of shape (H_src, W_src, ...)
|
Source (distorted) image, any |
required |
K_new
|
ndarray of shape (3, 3)
|
Target pinhole intrinsics; see :meth: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
out |
ndarray of shape (height, width, ...)
|
The rectified image, sized |
K_new |
ndarray of shape (3, 3)
|
The intrinsics actually used (echoes the input, or the computed default). |
Source code in ds_msp/ops/undistort.py
undistort_points ¶
Map distorted pixels to rectified pinhole pixels (in the K_new frame).
Closed-form counterpart to :meth:undistort_image: unprojects each point
through self.model and reprojects the resulting ray with K_new.
Exact wherever the ray is recoverable — unlike inverting a displacement
mesh, this has no periphery error (see :mod:ds_msp.ldc for the mesh
alternative and its accuracy trade-off).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
ndarray of shape (N, 2)
|
Distorted pixels in the original (source) image. |
required |
K_new
|
ndarray of shape (3, 3)
|
Target pinhole intrinsics; see :meth: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
uv |
ndarray of shape (N, 2)
|
Rectified pixel coordinates in the |
valid |
ndarray of shape (N,), bool
|
|
Source code in ds_msp/ops/undistort.py
cubemap_charts ¶
Build the six cube faces (+/-X, +/-Y, +/-Z) as tangent images.
Less polar distortion than equirectangular, and each face is a plain perspective view. A
bare 90° face leaves a measure-zero gap at the cube corners (and a half-pixel sliver from
the principal-point convention), so each face is widened by overlap_deg on every side,
giving a small guard band that tiles the sphere seamlessly — the standard cubemap practice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
face_size
|
int
|
Width and height of each square face, pixels. |
required |
overlap_deg
|
float
|
Extra field of view added on every side of the nominal 90° face, degrees, so adjacent faces overlap slightly instead of leaving gaps. |
1.0
|
Returns:
| Type | Description |
|---|---|
list of TangentImage
|
Six charts, one per cube face, in the fixed order |
Source code in ds_msp/ops/reproject.py
reproject_image ¶
reproject_image(cam, img: ndarray, chart: Chart, interpolation: int = cv2.INTER_LINEAR) -> Tuple[np.ndarray, np.ndarray]
Resample a fisheye image into a chart (e.g. equirectangular, cubemap face).
Builds the lookup with :func:reproject_maps and applies it with cv2.remap.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cam
|
CameraModel
|
The calibrated model that captured |
required |
img
|
ndarray of shape (H_src, W_src, ...)
|
Source image, any |
required |
chart
|
Chart
|
The target chart; determines the output size ( |
required |
interpolation
|
int
|
OpenCV interpolation flag passed to |
cv2.INTER_LINEAR
|
Returns:
| Name | Type | Description |
|---|---|---|
out |
ndarray of shape (H, W, ...)
|
The resampled image, |
valid |
ndarray of shape (H, W), bool
|
Per-pixel mask, |
Source code in ds_msp/ops/reproject.py
reproject_maps ¶
Build (mapx, mapy, valid) resampling lookups for a chart from a calibrated camera.
For every output pixel: chart pixel_to_ray -> cam.project -> source pixel. valid
marks output pixels whose ray both exists in the chart and projects inside the camera's
model-valid cone; their map entries are set to -1 so cv2.remap leaves them blank.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cam
|
CameraModel
|
Any calibrated model implementing |
required |
chart
|
Chart
|
The output chart (e.g. :class: |
required |
Returns:
| Name | Type | Description |
|---|---|---|
mapx |
ndarray of shape (H, W), float32
|
Source-image |
mapy |
ndarray of shape (H, W), float32
|
Source-image |
valid |
ndarray of shape (H, W), bool
|
|
Source code in ds_msp/ops/reproject.py
solve_pnp ¶
solve_pnp(model: CameraModel, object_points: ndarray, image_points: ndarray, method: int = cv2.SOLVEPNP_ITERATIVE) -> Tuple[bool, Optional[np.ndarray], Optional[np.ndarray]]
Estimate pose from 3D-2D correspondences for any fisheye/omni model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
CameraModel
|
Any model implementing the contract. |
required |
object_points
|
(N, 3) world points.
|
|
required |
image_points
|
(N, 2) distorted pixels.
|
|
required |
Returns:
| Type | Description |
|---|---|
tuple
|
|
Source code in ds_msp/ops/pose.py
solve_pnp_ransac ¶
solve_pnp_ransac(model: CameraModel, object_points: ndarray, image_points: ndarray, *, thresh_px: float = 3.0, max_iters: int = 300, confidence: float = 0.999, seed: int = 0, refine: bool = True) -> Tuple[bool, Optional[np.ndarray], Optional[np.ndarray], np.ndarray]
Outlier-robust PnP for any camera model.
Unlike :func:solve_pnp (a single non-robust solve), this rejects gross-outlier
correspondences with RANSAC before estimating the pose, so a handful of mis-detected /
mismatched points don't drag the result. The pixels are unprojected through the model
(the same step :func:solve_pnp uses), then a RANSAC pose is fit on the normalized plane
(:func:ds_msp.geometry.resection.ransac_pnp_normalized — a plane homography for a coplanar
board, a 3x4 DLT otherwise); with refine=True the pose is polished on the consensus set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
object_points
|
(N, 3) world points.
|
|
required |
image_points
|
(N, 2) distorted pixels.
|
|
required |
thresh_px
|
inlier reprojection gate in pixels.
|
|
3.0
|
Returns:
| Type | Description |
|---|---|
tuple
|
|