Waymark FlyTrack
Counts and tracks vehicles and animals in saved drone footage
Four to six sentences from Cognitio, written on request. Generated text: the page is the reference.
On this page
Overview #
Waymark FlyTrack looks at drone footage that has already been recorded and says what vehicles and animals are in it, where each one is in every frame, and how each one moved. It is built for counting and flow: how many trucks used the haul road this morning, how many sheep crossed from one field to the other, where the vehicles on a site were at each second of a clip. Every detection is a class and a box; a track is a run of detections that the tracker judged to be the same object within one clip.
It is the fourth member of the Waymark series and the first to read pixels directly: Waymark and Waymark Extra read a scene sketch written from a photo, and Waymark Flight reads an airspace scene. FlyTrack is a small centre-point detector trained from scratch on openly licensed aerial imagery, paired with a deterministic tracker that has no weights at all.
What it deliberately does not do is identify. There is no person class, no face or appearance feature, no re-identification and no memory across clips. A track id means “the same car for the next few seconds of this clip” and nothing more. It works on saved files sent to the API, not on a camera feed.
Intended use #
- Traffic and haul-road counts from a drone clip: how many cars, trucks and buses passed, and in which direction.
- Herd and flock counts and movement from a survey flight over a field, a pen or a paddock.
- Site surveys: where the vehicles on a yard were at each moment of a clip, as paths in frame coordinates.
Out of scope #
- People: they are not a class, are never boxed and are never tracked. Footage in which the interest is a person is out of scope, whatever the consent arrangements.
- Identity of any kind: which truck, whose car, which animal. Track ids are per clip and carry nothing that links one clip to another.
- Camera feeds and anything time-critical: the route takes a saved clip and answers in tens of seconds.
- Equipment and other object classes: the first version knows four classes, and objects outside them are ignored or mislabelled as the nearest one.
Choose Waymark FlyTrack when #
- The footage is straight-down or steeply oblique drone video of vehicles or livestock, at the altitudes its training data covers (roughly 15 m for animals and 150 to 250 m for vehicles).
- A count per class and a rough path per object are the answer; if the question is about the layout of a scene, Waymark is the model.
- Otherwise there is no other member of the family for pixels; the held-out figures, once published, say how far to trust it.
Architecture #
| Parameters | 4,448,840 |
|---|---|
| Backbone | Stem of two 3×3 convolutions (stride 2), then four residual stages of two blocks at 48, 96, 192 and 256 channels (strides 4 to 32) |
| Top-down path | Three upsample-and-add steps back to stride 4 with a 3×3 refinement each |
| Heads | At stride 4: a 4-class centre heatmap (sigmoid), a box size (softplus, pixels) and a sub-pixel centre offset |
| Training crops | 512 × 512 random crops with scale jitter 0.7–1.4, horizontal and vertical flips and light colour jitter; images cached with a long side of 1,536 |
| Loss | CenterNet focal loss on the heatmap, L1 on size (weight 0.1) and offset at object centres |
| Decoding | 3×3 max-pool peak pick, up to 300 detections, served at score 0.25 |
| Tracker | Two-pass greedy IoU matching against a constant-velocity prediction (IoU 0.3 for scores ≥ 0.5, then 0.2 for the rest); confirmed after 2 hits, dropped after 8 missed frames; ids per clip only |
| Serving device | CPU container, scales to zero; frames decoded by ffmpeg |
The detector is a CenterNet-style network kept small enough to run on CPU. A stem of two convolutions halves the image, four residual stages take it to a thirty-second of its size, and a top-down path adds the finer feature maps back in until the output is at a quarter of the input resolution. At that resolution three heads answer per cell: a heatmap with one channel per class that peaks at object centres, the box width and height in pixels, and the fraction of a cell by which the true centre is offset. Decoding keeps the local maxima of the heatmap and reads a box at each; there is no anchor and no non-maximum suppression beyond the peak pick.
The tracker is code. Each open track predicts where its box will be next frame from a smoothed constant velocity. High-score detections are matched to predictions first, greedily by intersection over union; the tracks still unmatched then get a second chance against the low-score detections, which is what keeps a track alive through a frame of blur or partial occlusion. A track is confirmed after two consecutive hits and retired after eight frames without one, so a single spurious detection never becomes a track and a brief gap does not split one. Ids are integers assigned in order within a clip.
The service decodes the clip with ffmpeg at the requested frame rate, scales the frames to a long side of 1,024 pixels, runs the detector on each and the tracker across them, and returns everything in the pixels of the decoded frames.
Inputs & outputs #
Input #
| Field | Type | Required | Description | Limit |
|---|---|---|---|---|
video_base64 | string | No | A saved clip as base64 or a data: URL (MP4, MOV or WebM). Decoded with ffmpeg at fps frames a second for max_seconds, scaled to a long side of 1,024 pixels. One of video_base64 and image_base64 is required. | At most 15,000,000 bytes |
image_base64 | string | No | An aerial photo as base64 or a data: URL (JPEG or PNG), treated as a single frame: detections and counts, no tracks. | At most 6,000,000 bytes |
fps | number | No | Frames a second taken from the clip. More frames give smoother tracks and cost more time. | 0.5–5; default 3 |
max_seconds | number | No | How much of the clip is read, from its start. | 0.5–12; default 10 |
min_score | number | No | Detections below this score are dropped before tracking. | 0.05–0.95; default 0.25 |
Exactly one of the media fields is sent. A clip is read from its start for max_seconds at fps frames a second; a photo is one frame, so it returns detections and counts but no tracks.
{
"video_base64": "data:video/mp4;base64,AAAAIGZ0eXBpc29t…",
"fps": 3,
"max_seconds": 10,
"min_score": 0.25
}Limits: the JSON body is at most 24,000,000 bytes, a clip at most 15,000,000 bytes and a photo at most 6,000,000 bytes; fps is clamped to 0.5–5, max_seconds to 0.5–12 and min_score to 0.05–0.95. Frames are scaled so the long side is 1,024 pixels, which sets the smallest object the detector can see at roughly ten pixels in the decoded frame.
Output #
class 4 labels
cartruckbusanimal
media kind 2 labels
videoimage
| Field | Type | Description |
|---|---|---|
engine | string | Always waymark-flytrack. |
media | object | What was decoded: kind (video or image), width, height, frames, and for a clip duration_s and fps. |
frames | array | One entry per decoded frame: t in seconds and detections, each {class, score, box, track} with the box as [x1, y1, x2, y2] in pixels of the decoded frame and track the id of the confirmed track it belongs to, or null. |
tracks | array | One entry per confirmed track: id, class, first_t, last_t, frames (how many it was seen in), max_score and path, a list of [t, cx, cy] centres. |
counts | object | The number of confirmed tracks per class: car, truck, bus, animal. On a photo, the number of detections per class. |
coordinates | string | A reminder that boxes and paths are in pixels of the decoded frame, whose long side is at most 1,024. |
latency_ms | integer | Detection and tracking time on the service. |
notice | string | The scope notice: class-level tracking of vehicles and animals in saved footage, no identity, no real-time use. |
A successful response carries the decoded media description, the per-frame detections, the tracks and the counts.
{
"media": { "kind": "video", "width": 1920, "height": 1080, "duration_s": 6.2, "frames": 18, "fps": 3 },
"frames": [
{ "t": 0, "detections": [ { "class": "truck", "score": 0.91, "box": [412.0, 220.5, 470.2, 251.0], "track": 1 } ] }
],
"tracks": [
{ "id": 1, "class": "truck", "first_t": 0, "last_t": 5.67, "frames": 18, "max_score": 0.94, "path": [[0, 441.1, 235.8], [0.333, 448.0, 236.2]] }
],
"counts": { "car": 0, "truck": 1, "bus": 0, "animal": 0 },
"coordinates": "pixels of the decoded frame (long side ≤ 1024)",
"latency_ms": 4200,
"notice": "Class-level tracking of vehicles and animals in saved drone footage; no identity, no live use."
}The example is illustrative of the shape. A detection with track: null was seen but not yet confirmed as a track, or belonged to a track that never reached two hits; counts counts confirmed tracks, so it is the number a host should report, not the number of boxes.
Training #
The detector is trained from scratch on four openly licensed sources, all Creative Commons Attribution 4.0 and attributed in meta.json: the Aerial Multi-Vehicle Detection Dataset (cars, buses and trucks in 9,048 stills at 150 to 250 m), the ICAERUS drone images of sheep and of goats (low-altitude flights over farms in France), and the New Zealand Cattle Detection tiles, whose point annotations become fixed 22-pixel boxes at 0.1 m per pixel. Sheep, goats and cattle share one animal class; no dataset with a research-only licence is used, and no person is a class.
Every image is cached once with a long side of 1,536 pixels. Training draws two 512 × 512 crops per image per epoch, biased toward objects two times in three, with scale jitter, flips and light colour jitter, and rasterises the centre heatmap, the sizes and the offsets at stride 4. The loss is the CenterNet focal loss on the heatmap plus L1 on the sizes and offsets at object centres; AdamW with a cosine schedule and bf16 autocast on one A100. The epoch with the best held-out average precision is kept.
The tracker is not trained. It is scored on four ICAERUS drone videos of sheep that carry per-frame boxes and consistent ids, which never enter training.
First run: the base size on the four sources, Vertex AI job flytrack-20260923-201621. Released once evaluated.
Evaluation #
Evaluation results have not been published for this version.
API #
Waymark FlyTrack is exposed through the Falcon API route /v1/track. Requests count against the spatial preview quota bucket, one unit per request whatever the clip length. Envelope, authentication, rate limits and retry guidance are in API conventions.
POST /v1/track HTTP/1.1
Authorization: Bearer $FALCON_API_KEY
Content-Type: application/json{ "video_base64": "data:video/mp4;base64,AAAAIGZ0eXBpc29t…", "fps": 3, "max_seconds": 10 }{ "ok": true, "engine": "waymark-flytrack", "media": { "kind": "video", "width": 1920, "height": 1080, "duration_s": 6.2, "frames": 18, "fps": 3 }, "frames": [ { "t": 0, "detections": [ { "class": "truck", "score": 0.91, "box": [412.0, 220.5, 470.2, 251.0], "track": 1 } ] } ], "tracks": [ { "id": 1, "class": "truck", "first_t": 0, "last_t": 5.67, "frames": 18, "max_score": 0.94, "path": [[0, 441.1, 235.8]] } ], "counts": { "car": 0, "truck": 1, "bus": 0, "animal": 0 }, "latency_ms": 4200, "notice": "Class-level tracking of vehicles and animals in saved drone footage; no identity, no live use." }| Status | Code | Meaning |
|---|---|---|
| 400 | media_required | neither video_base64 nor image_base64 was sent |
| 400 | bad_media | the clip or photo could not be decoded |
| 400 | video_too_large / image_too_large | over 15,000,000 or 6,000,000 bytes |
| 400 | bad_fps / bad_max_seconds / bad_min_score | a knob outside its range or not a number |
| 429 | quota_exceeded | the spatial bucket is exhausted for the month |
| 503 | track_warming | the service is starting; retry after the Retry-After seconds |
| 503 | track_unavailable | no service is configured for this deployment |
| 502 | track_failed | the service answered with an error |
| Endpoint | Auth | Body limit | Description |
|---|---|---|---|
POST /v1/track | Bearer preview key (fln_) or session token (fls_) | 24,000,000 bytes | A saved clip or an aerial photo in, per-frame detections, tracks and counts per class out; metered in the spatial bucket, one unit per request. |
The service behind the route takes the same body on its own /v1/track and answers /health with readiness, the class list and the limits.
Runtime & deployment #
| Kind | CPU service |
|---|---|
| Resident | One CPU container holding the detector weights and ffmpeg for decoding |
| Serving | The Falcon API route /v1/track, fronting the Waymark FlyTrack service |
| Cold start | Scales to zero when idle; the first call after a quiet period waits for the container and may answer 503 track_warming with Retry-After 30 |
| Concurrency | Two clips at a time per instance; frames of one clip are processed in order |
| Timeout | 180 s per request on the service |
The service is a Python container on CPU with the detector weights, ffmpeg and the tracker. A ten-second clip at three frames a second is thirty detector passes at a long side of 1,024 pixels, about a second each on four cores, so a request answers in roughly half a minute; a photo answers in about a second. The container scales to zero when idle and the Falcon API turns its loading state into 503 track_warming with a retry hint.
- The host sends the file; nothing is fetched from a URL, and nothing is kept after the response.
- Frame rate and duration are the cost knobs: fewer frames answer faster and lose short-lived tracks.
- The same trainer package serves and trains, so the detector, the decoding and the tracker in the service are the code the evaluation used.
Limits & safety #
FlyTrack sees only the pixels it is sent, at a long side of 1,024. It does not know the altitude, the camera, the ground sampling distance or the location, and it does not see any other clip.
- People are not a class. The model has not been trained to see them and returns nothing for them; a person in the footage is not a detection, not a track and not a count. The scope of the model is vehicles and animals, and the notice in every response says so.
- No identity, ever: no re-identification, no appearance features, no linking across clips, no face processing. A track id is an integer valid inside one response.
- Saved footage only. The route has no streaming form and answers in tens of seconds, which rules out real-time tracking by design.
- It knows four classes at the altitudes of its training data. Objects it has not seen the like of, clips filmed much lower or higher, night footage, thermal footage and heavy motion blur are outside what the held-out figures describe.
- Counts are counts of confirmed tracks, which a long occlusion can split and a crowd can merge; the per-frame detections are there to be checked.
- The footage the host sends may show private property or people; the host is responsible for having the right to process it. The model cannot make that judgement and does not try.
Out of scope: FlyTrack does not identify, recognise, follow across clips or watch in real time, and it is not a safety system. Not a substitute for a survey, and no help with a clip whose subject is a person.
Fixed weights per version; the model does not learn from requests.
Versions #
| Version | Date | Status | Note |
|---|---|---|---|
| 0.1.0 | Training | First run: the base size on the four CC BY 4.0 sources, 16 epochs of two crops per image, one A100 (Vertex AI job flytrack-20260923-201621). Released once evaluated. |
Compatibility: a major version bump changes the request or response contract — a field added, removed or renamed, a class added to or removed from the list — or the geometry the service decodes at. A minor bump is a retrain with the same contract; the figures on this page change, the shapes do not.
No weights are released yet; this page records the training run and is updated with the bundle's identifier and hash when it is. Weights are not distributed during the private preview; see Access and Status & versioning.
Weights are not distributed during the private preview.