LYNX Python API Reference

Install golynx. Import lynx. Python 3.10 to 3.14.

1pip install golynx

Fifteen wheels: five interpreters across three platforms.

PlatformWheel tagInstall
Linux x86-64manylinux_2_34_x86_64pip install golynx
macOS Apple siliconmacosx_14_0_arm64pip install golynx
Windows x64win_amd64pip install golynx
Linux with CUDAgolynx-gpuextra index
Jetson JetPack 6golynx-jp6-1 / -jp6-2extra index

The GPU and Jetson builds are too large for PyPI and come from our own index:

1pip install golynx-gpu --extra-index-url <your beta index URL — provided at onboarding>

Quick start

No catalog models are available yet. Bringing your own ONNX model is the only way to run the SDK today. lynx.open("<slug>") appears throughout these pages and is the real API, but every catalog slug returns model_not_in_production until the catalog publishes — contact sales@synetic.ai for access.

Your own ONNX model:

1import lynx
2
3with lynx.open_standard("your-model.onnx") as model:
4 result = model.predict("street.jpg")
5
6 for det in result:
7 print(det.class_name, det.box.trust.confidence, det.depth.value)
8
9 result.show()

LYNX provides logic on top of trained models, so in order to separate measurements from the model and LYNX, measurements include their source.


The surface

Every public type in the lynx namespace, with its members and return types.

Model

Two ways in.

open

open() resolves a slug against the LYNX registry.

METHODopenclick to expand
open(slug="your-model-slug", *, version, tasks, confidence, goal, nms, seg_source, tiling, providers)

Model

A LYNX model carries several heads. One pass returns detection together with whichever of segmentation, depth, pose, orientation, classification, text and re-identification that model was built with, without running the image again.

Each head beyond detection costs a few milliseconds, so by default only the detection head runs. Enable the rest with tasks:

1model = lynx.open("your-model-slug", tasks=lynx.FrameTask.BOUNDING_BOX | lynx.FrameTask.DEPTH)

Disabling a head you are not reading is the cheapest throughput you will find.

A model opened by slug downloads on first use and is cached. Later runs re-download only if it changed. Pin version= to prevent that.

open_standard

open_standard() imports an ONNX model you already have.

METHODopen_standardclick to expand
open_standard(path, config=None, **opts)

Model

Properties the file declares are used as they stand. Everything else is deduced or declared through a Config. See Bring your own model.

An imported model ships no per class thresholds, so every class shares one. Pass a calibration set to probe_config to produce them.

Members

1model = lynx.open("your-model-slug", tasks=lynx.FrameTask.BOUNDING_BOX | lynx.FrameTask.DEPTH)
2
3print(model.slug, model.version, model.precision)
4print(model.providers) # (Provider.TENSORRT,)
5print(len(model.classes), "classes")
6
7result = model.predict("street.jpg")
8result, timing = model.predict_profiled("street.jpg")
9print(timing.total_us)
10
11model.close()

available_batch_sizes

tuple[int, ...] — Batch sizes that already have an engine

build_id

str — Exact build, for reproducing a result

capabilities

Capabilities — Which heads this model has

classes

ClassList — The taxonomy it was trained on

METHODcloseclick to expand
close()

None — Release the model and everything borrowed from it

license

LicenseInfo — Coverage and expiry

METHODpackageclick to expand
package(out, engines=None)

None — Write model and config as one .lnxp

precision

str — Weight precision in use

METHODpredictclick to expand
predict(image, **opts)

FrameResult — Run the model on one image

METHODpredict_batchclick to expand
predict_batch(images, **opts)

tuple[FrameResult, ...] — Run it on several at once

METHODpredict_profiledclick to expand
predict_profiled(image, **opts)

tuple[FrameResult, Timing]predict plus stage timings

METHODprepareclick to expand
prepare(batch_sizes)

None — Build engines now rather than on first use

providers

tuple[Provider, ...] — Runtimes it is executing on

slug

str — Registry name it was opened by

METHODstreamclick to expand
stream(camera_id=None, **opts)

Stream — Build a stateful stream over this model

version

str — Catalogue version actually loaded

predict options

OptionTypeEffect
confidencefloat or ConfidenceModeScore floor, or a calibrated operating point
max_detintCap on returned detections
tasksFrameTaskWhich heads to run. Detection only unless widened
retainExtentWhether to keep modal or amodal extent
nmsNmsModeOverride the model's declared NMS behaviour
ocrOcrOverride text recognition
channelsChannelOrderOverride the input channel order
seg_sourceSegSourceInstance masks, dense map, or whichever the model has
depth_gateDepthGateReject detections whose metric size is implausible
tilingTilingSlice the frame and run each tile. Overrides the model's setting
intrinsicsIntrinsicsCamera focal length and centre. Without it, distances come back relative
timestampfloatStamp the result rather than using the wall clock

stream options

OptionTypeEffect
temporalTrackedTaskWhich temporal heads to run
window_sfloatLength of the temporal window
queueintDepth of the input queue
dropDropPolicyWhat to shed when the queue is full
track_max_age_sfloatHow long a track survives without a match
track_min_hitsintMatches before a track is confirmed
scale_hold_sfloatHow long a recovered depth scale stays valid
weak_box_conffloatFloor for boxes the tracker may continue a track with
pulseRateBandSearch bounds for the pulse estimator
respirationRateBandSearch bounds for the respiration estimator

FrameResult

Iterating a FrameResult yields Detection. It is a Sequence[Detection], so len(result) and result[0] work directly.

1result = model.predict("street.jpg")
2
3print(len(result), "detections at", result.timestamp)
4
5if result.depth_map:
6 print(result.depth_at(640, 360).value, "m at centre")
7
8a, b = result[0], result[1]
9print(result.distance(a, b).value, "m apart")
10
11result.save("annotated.jpg")
12result.close()
METHODangleclick to expand
angle(vertex, a, b)

Measure — Degrees at vertex

camera_id

str \ — None — Label of the stream that produced it

classifications

tuple[Classification, ...] — Whole image labels

METHODcloseclick to expand
close()

None — Release the frame

METHODdepth_atclick to expand
depth_at(x, y)

Measure — Depth at one pixel

depth_map

DepthMap \ — None — Dense depth for the whole frame

detections

DetectionList — Everything found in the frame

METHODdistanceclick to expand
distance(a, b)

Measure — Metres between two detections

frame_index

int — Position in the stream, 0 for predict

METHODnormal_atclick to expand
normal_at(x, y)

