Skip to content

7. API reference

Everything below is importable from nanofractal (import nanofractal as nf).

FractalDetector

FractalDetector(config, marker_size=-1.0, params=None)
  • config — "FRACTAL_2L_6", "FRACTAL_3L_6", "FRACTAL_4L_6" or "FRACTAL_5L_6"; anything else raises ValueError.
  • marker_size — side of the external marker's black square in your length unit; needed for a metric pose (-1: no scale).
  • params — a DetectorParams (copied; read and change it via .params).
method returns
detect(image, with_inner_points=False, roi=None, all_instances=False, prior=None) DetectionResult; with all_instances=True every copy of the marker, see instances; prior = the last detection, see Video
diagnose(image, roi=None) Diagnosis(result, n_contours, n_not_quad, quads, second_pass) — see Troubleshooting
detect_batch(images, num_threads=0, roi=None) list[DetectionResult] (no inner points, no prior; cell_px / contrast / bit_errors are None)
estimate_pose(result, camera_matrix, dist_coeffs, fisheye=False, full=False) (rvec, tvec, reproj_err), a Pose with full=True, or None
draw(image, result, camera_matrix=None, dist_coeffs=None, rvec=None, tvec=None, axis_length=None, inplace=True) the image drawn on
  • image: uint8 C-contiguous (H,W), (H,W,1) or (H,W,3) BGR.
  • roi: (x, y, width, height) inside the image; results are in full-image coordinates.
  • prior: a DetectionResult of this marker from a moment ago (full-image coordinates); quads where its levels were are read with a few wrong cells allowed (grids of 10+ cells). Used for this call only.
  • expected_side_px: (lo, hi), the outer level's side in pixels (from the height); quads of a level's expected size are read with a looser tolerance, and res.lookalikes lists Lookalike(corners, centre, level, border_errors, bit_errors, contrast) for those that still do not read (None without the hint). See Video.
  • num_threads=0: all cores.
  • estimate_pose: camera_matrix 3×3, dist_coeffs of length 4/5/8/12/14 (exactly 4 with fisheye=True); uses inner points when the result has ≥ 4, else the outer corners of every detected level; one outlier pass with ≥ 8 points; full=True returns Pose(rvec, tvec, reproj_err, method, n_points, n_inliers, reproj_err_rel, cov, rvec_alt, tvec_alt, reproj_err_alt); properties sd_tvec, sd_t, sd_rot_deg from cov.
  • draw needs a writable contiguous image when inplace=True; axis_length defaults to half marker_size.

Attributes: config, marker_size, params.

FractalTracker

FractalTracker(detector, margin=0.25, pad=16, auto_scale=False, scale_target_px=400, use_prior=False, prior_max_age=5, capture_frames=0)

auto_scale=True shrinks the searched region (detection_scale, 1 down to 0.35) so the largest level of the previous frame is about scale_target_px wide; only when the detector's own detection_scale is 1. use_prior=True passes the last non-empty result (at most prior_max_age frames old) as prior to detect. capture_frames=N (0 = off, else ≥ 2; implies use_prior): while there is no track, a quad within that tolerance of a level's code that stays in place for N - 1 frames is read with it as prior in the next one, see Video.

member
detect(image, with_inner_points=False, expected_side_px=None) like detector.detect, searching near the previous result
reset() forget the previous result
full_frame_detections how many frames needed a whole-frame search

DetectionResult

attribute type
ids int32 (N,) — level ids, 0 = external
corners float32 (N, 4, 2) — marker TL, TR, BR, BL in pixels
points_2d float32 (M, 2) or None — inner+outer image points
points_3d float32 (M, 3) or None — matching marker points, z = 0
points_level int32 (M,) or None — level id of each point
instances int32 (N,) or None — copy of each level (all_instances=True; 0 = the largest copy)
points_instance int32 (M,) or None — copy of each inner point
multiple_instances bool — a level was seen in two separate places (two copies of the marker); only the largest of each level is returned
inconsistent_ids int32 (K,) — levels dropped because they are not where the other levels put them
cell_px float32 (N,) — pixels per cell of each level
contrast float32 (N,) — mean bright minus mean dark cell, grey levels
bit_errors int32 (N,) — cells read wrong; > 0 only for levels accepted through prior

len(r), bool(r), for level_id, corners in r, readable repr; r.n_instances, r.instance(k) (copy k as its own DetectionResult). estimate_pose refuses a result with several copies — pass r.instance(k).

Diagnosis

attribute type
result the DetectionResult (same as detect)
n_contours contours traced (at least min_contour_size long)
n_not_quad of those, not a convex quadrilateral
quads list[QuadInfo]
second_pass True when the detection came from the second pass (params.close_pass); quads are then those of that pass

QuadInfo(corners, reason, cells, nearest_id, border_errors, bit_errors, contrast): corners float32 (4, 2) before sub-pixel refinement; reason one of "accepted", "duplicate", "border", "bits", "inconsistent"; cells the grid size (border included) and nearest_id the code it came closest to; border_errors frame cells read white; bit_errors inner bits that differ from nearest_id; contrast mean bright minus mean dark cell (grey levels).

DetectorParams

Fields min_contour_size, adaptive_block_size, adaptive_c, approx_poly_rate, subpix_win_size, kfilter_min_dist, detection_scale, close_pass — see Tuning.

Functions

function
generate_fractal(config, size_px=400, nested=True) uint8 (size_px, size_px) marker image
refine_corners(image, corners, win_size=5) float32 (N, 4, 2) refined corners
set_num_threads(n) / get_num_threads() threads per detect() call (n <= 0: all cores)
PoseSmoother(process_noise=1e-4, measurement_noise=1e-2, mode="kalman", gate=None, max_rejects=3) .update(rvec, tvec, t=None, reproj_err=None, n_points=None) -> (rvec, tvec), .reset(), .last_rejected; mode="ema" for a fixed gain

nanofractal.__version__ is the package version.

Command line

python -m nanofractal.bench [--resolution WxH] [--scene clean|perspective|clutter]
                            [--mode detect|inner|scale05] [--config FRACTAL_5L_6] [--frames N]