Camera Traps in Potato: Reviewing MegaDetector Output, Camtrap DP and Darwin Core
Import MegaDetector or COCO Camera Traps output into Potato, triage images and correct boxes, and export MegaDetector JSON, a Camtrap DP package or Darwin Core.
Potato 2.12.0 reviews camera-trap images after a detector has run over them. You import MegaDetector's batch output or a COCO Camera Traps file, annotators triage each image and correct its boxes, and the result exports as reviewed MegaDetector JSON, a Camtrap DP data package or Darwin Core occurrences.
Potato reads the detector's output and does not run the detector. Run MegaDetector, or the classifier you use for species, on your own machine first.
Import the detector output
# MegaDetector batch output; images under /data/traps
potato import -i md_output.json --image-dir /data/traps -o review-project/
# The same, with the images hosted elsewhere
potato import -i md_output.json --image-url-prefix https://example.org/traps -o review-project/
# Keep only detections with confidence 0.5 or more
potato import -i md_output.json --image-dir /data/traps --md-threshold 0.5 -o review-project/
# COCO Camera Traps, one item per sequence
potato import -i cct.json --image-dir /data/traps --sequences -o review-project/The format is detected from the content, and -f megadetector or -f coco_camera_traps chooses explicitly. With --image-dir, the generated config sets media_directory to that folder, so Potato serves the images from where they already are. With --image-url-prefix, the prefix is joined to each file name instead.
Each image is one item with these questions:
| Scheme | Type | Pre-filled with |
|---|---|---|
triage | radio: empty, animal, person, vehicle | The category of the most confident detection, or empty when no detection reaches the threshold |
detections | image annotation, bounding boxes | Every detection at or above the threshold, labelled with its top species classification when the file has one, otherwise its category |
species | multiselect | The species of those detections, created only when the source names species |
The triage question is a quick first pass: annotators answer it with the keys 1 to 4 and move on, then come back to the boxes of the images that need them. Boxes keep the detector's provenance ("source": "ai", the detector's name and the confidence), and get "edited": true when an annotator changes them. The item keeps datetime, location, seq_id and frame_num when the source has them.
The MegaDetector importer reads batch-output format 1.x. Its bbox is [x, y, width, height] as fractions of the image from the top-left corner, which is how Potato stores boxes, so no image size is needed. Images with a failure are left out and counted, and so are detections below --md-threshold (default 0.2). A file of video results is reviewed at clip level, with each video as one item that has the triage and species questions.
A COCO file whose images carry seq_id is read as COCO Camera Traps, with its categories as the species plus empty. With --sequences, images that share a seq_id become one item, shown as a gallery of the frames in order, with triage and species but no boxes.
Review
python potato/flask_server.py start review-project/config.yaml -p 8000On each image, the annotator checks the triage answer, moves, resizes, relabels or deletes boxes, draws any animal the detector missed, and ticks the species present. Pre-filled answers are stored only when the annotator saves, so an export contains reviewed images only. Detecting Rubber-Stamped Pre-Labels covers checking whether reviewers accepted suggestions without looking.
Export reviewed MegaDetector JSON
python -m potato.export -c review-project/config.yaml -f megadetector -o export/megadetector_reviewed.json uses batch-output format 1.4, with one entry per reviewed image, so it can go back into tools that read MegaDetector results. A box the reviewer drew or changed gets conf 1.0, and a detector box left as it was keeps the detector's score. When several people reviewed an image, the first by user ID is written with a warning, and --option annotator=<user> picks one person.
Export a Camtrap DP package
python -m potato.export -c review-project/config.yaml -f camtrap_dp -o export/ \
--option timezone=-05:00 --option contributor="Your Name" \
--option sampling_design=opportunistic --option capture_method=activityDetectionThe export writes a Camtrap DP 1.0 data package: datapackage.json, deployments.csv, media.csv and observations.csv. Observations are one per box, one per ticked species without a box, and one blank observation for an image triaged empty. classificationMethod is machine for a detector box the reviewer left unchanged, and human otherwise. Sequence items give event-level observations.
Camtrap DP requires facts Potato does not have: the coordinates of each deployment, a UTC offset on every timestamp, and package metadata. Pass what you know as options:
| Option | Fills |
|---|---|
timezone | UTC offset added to timestamps that have none, such as +02:00 or Z |
title | title and project.title (default: annotation_task_name) |
contributor | contributors, one entry with role contact |
license | licenses, scope data |
sampling_design | project.samplingDesign |
capture_method | project.captureMethod and media.captureMethod (activityDetection or timeLapse) |
Anything still missing is listed in the export warnings. Fill it in, such as the deployment coordinates in deployments.csv, and check the package with a Camtrap DP validator before publishing it.
Export Darwin Core occurrences
python -m potato.export -c review-project/config.yaml -f darwin_core -o export/occurrence.csv has one Darwin Core occurrence per animal observation that has a scientific name. Animals labelled only animal are left out, since an occurrence needs a scientific name, and the export says how many. basisOfRecord is MachineObservation when the identification is the detector's and the reviewer left it unchanged, and HumanObservation when a person drew, changed or added it.
A reviewer can answer empty and still leave boxes on the image. The exports write the boxes, because deleting a box is the reviewer's decision, and the warnings list each such item and annotator, so fix them in Potato and export again.
Example
examples/image/camera-trap-review/ has eight synthetic frames from two cameras (deer, a raccoon at night, a person, a vehicle and empty frames) and the MegaDetector file they were imported from.
python potato/flask_server.py start examples/image/camera-trap-review/config.yaml -p 8000Further Reading
- Bioacoustics - Reviewing BirdNET detections and Raven tables
- Image Annotation - Boxes, polygons and the image tools
- Maps - Drawing on georeferenced images and GeoTIFFs
- LLM Pre-Annotation - Reviewing machine suggestions in general
For implementation details, see the source documentation.