tuple[float, float, float] \ — None — Surface normal at one pixel

normals_map

ndarray \ — None — Surface normals for the whole frame

METHODplotclick to expand
plot(...)

ndarray — Detections drawn onto the frame

METHODpoint_distanceclick to expand
point_distance(a, b)

Measure — Metres between two pixels

METHODsaveclick to expand
save(path=None)

str — Write the plot, returns the path

scene_text

SceneText \ — None — Text read from the frame

segmentation_map

SegmentationMap \ — None — Dense per pixel class labels

METHODshowclick to expand
show(path=None)

None — Open the plot in a viewer

source_image

ndarray \ — None — The frame as it went in

source_image_is_bgr

bool — Channel order of source_image

stream

Stream \ — None — The stream, when there was one

METHODsubmit_feedbackclick to expand
submit_feedback(image, correction)

None — Report a wrong result

timestamp

float — When the frame was taken

tracked

FrameResultTracked \ — None — Frame level tracking state

distance takes two Detection. point_distance takes two (x, y) pairs.

DetectionList

Sequence[Detection]. Indexable, sliceable, iterable, len().

FrameResultTracked

None unless a stream produced the result. Everything here needs more than one frame, which is why it lives on the tracked result rather than on FrameResult.

flow

ndarray \ — None

stream_id

int


Detection

1person = model.classes["person"]
2nose = person.keypoints["nose"] if person.has_pose else None
3
4for det in model.predict("street.jpg"):
5 print(det.class_name, det.box.trust.confidence)
6
7 if det.depth.value:
8 print(" ", det.depth.value, "m,", det.size_m.value, "m tall")
9
10 kp = det.keypoints[nose] if nose and det.class_name == "person" else None
11 if kp:
12 print(" nose at", kp.x)

A detection names its class but does not hand you the class object: reach it through model.classes. Keypoints index by KeypointDef, never by a raw integer, so a model upgrade that reorders the schema cannot silently move them.

amodal_box

Box \ — None — Full extent including the occluded part

METHODangleclick to expand
angle(vertex, a, b)

Measure — Degrees at vertex, between rays to a and b

METHODangle_atclick to expand
angle_at(vertex)

Measure — Degrees at a keypoint's declared pair

box

Box — Where it is, and how trusted

METHODbox_3dclick to expand
box_3d(intrinsics)

Box3D \ — None — Its 3D extent in camera space

class_id

int — Numeric class, matches Class.id

class_name

str — Human readable class

cls

Class — The full class definition

depth

Measure — Metres from the camera

METHODdistanceclick to expand
distance(other)

Measure — Metres to another detection

embedding

ndarray \ — None — Identity vector for matching across cameras

keypoints

Sequence[Keypoint] — Pose points, in schema order

occlusion

Measure — How much of it is hidden

METHODposition_3dclick to expand
position_3d(intrinsics)

Point3D \ — None — Where it is in camera space

segmentation

Mask \ — None — Its outline, not just its box

size_m

Measure — Metric extent of the object

tracked

DetectionTracked \ — None — Identity and history, streams only

METHODvolumeclick to expand
volume(intrinsics)

Measure — Cubic metres, needs camera intrinsics

METHODweightclick to expand
weight(intrinsics)

Measure — Kilograms, from volume and class density

yaw

Measure — Degrees of rotation about the vertical

angle takes three KeypointDef, vertex first, matching FrameResult.angle. angle_at takes one and uses the angle_pair declared on it.

box.angle is the oriented-box heading and is a different quantity from both.

depth is metres from the camera. size_m is the object's metric extent, also metres. yaw is degrees. Read depth.trust.source to know whether the distance rests on a measured focal length or an assumed one.


DetectionTracked

None when the detection matched no track. Always None on predict().

age_s

float

approach

Reading \ — None

METHODapproach_pairclick to expand
approach_pair(other, intrinsics)

ApproachPair \ — None

behavior

LabelReading \ — None

METHODcrossedclick to expand
crossed(line)

Cross

METHODdwell_sclick to expand
dwell_s(z)

float

global_id

int \ — None

heading

Reading \ — None

id

int

lifecycle

TrackState

pulse

Reading \ — None

respiration

Reading \ — None

speed

Reading \ — None

METHODzoneclick to expand
zone(z)

ZoneState

speed is metres per second. heading is degrees, 0 is +x rotating toward +y. Both are camera relative, so on a moving mount they include the camera's own motion.

approach is the closing rate on the camera. approach_pair is the closing rate between this subject and another, which is a different quantity: two objects moving in parallel at the same speed have high individual speed and zero closing rate.

id is unique within a stream. global_id is unique across a StreamManager with cross_camera enabled.

pulse requires a pose model. It reads a forehead located from the eyes, so both eyes must be present, confident and far enough apart, and there is no fallback to cropping the box. A model that cannot say where the eyes are cannot have a pulse measured.

respiration needs no landmarks. A torso is a box shaped thing, so it works on any model that detects one.

Both are windowed. A reading that has been established once is held when a later window is too short, too sparsely sampled, or too disturbed by movement, and age_s on the Reading says how stale it is. They return None only when nothing was ever established.


ApproachPair

Closing behaviour between two tracked subjects. Returned by DetectionTracked.approach_pair.

attached

bool — The two are moving as one system, a load on a vehicle

basis

ApproachBasis — What the geometry was computed from

bucket

ApproachBucket — The banded verdict. Act on this

closest_approach

ClosestApproach — Where they end up if both hold course

separation

Measure — The gap now

trust

Trust — About the pairing, not about any one number

ClosestApproach

separation

Measure

time

Measure

Three numeric quantities, and they do not share a provenance, which is why each carries its own Measure rather than one covering the set.

separation is a measurement off two positions. It always resolves and is the best conditioned of the three.

closest_approach.separation is a prediction and needs both velocities. As the closing rate approaches zero it tends toward the current gap and stays finite.

closest_approach.time takes the same inputs plus whether they meet at all, and runs to infinity where the closing rate does not. One shared margin across the three would have to be the worst of them, so the gap you can always measure would carry the uncertainty of a prediction that may not exist.

trust is about the pairing. It qualifies bucket, attached and basis, the same way Box carries one trust over its extent.

bucket is the output to act on. Nobody acts on "3.2 seconds", they act on "closing fast", and banding also makes the error compounding moot: dividing a distance by a closing rate roughly halves the precision of both.

attached says the two are one moving system rather than two converging ones. A forklift and the pallet it carries have zero relative velocity and overlapping extents, and their collision geometry is the union of the two rather than either box.

Both predictions are straight line extrapolations. Over half a second that holds. Over three seconds people and vehicles turn, and the numbers stop meaning anything.

A pair with no prediction reports None rather than zero. Zero reads as "certainly not approaching", which is the opposite of "we could not say".


Stream

METHODadd_lineclick to expand
add_line(a, b, name=None, ref=ZoneRef.BASE)

Line

METHODadd_zoneclick to expand
add_zone(polygon, name=None, ref=ZoneRef.BASE)

Zone

camera_id

str \ — None

METHODcloseclick to expand
close()

None

model

Model

METHODon_behaviorclick to expand
on_behavior(label, hold_s)

decorator

METHODon_dwellclick to expand
on_dwell(zone, threshold_s)

decorator

METHODon_lineclick to expand
on_line(line=None)

decorator

METHODon_trackclick to expand
on_track()

decorator

METHODon_zoneclick to expand
on_zone(zone=None)

decorator

METHODprocessclick to expand
process(frame, timestamp=None)

FrameResult

stream_id

int

temporal

TrackedTask

tracking

TrackOpts

window_s

float

tracking reads back the options the stream is actually running. Zero means "use the default" per field, so the values you passed in are not necessarily the values in force.

weak_box_conf lets the tracker continue a track through a frame where the detector's score dipped below threshold. A weak box exactly where a confirmed track was predicted is much more likely real than the same box in empty space, which is why this is not the same as lowering confidence: that would admit weak boxes everywhere, including where there is no track to continue.

Weak boxes never start a track and are never returned to you. They exist to keep an id alive across a gap.

ref decides which point of a box is tested against the geometry: ZoneRef.BASE uses the bottom centre, ZoneRef.CENTRE uses the box centre.

Passing no zone to on_zone, or no line to on_line, registers for all of them.

RegistrationFires
on_zoneZONE_ENTERED, ZONE_EXITED
on_dwellDWELL, once per subject per visit
on_lineLINE_CROSSED
on_trackTRACK_CONFIRMED, TRACK_LOST
on_behaviorBEHAVIOR, once per continuous hold

Zone

id

int

name

str \ — None

polygon

ndarray

ref

ZoneRef

Line

a

tuple[float, float]

b

tuple[float, float]

id

int

name

str \ — None

ref

ZoneRef

Cross.FORWARD is left to right when walking from a to b.

Event

box

Box \ — None

class_id

int

class_name

str

detection

Detection \ — None

direction

Cross

dwell_s

float \ — None

kind

EventKind

label

str \ — None

line

Line \ — None

timestamp

float

track_id

int

value

float

zone

Zone \ — None


StreamManager

1manager = lynx.StreamManager()
2manager.add(model.stream(camera_id="north"), "rtsp://north/live")
3manager.add(model.stream(camera_id="south"), "rtsp://south/live")
4manager.cross_camera(True, threshold=0.7, confirm=3)
5
6for result in manager:
7 for det in result:
8 if det.tracked and det.tracked.global_id:
9 print(result.camera_id, det.tracked.global_id)
METHODaddclick to expand
add(stream, source)

None

METHODcloseclick to expand
close()

None

METHODcross_cameraclick to expand
cross_camera(enabled, threshold, confirm)

None

METHOD__iter__click to expand
__iter__()

Iterator[FrameResult]

METHODstartclick to expand
start(callback)

None

METHODstopclick to expand
stop()

None

streams

tuple[Stream, ...]


Lifetime

Three rules cover every borrowed object in the SDK.

Results from the StreamManager iterator expire on the next iteration. Reading an expired result raises lynx.errors.ResultExpired. Copy anything you need to keep before advancing.

Event handlers fire inside process() on the calling thread. Event.detection is valid for the duration of that call only.

Model, Stream, StreamManager, FrameResult, Camera, VideoWriter and Magnifier all hold native resources and all expose close(). All of them work as context managers.

1with lynx.open("your-model-slug") as model:
2 with model.predict("street.jpg") as result:
3 ...

Measurement types

Trust

Carried by Box, Measure, Mask and Keypoint. Every one of them answers the same question: how much of this number came from the model, and how much came from something the SDK inferred.

confidence

float

margin

float \ — None

raw

float

size_basis

SizeBasis \ — None

size_check

SizeCheck \ — None

source

Source

raw is the model's score before calibration. confidence is after. On a model opened in ConfidenceMode.NON_CALIBRATED the two are equal.

confidence and margin are different quantities. A depth has both. A box has a confidence and no margin.

margin is plus or minus in the value's own units, metres for a depth and degrees for an angle. None when nothing reports one, never 0, because 0 reads as exact.

raw is the value before the SDK adjusted it, and is always a real number. Where nothing was adjusted it equals the adjusted value.

derivations is the chain that produced the number. source is its last step.

source says where the number came from, and on a distance it also says what the units are. Read it before treating a distance as metres.

sourceWhere it came fromDistance units
TRAINEDA depth head emitted itmetres
TRAINED_RELATIVEA depth head on a relative scale, not absolute unitsnone available
TRAINED_SIZEA metric size head emitted itmetres
TRAINED_RANGEA range head emitted itmetres
DERIVED_DEPTHRecovered from the depth mapmetres
DERIVED_DECLARED_HEIGHTA known dimension plus a real focal lengthmetres
DERIVED_ASSUMED_FOCALA known dimension plus an assumed lensmetres, approximate
DERIVED_POPULATIONSeveral instances of one deformable classmetres, fair
DERIVED_ASSUMED_POSTUREA deformable class assumed to be in its usual posturemetres, approximate

Under DERIVED_ASSUMED_FOCAL the SDK assumed a normal lens at roughly 60 degrees horizontal field of view. Ordering and ratios between objects are correct, and the absolute scale carries the error of that assumption. margin widens to reflect it. Supply intrinsics to replace the assumption with your real lens.

Size is not affected. size_m is metric under every source, because the focal length cancels out of it. Only distance depends on knowing the focal length.

Measure

trust

Trust

value

float \ — None

value is None when there is no measurement. trust is always present, and trust.source says why.

Box

Coordinates are source pixels.

angle

float \ — None

center

tuple[float, float]

h

float

trust

Trust

w

float

x

float

x1

float

x2

float

y

float

y1

float

y2

float

x and y are the centre. x1, y1, x2, y2 are the corners.

angle is None when the model has no orientation head, and 0.0 when the model measured the box and found it axis aligned.

Other geometry

TypeMembers
Box3Dcenter, width, height
Point3Dx, y, z
Intrinsicsfx, fy, cx, cy
Maskxy, trust
SegmentationMapclass_ids, confidence, shape

Mask.xy is an (N, 2) polygon in source pixels. Intrinsics is the one thing in this list you supply rather than receive.

DepthMap

METHODatclick to expand
at(x, y)

Measure

height

int

metric

bool

scale

float \ — None

scale_age_s

float

scale_anchors

int

scale_rejected

int

scale_se

float \ — None

scale_undeclared

int

shape

tuple[int, int]

width

int

Metric depth is recovered per frame from objects of declared size. The scale_* fields report that recovery: how many candidate anchors were found, how many were rejected as inconsistent, how many detections had no declared size to contribute, and how old the scale in force actually is.

scale_age_s is 0.0 when the scale came from this frame. A non zero value means the scale is being held from an earlier frame under scale_hold_s.

Reading

A windowed estimate. It composes a Measure rather than restating one: the value and its trust both come from measure, and the rest says what window produced it.

age_s

float

measure

Measure

reason

VitalReason

samples

int

window_s

float

1r = det.tracked.pulse
2r.measure.value # the rate
3r.measure.trust.source # whether it came off a held estimate
4r.measure.trust.margin # plus or minus, when stated
5r.age_s, r.samples # how fresh, and from how many frames

reason says why a reading is what it is, and is the field to read when one is absent or stale rather than inferring it from age_s alone.

LabelReading

The categorical counterpart to Reading. It carries a Trust directly rather than composing a Measure, because a label has no value to be uncertain about.

age_s

float

label

str

trust

Trust

window_s

float

trust.margin is always None. A plus or minus on a categorical label is not a quantity, and that is the honest answer rather than an omission.

trust.source is what distinguishes a label served from a held estimate from one computed on this frame. age_s says the reading is old; source says it was never recomputed.

A Reading is a windowed estimate, not a per frame value. window_s is the window it was computed over, age_s is how long ago that window closed, and samples is how many frames contributed.

LabelReading is the categorical counterpart and does not compose a Measure, because a label has no value to be uncertain about.

measure.trust.margin is plus or minus on the rate itself. None means unstated rather than broken: a falling confidence says a reading is ageing, and margin says how precise it ever was.

age_s is 0.0 for a reading computed from the current window. A non zero value means the estimator could not produce a fresh one and is holding the last established reading. Treat a growing age_s as the signal that conditions have degraded, since the value itself will not change.

RateBand

Passed as the pulse or respiration option to stream().

filter_max_per_min

float

filter_min_per_min

float

max_age_s

float

min_confidence

float

The filter fields bound what the estimator searches, not what is clinically normal. Widening them costs accuracy.

DepthGate

Passed as the depth_gate option to predict(). Rejects detections whose recovered metric size falls outside the class size band.

METHODresetclick to expand
reset()

None

stats

dict


Classes and keypoints

1nose = model.classes["person"].keypoints["nose"] # KeypointDef
2det.keypoints[nose.index] # Keypoint
TypeMembers
KeypointDefname, group, index, cls, neighbours, mirror, angle_pair
Keypointx, y, name, present, trust
SizeBandclass_id, p1, median, p99
SizeDimensionsclass_id, length, width, height, height_stable, have_length, have_width, have_height

Detection.keypoints indexes by position. A name resolves through the class:

Keypoint.present means the decode located the keypoint. It is not a confidence threshold. A present keypoint can still have low trust.confidence.

SizeBand is the observed size distribution for a class, in metres. SizeDimensions is its declared physical extent, with a have_* flag per axis because not every class has all three.


Class

One class in the model's taxonomy. Returned by ClassList lookups — model.classes["person"].

dimensions

SizeDimensions \ — None

has_pose

bool

id

int

METHODkeypointclick to expand
keypoint(name)

KeypointDef

keypoints

KeypointSchema

name

str

size_band

SizeBand \ — None

id is the class id the model emits, and is what Detection.class_id holds. It is not the position of the class within ClassList.

name is the catalogue name, and is what Detection.class_name holds.

has_pose is whether the class declares keypoints. When it is False, keypoints is empty and so is Detection.keypoints for that class.

keypoints is the schema: which keypoints the class declares, their order, and how they connect. keypoint(name) is the single lookup, equivalent to keypoints[name].

size_band is how large members of the class are observed to be, in metres, as p1, median and p99. It is what a DepthGate tests against and what makes SizeCheck meaningful.

dimensions is the class's declared physical extent, in metres, with a have_* flag per axis because not every class declares all three. This is the input to metric depth: a detection of a class with a declared height is a scale anchor.

height_stable gates whether the class may anchor a scale, not how good the measurement is. A seated person is not a short person, so a class whose height varies with posture is excluded rather than allowed to poison the scale for the whole frame. An undeclared class contributes nothing at all, deliberately: a guessed focal length would be wrong for every object in the frame instead of one.

size_band and dimensions come from the catalogue on a catalogue model. On an imported model they are None until you declare them with lynx_size_dims. See Bring your own model.

ClassList

Returned by Model.classes. A Sequence, built on first access and cached for the life of the model.

1model.classes["person"] # Class
2model.classes[det.class_id] # Class, by class id
3model.classes.names # ('person', 'car', ...)
4
5for cls in model.classes:
6 print(cls.id, cls.name)

[id]

Class

[name]

Class

[slice]

tuple[Class, ...]

METHODgetclick to expand
get(key, default=None)

Class \ — None

METHODlenclick to expand
len()

int

names

tuple[str, ...]

Iterating yields Class.

Subscripting raises on a miss: UnknownClass for an unknown name, IndexError for an unknown id. get raises neither and returns default.

A slice returns a plain tuple. The result has no name lookup and no names.

names is rebuilt on every access, so read it once rather than in a loop.

Indexing is by Class.id, so model.classes[det.class_id] is correct by construction. Iteration walks the classes in order and is unaffected by gaps in the id space.


KeypointSchema

Returned by Class.keypoints. Same shape as ClassList, keyed over the keypoints a class declares.

1schema = model.classes["person"].keypoints
2
3if "nose" in schema:
4 det.keypoints[schema["nose"].index]

[index]

KeypointDef

[name]

KeypointDef

[slice]

tuple[KeypointDef, ...]

METHODgetclick to expand
get(key, default=None)

KeypointDef \ — None

in

bool

METHODlenclick to expand
len()

int

names

tuple[str, ...]

Iterating yields KeypointDef.

Subscripting raises NotFound for an unknown name and IndexError for an out of range index. get returns default instead.

Here the index is the keypoint's declared position, and matches KeypointDef.index and the ordering of Detection.keypoints.

Scene text

TypeMembers
SceneTexttext, lines, blocks, vertical_text, json, to_dict

SceneText is the frame level grouped read. Detection carries no per object text.


Capabilities

What the model can do. Returned by Model.capabilities.

1if lynx.FrameTask.DEPTH in model.capabilities.tasks:
2 ...

nms_free

bool

pr_curves

bool

tasks

FrameTask

temporal

TrackedTask

tasks and temporal are flag enums, so test with in.

tasks is what the model actually has, and is the thing to branch on rather than assuming a head is present.

pr_curves is True when the model ships calibration curves, which is what makes the CALIBRATED_* confidence modes meaningful.


LicenseInfo

Returned by Model.license.

expires_at

int

status

LicenseStatus

expires_at is Unix epoch seconds.


ModelEntry

One row of the registry. Returned by available_models.

available

bool

class_count

int

latest_version

str

license_tier

str

licensed

bool

name

str

openable

bool

public_trial

bool

slug

str

licensed is whether your licence covers it. available is whether it is published. openable is whether open() will succeed right now, which is the one to test.


Timing

Returned by Model.predict_profiled.

inference_us

float

postprocess_us

float

preprocess_us

float

tiles

int

total_us

float

Microseconds. total_us is the wall time for the call and is not the sum of the other three.

tiles is how many forward passes actually ran, and 0 when the frame ran whole. Without it, 520 ms of inference cannot be told apart as one slow forward or eight ordinary ones.


Bring your own model

open_standard takes a path instead of a slug. It reads ONNX graphs and .lnxp packages, and dispatches on the file's magic rather than its extension.

1model = lynx.open_standard("your-model.onnx")

That works when the file declares enough about itself. Most do not, which is why the rest of this section exists.

Why there is a configuration

An ONNX file states the shape of its outputs. It does not state what they mean. Given a [300, 6] tensor, nothing in the file separates one detection per row from the transpose, box4, score, class_id from box4 plus two class scores, corner boxes from centre form boxes, or coordinates in the letterboxed input from coordinates already mapped back to the source.

Every wrong reading produces plausible boxes, not an error. Boxes on roughly the right objects, slightly wrong, with confident scores. Getting lynx_box_space wrong on a real export measured at IoU 0.22 where the correct reading gave 0.99, and nothing in either run reported a problem.

So every key is declared, never defaulted.

Probe

probe_config runs the real pipeline over your model and returns the configuration document.

1config = lynx.probe_config("your-model.onnx", "frame.jpg")
InputSettles
Model onlyOutput layout, fused columns, dense regression, from declared shapes
Model and imageBox format and coordinate space, by scoring full runs against each other
Model, image, and a marked boxCoordinate space in the one case that cannot be proven otherwise

The image must be non-square. Letterbox and stretch agree exactly on a square frame, so a square probe image cannot separate them. Probe reports that rather than picking one.

Probe does not guess. A field it cannot settle comes back unresolved, with what would settle it, because a guessed key is indistinguishable from a fact once it is written to the file.

A value your model already declares is carried through as DECLARED. Where observation contradicts it the field becomes CONFLICT and the declared value still wins. That disagreement is usually a real bug in the export, and silently correcting it hides the thing most worth seeing.

Reviewing what probe decided

Config subclasses dict, so it prints, serialises and indexes like the document it is.

1config["lynx_box_space"] # 'input_px'
2config.provenance("lynx_box_space") # Provenance.DEDUCED
3config.margin("lynx_box_space") # 0.34, how close the call was
4config.detail("lynx_box_space") # why, and what would settle it
5
6config["lynx_box_space"] = "orig_px" # yours now, probing will not overwrite it
7config.save("your-model.lynx.json")
8
9model = lynx.open_standard("your-model.onnx", config)
METHODConfig.loadclick to expand
Config.load(path)

Config

METHODConfig.parseclick to expand
Config.parse(text)

Config

METHODdetailclick to expand
detail(key)

str \ — None

get, keys, [key]

as dict

METHODmarginclick to expand
margin(key)

float

METHODprovenanceclick to expand
provenance(key)

LogLevelINFO, WARNING, ERROR

VitalReason

Why a rate reading is absent, held, or fresh

Provenance

METHODsaveclick to expand
save(path)

str

METHODthresholdsclick to expand
thresholds()

dict[str, float]

METHODto_dictclick to expand
to_dict()

dict

METHODto_jsonclick to expand
to_json()

str

METHODunresolvedclick to expand
unresolved()

tuple[tuple[str, str], ...]

margin is 0 to 1, and reports how close a deduced call was. A field decided by a hair is worth reading even when nothing reports a problem.

Keys that come back AMBIGUOUS or CONFLICT appear in unresolved() as (key, why) pairs. It is a method, unlike names and thresholds beside it.

Configuration keys

KeyValues
lynx_output_layoutseparate, fused_rows, fused_cols, dense
lynx_fused_columnsscore_class, class_scores
lynx_box_formatxyxy, cxcywh
lynx_box_spaceinput_px, orig_px, norm_input
lynx_output_mapRole list. A fused layout is ["detection"]
lynx_num_classesint
lynx_img_sizeint or [h, w]
lynx_class_nameslist[str]
lynx_user_classesNames to expose. Absent means expose all
lynx_size_dimsPer class physical dimensions, keyed by class id

lynx_box_space is the field that fails most quietly. The SDK applies its inverse letterbox on your word. Declare input_px for a graph that already un letterboxed internally and the transform runs twice.

Declaring class sizes

Without dimensions, an imported model has no metric size, no SizeCheck and no DepthGate, and distances rest on an assumed lens. Declare them and all four work.

1config["lynx_size_dims"] = {"by_class_id": {
2 "0": {"height_m": [0.75, 1.70, 2.05], "height_stable": True},
3 "5": {"height_m": [2.80, 3.20, 3.60], "height_stable": True}}}

height_m is [p1, median, p99] in metres. The median is what the scale uses. Set height_stable to False for a class whose height depends on posture, and it will still be measured but will not anchor a scale.

The lookup is by class id, not by name. There is no name keyed size table inside the SDK.

Supply intrinsics to predict() as well and distances come back in metres. Without it they are correct for ordering and for ratios, but scaled by an unknown constant.

Dense heads

An export whose decode was stripped, as for INT8 quantisation, needs four more keys.

KeyValues
lynx_dense_regressiondirect for 4 box channels, dfl for 4 × bins
lynx_dfl_binsRequired when dfl
lynx_stridesFor example [8, 16, 32]
lynx_scores_logitsDefaults to 1. The sigmoid was part of what was stripped

The anchor grid is derived from lynx_strides and lynx_img_size, never declared, so a grid that disagrees with the tensor is caught instead of shifting every box by one level.

Autotune

autotune brute forces preprocessing over one image when probe leaves the choice open.

1tune = lynx.autotune("your-model.onnx", "frame.jpg")
2tune.best.channel_order, tune.best.resize_mode
3tune.lead # 1.02 means no real preference
TypeMembers
Autotunebest, lead, axis_lead(axis), iterable of Candidate
Candidatechannel_order, resize_mode, rotation_deg, score, n_detections, ok

best is None when no candidate produced detections, and also when the winner's decode kept every row, since noise still sorts and a ranking over noise is not a result.

lead is the ratio of the first candidate's score to the second, and a lead near 1.0 means the result is not a preference worth acting on. It reports the weakest axis, which understates the case where the grid was certain about one thing and undecided about another.

axis_lead(axis) gives the margin per axis. The top two candidates usually differ in one axis only, so a headline lead of 1.03 can sit alongside a rotation margin of 2.05.

Autotune is not a first resort. Its grid is channel order by rotation by resize, so a model whose column layout is undeclared cannot be fixed by it. Declare the metadata, probe the graph, and reach for autotune only when decode already works and the orientation or channel order is genuinely unknown. It costs sixteen forward passes.

Calibrating

A model you brought yourself has no per class thresholds, so every class uses the same one. Pass a validation folder and probe_config produces them in the same document.

1config = lynx.probe_config("your-model.onnx", "frame.jpg", val_dir="val/")
2config.thresholds() # {'person': 0.41, 'car': 0.33, ...}

The folder is standard YOLO layout: a val/ holding images/ and labels/.

Packaging

Four files and a runbook is how a fleet ends up running default thresholds while nobody notices. package writes the model and its configuration as one .lnxp.

1model = lynx.open_standard("your-model.onnx", config)
2model.package("your-model.lnxp")
3
4model = lynx.open_standard("your-model.lnxp") # nothing else needed

The model knows the file it was opened from and the config it was opened with, so neither is passed back in.

Engine prebuilding is TensorRT only. CoreML compiles per shape at load, and the ONNX Runtime CPU path has nothing to prebuild, so on those hosts engine_target() is empty and there is no engine to package.

1lynx.engine_target() # 'linux-aarch64-trt10.3-sm87'
2lynx.package_add_engine("your-model.lnxp", target, "engine.plan")
3lynx.package_inspect("your-model.lnxp") # segments, sizes, digests, targets

package_add_engine is the only way one package carries engines for more than one kind of hardware.

Limits

ONNX only. No .pt, no pickle, no framework dependency.

Detection layouts only. Pose, segmentation and depth on foreign models are not covered by the configuration vocabulary.

Everything that is not a signed .lnx opens with a non catalogue origin, so nothing keyed on catalogue conventions applies by default. Metric size, SizeCheck and DepthGate all need class dimensions, which a catalogue model carries and an imported one does not. Declare them yourself with lynx_size_dims and all three work.

When boxes look wrong

They will look plausible, so work through the declarations rather than the model.

  1. Run probe with a non-square image and read unresolved().
  2. Check lynx_box_space first.
  3. Compare against onnxruntime directly, preprocessing the image the way your configuration says: square letterbox for letterbox, plain resize for stretch.
  4. If the top detection is a different class than expected, check preprocessing before the decode. The same model under two letterbox conventions genuinely ranks detections differently.

Capture and output

1camera = lynx.camera_open(0)
2stream = model.stream(camera_id="north-gate")
3
4for frame in camera.frames():
5 result = stream.process(frame)
METHODcamera_openclick to expand
camera_open(...)

Camera

METHODvideo_writerclick to expand
video_writer(...)

VideoWriter

METHODmagnifierclick to expand
magnifier(...)

Magnifier

METHODdespeckleclick to expand
despeckle(image, ksize=3)

ndarray

METHODdepth_to_u8click to expand
depth_to_u8(result)

ndarray

TypeMembers
Cameraread, frames, actual_format, close
VideoWriterwrite, frames, finish, close
Magnifierprocess, reset, close

Camera.read returns one frame. Camera.frames is a generator. actual_format is what the device gave you, which is not always what was asked for.

despeckle and depth_to_u8 are frame helpers. depth_to_u8 turns a result's depth map into something displayable, and discards the metric values doing it.


Configuration

Process wide, and entirely optional. The defaults run without any of it.

You do not need an API key to try the SDK. It runs free for 30 days without one. Set a key to go past that, or to reach models your licence covers.

METHODset_apikeyclick to expand
set_apikey(key)

None

METHODset_cache_dirclick to expand
set_cache_dir(path)

None

METHODset_device_nameclick to expand
set_device_name(name)

None

METHODset_workersclick to expand
set_workers(*, gpus=None, cpus=0)

None

METHODset_telemetry_enabledclick to expand
set_telemetry_enabled(enabled)

None

METHODset_feedback_enabledclick to expand
set_feedback_enabled(enabled)

None

METHODset_diagnostic_callbackclick to expand
set_diagnostic_callback(fn)

None

METHODshutdownclick to expand
shutdown()

None

Environment variableEffect
LYNX_API_KEYModel download credential
LYNX_CACHE_DIRWhere the SDK may write
LYNX_TELEMETRY0 disables usage telemetry

The environment variables are read at import. The setters override them.

Warnings print to stderr by default. set_diagnostic_callback(fn) routes them to your own handler as a Diagnostic with a stable code, a level, a message and typed fields, so you can branch on one without matching English prose. set_diagnostic_callback(None) silences them.

A notice with no code yet reports DiagCode.UNSPECIFIED, which means no contract has been stated for it, not that nothing happened.

A diagnostic states what you can act on. It will not tell you how the SDK reached a conclusion, only what it concluded and what you can do about it.

Inspecting the environment

METHODversionclick to expand
version()

str

METHODavailable_modelsclick to expand
available_models(scope=ModelScope.AVAILABLE)

tuple[ModelEntry, ...]

METHODavailable_providersclick to expand
available_providers()

tuple[Provider, ...]

METHODprovider_nameclick to expand
provider_name(p)

str

METHODcuda_device_countclick to expand
cuda_device_count()

int

available_models returns what this API key can open. Pass ModelScope.ALL to see the full catalogue including models the licence does not cover, which is what ModelEntry.licensed and .openable report on.


Errors

All under lynx.errors.

ExceptionRaised when
NotFoundBase class for the below
ModelNotFoundThe slug or path does not resolve
AuthThe API key was rejected
NetworkThe registry was unreachable
PermissionThe licence does not cover this
ResultExpiredA borrowed result was read after expiry

Enums

UNSET is 0 on every enum that lands in a struct, and means nobody wrote there. Python reports it as None wherever it describes an absence rather than a state.

EnumMembers
ChannelOrderAUTO, AUTO_LOCK, RGB, BGR
ConfidenceModeNON_CALIBRATED, CALIBRATED_MAX_RECALL, CALIBRATED_BALANCED, CALIBRATED_MAX_PRECISION
CrossUNSET, FORWARD, BACKWARD
DropPolicyDROP_OLDEST, DROP_NEWEST, LATEST_ONLY
EventKindUNSET, ZONE_ENTERED, ZONE_EXITED, DWELL, LINE_CROSSED, TRACK_CONFIRMED, TRACK_LOST, BEHAVIOR
ExtentMODAL, AMODAL
GoalLATENCY, BALANCED, THROUGHPUT
LicenseStatusUNSET, VALID, EXPIRED, UNKNOWN
MagnifyModeMOTION, COLOR
ModelScopeAVAILABLE, ALL
NmsModeAUTO, ON, OFF
OcrAUTO, ON, OFF
LogLevelINFO, WARNING, ERROR
VitalReasonWhy a rate reading is absent, held, or fresh
ProvenanceDECLARED, DEDUCED, ASSUMED, AMBIGUOUS, CONFLICT, ABSENT
ProviderCPU, CUDA, TENSORRT, COREML, OPENVINO
ResizeModeLETTERBOX, STRETCH, STRIDE_LETTERBOX
SegSourceAUTO, DENSE, INSTANCE
TilingAUTO, ON, OFF
ApproachBasisWhat the approach geometry was computed from
ApproachBucketBanded closing verdict
AutotuneAxisCHANNEL_ORDER, ROTATION, RESIZE_MODE
SizeBasisUNSET, HEIGHT, FOOTPRINT, ORIENTED, BAND
SizeCheckUNSET, OK, TOO_SMALL, TOO_LARGE, NO_BAND, NO_SCALE
SourceUNSET, TRAINED, TRAINED_RELATIVE, TRAINED_SIZE, TRAINED_RANGE, DERIVED_DEPTH, DERIVED_DECLARED_HEIGHT, DERIVED_ASSUMED_FOCAL, DERIVED_POPULATION, DERIVED_ASSUMED_POSTURE
FrameTaskBOUNDING_BOX, ORIENTED_BOUNDING_BOX, AMODAL_BOX, SEGMENTATION, INSTANCE_SEGMENTATION, POSE, DEPTH, CLASSIFICATION, TEXT_RECOGNITION, REID, YAW_3D, METRIC_SIZE, RANGE, DENSITY
TrackedTaskPULSE, RESPIRATION, BEHAVIOR, OPTICAL_FLOW
TrackStateUNSET, NEW, TENTATIVE, CONFIRMED, LOST
ZoneRefBASE, CENTRE
ZoneStateUNSET, OUTSIDE, INSIDE, ENTERED, EXITED

What None means

None is always an absence, never a zero. A member that has a value but a bad one reports that through trust, not by going None.

Detection.tracked

The detection matched no track

Detection.amodal_box

The model emits no amodal extent, or FrameTask.AMODAL_BOX was not enabled

FrameResult.tracked

No stream produced the result

FrameResult.stream

The result came from predict()

FrameResult.depth_map

The model has no depth head, or FrameTask.DEPTH was not enabled

Box.angle

The model has no orientation head, or FrameTask.ORIENTED_BOUNDING_BOX was not enabled

Measure.value

There is no measurement

Trust.margin

Nothing reports one for this quantity

DetectionTracked.speed

There is no scale to convert with

DetectionTracked.heading

The subject is stationary

DetectionTracked.pulse

No pose model, no eyes visible, or no reading ever established

DetectionTracked.respiration

No reading ever established

DetectionTracked.global_id

The subject has been seen in one camera only

DepthMap.scale

No anchor was recovered this frame

DepthMap.scale_se

Fewer than two anchors

Autotune.best

No candidate produced detections, or the ranking was over noise


Complete surface

Everything the SDK exports appears here; the sections above explain when to reach for it.

Module functions

__version__, __commit__, __build_number__, open, open_standard, probe_config, engine_target, package_add_engine, package_inspect, despeckle, depth_to_u8, camera_open, video_writer, magnifier, version, set_apikey, set_device_name, set_cache_dir, set_telemetry_enabled, set_feedback_enabled, set_diagnostic_callback, set_workers, cuda_device_count, available_providers, provider_name, available_models, shutdown, autotune, errors

Model and results

typemembers
Modelavailable_batch_sizes, build_id, capabilities, classes, close, license, ocr, ocr_batch, ocr_step, ocr_upscale_target, ocr_win, package, precision, predict, predict_batch, predict_profiled, prepare, providers, size, slug, stream, version
FrameResultangle, camera_id, classifications, close, density, density_count, depth_at, depth_map, detections, distance, frame_index, normal_at, normals_map, plot, point_distance, save, scale_info, scene_text, segmentation_map, show, source_image, source_image_is_bgr, stream, submit_feedback, timestamp, tracked
FrameResultTrackedflow, flow_confidence, stream_id
Detectionamodal_box, angle, angle_at, at, box, box_3d, class_id, class_name, contour, depth, derived_amodal, distance, embedding, index, keypoints, occlusion, position_3d, range, result, root, size_m, surface, tracked, volume, weight, yaw
DetectionTrackedage, approach, approach_pair, behavior, crossed, dwell, global_id, heading, id, lifecycle, pulse, respiration, speed, zone
DetectionList
Classificationclass_id, class_name, confidence

Streaming and events

typemembers
Streamadd_line, add_zone, camera_id, close, handler_errors, model, on_behavior, on_dwell, on_line, on_track, on_zone, process, stream_id, temporal, window
StreamManageradd, close, cross_camera, start, stop, streams
Eventbox, class_id, class_name, detection, direction, dwell, kind, label, line, timestamp, track_id, value, zone
Zonename
ZoneRefBASE, CENTRE
Linename
RateBandfilter_max_per_min, filter_min_per_min, max_age, min_confidence
Readingage, confidence, reason, samples, value, window

Bring your own model

typemembers
Configdetail, get, keys, load, margin, parse, provenance, save, thresholds, to_dict, to_json, unresolved
Autotunebest, lead
Candidatechannel_order, n_detections, ok, resize_mode, rotation_deg, score, status
Capabilitiesnms_free, pr_curves, tasks, temporal
ModelEntryavailable, class_count, latest_version, license_tier, licensed, name, openable, public_trial, slug
LicenseInfoexpires_at, status

Geometry and measurement

typemembers
Boxangle, center, h, trust, w, x, x1, x2, y, y1, y2
Box3Dcenter, height, width
Pointby_track, kind, part, subject, x, xy, y
Point3Dmargin_x, margin_y, margin_z, x, y, z
Measuretrust, value
Trustconfidence, derivations, margin, raw, size_basis, size_check, source
Masktrust, xy
SegmentationMapclass_ids, confidence, shape
DepthMapat, height, metric, scale, scale_age, scale_anchors, scale_rejected, scale_se, scale_undeclared, shape, width
Keypointname, present, trust, x, y
KeypointList
KeypointDefangle_pair, cls, group, index, mirror, name, neighbours
KeypointSchemaget, names
Classdimensions, has_pose, id, keypoint, keypoints, name, size_band
ClassListget, names
SizeDimensionsclass_id, have_height, have_length, have_width, height, height_stable, length, may_anchor, referent_risk, width

Text and OCR

typemembers
SceneTextblocks, json, lines, text, to_dict, vertical_text
LabelReadingage, confidence, label, window
OcrAUTO, OFF, ON

Capture and output

typemembers
Cameraactual_format, close, frames, read
VideoWriterclose, finish, frames, write
Magnifierclose, process, reset

Enums and everything else

typemembers
Contouris_hole, mask, parent, trust
PointKindKEYPOINT, NEAREST, ROOT, XY
Intrinsicscx, cy, fx, fy
ScaleInfoanchors, deformable, edge_clipped, focal, focal_se, rejected, source, undeclared
ApproachPairattached, basis, bucket, closest_approach, confidence, separation
ClosestApproachreason, separation, time
DensityMapchannels, class_ids, h, shape, values, w
ApproachCLEAR, CLOSING, IMMINENT
PairReasonALREADY_SEPARATING, ATTACHED, OUTSIDE_PREDICTION_WINDOW, PARALLEL, PREDICTED
ApproachBasisMOTION, NO_VELOCITY, STILL
VitalReasonBELOW_CONFIDENCE, NONE, NOT_REQUESTED, NOT_SKIN, NO_FACE, NO_SOURCE, NO_SUBJECT, SUBJECT_MARGINAL, SUBJECT_TOO_SMALL, TOO_MUCH_MOTION, WARMING_UP
ScaleAUTO, BALANCED, PERMISSIVE, STRICT
SizePenaltyAUTO, OFF, ON
ReferentRiskBROAD, NARROW, SHORTHAND, SPECIFIC, UNKNOWN_CLASS, UNSET
ModelSizecategory, disk_bytes, num_params
Timinginference_us, postprocess_us, preprocess_us, total_us
Confidencebalanced, max_precision, max_recall, mode, raw, value
SizeBandclass_id, median, p1, p99
AutotuneStatusDECODE_DEGENERATE, DECODE_FAILED, FORWARD_FAILED, LAYOUT_UNKNOWN, NOT_ATTEMPTED, OUTPUT_UNREADABLE, OUT_OF_MEMORY, PREPROCESS_FAILED, RAN
DepthGatereset, stats
FrameTaskAMODAL_BOX, BOUNDING_BOX, CLASSIFICATION, DENSITY, DEPTH, INSTANCE_SEGMENTATION, METRIC_SIZE, ORIENTED_BOUNDING_BOX, POSE, RANGE, REID, SEGMENTATION, TEXT_RECOGNITION, YAW_3D
TrackedTaskALL, BEHAVIOR, OPTICAL_FLOW, PULSE, RESPIRATION
SizeCategoryAUTO, LARGE, MEDIUM, NANO, PICO
GoalBALANCED, LATENCY, THROUGHPUT
ConfidenceModeCALIBRATED_BALANCED, CALIBRATED_MAX_PRECISION, CALIBRATED_MAX_RECALL, NON_CALIBRATED
NmsModeAUTO, CROSS_CLASS, OFF, ON
SegSourceAUTO, DENSE, INSTANCE
ChannelOrderAUTO, AUTO_LOCK, BGR, RGB
ProviderCOREML, CPU, CUDA, OPENVINO, RKNN, TENSORRT
TrackStateCONFIRMED, LOST, NEW, TENTATIVE, UNSET
DropPolicyDROP_NEWEST, DROP_OLDEST, LATEST_ONLY
LicenseStatusEXPIRED, UNKNOWN, UNSET, VALID
MagnifyModeCOLOR, MOTION
ProvenanceABSENT, AMBIGUOUS, ASSUMED, CONFLICT, DECLARED, DEDUCED
ModelScopeALL, AVAILABLE
SizeCheckNO_BAND, NO_SCALE, OK, TOO_LARGE, TOO_SMALL, UNSET
SizeBasisBAND, CROSS_CHECKED, FOOTPRINT, HEIGHT, LENGTH, ORIENTED, TRAINED, UNSET, WIDTH
SourceDERIVED, DERIVED_ASSUMED_FOCAL, DERIVED_ASSUMED_POSTURE, DERIVED_BRIDGED_EXTENT, DERIVED_DECLARED_HEIGHT, DERIVED_DEPTH, DERIVED_POPULATION, TRAINED, TRAINED_RANGE, TRAINED_RELATIVE, TRAINED_SIZE, UNSET
ZoneStateENTERED, EXITED, INSIDE, OUTSIDE, UNSET
CrossDirectionBACKWARD, FORWARD, UNSET
EventKindBEHAVIOR, DWELL, LINE_CROSSED, TRACK_CONFIRMED, TRACK_LOST, UNSET, VITAL_ABNORMAL, VITAL_NORMAL, ZONE_ENTERED, ZONE_EXITED
PreprocessChannelOrderBGR, RGB
ResizeModeLETTERBOX, STRETCH, STRIDE_LETTERBOX

115 exported names.