Author: Haochuan Hu
Cow Matcher is a GUI tool designed to manually and semi-automatically align sequential "Track" images (from AutoCattlog algorithm) with "Ground Truth" (GT) identities.
-
Dual-Pane Interface: View Track images (left) and Ground Truth image banks (right) simultaneously.
-
Smart Fill (Interpolation): Automatically fills gaps between two manually matched points (Flag 2).
-
Auto-Ignore: Automatically fills remaining mismatched rows with unique ignore IDs (Flag 4).
-
Visual Status Indicators: Color-coded borders indicate the status of each row (Matched, Interpolated, Ignored).
-
Global Transformations: Supports rotating and mirroring input images via configuration.
To run the tool, your data must follow specific naming conventions.
The images containing the cows to be identified.
-
Filename Format: trackId_{ID}pred{PredID}.jpg or trackId_{ID}.jpg
-
Regex: trackId_(\d+)(?:pred(\d+))?.jpg
-
Example:
-
trackId_105_pred_908.jpg (Track ID 105, Algorithm predicted Cow 908)
-
trackId_106.jpg (Track ID 106, No prediction)
-
A CSV file listing the known sequence of cows.
-
Required Columns: A column named
CowID. -
Generated Columns: The tool will automatically add
assignedTrackIDandflagcolumns if they don't exist.
A directory containing subfolders of cow images.
Bank/
├── 2023-10-01/
│ ├── 908.jpg
│ └── 102.jpg
├── 2023-10-02/
│ └── ...
Prerequisites
conda create -n cow_matcher python=3.12 -y && conda activate cow_matcher && pip install numpy pandas opencv-pythonRunning the Tool
python cow_matcher.py --track "./path/to/track_images" --gt "./path/to/list.csv" --bank "./path/to/bank"-
--track: Path to the folder containing the sequence of images to label.
-
--gt: Path to the CSV file containing the Ground Truth list.
-
--bank: (Optional) Path to the root folder of reference images (default: ./Bank/).
| Key | Function | Description |
|---|---|---|
1 |
Manual Match | Links the current Track row to the current GT row (Blue). |
2 |
Smart Fill / Auto | First Press: Interpolates gaps between manual matches (Orange) AND fills remaining empty rows with "Ignore" (Pink). |
| Second Press: Undo/Clear all auto-filled entries. | ||
3 |
Manual Ignore | Marks the current Track row as "Ignore" (Red). Used for bad images or non-cows. |
x |
Clear / Undo | Clears the assignment for the current row. |
r |
Mark / Bookmark | Toggles a "MARKED" status on the row. Useful for flagging difficult cases to review later. |
m |
Compact Mode | Toggles the GT view to hide empty image columns. |
q |
Save & Quit | Saves CSVs to the Progress/ folder and closes the tool. |
| Key | Function |
|---|---|
w / s |
Scroll Track list Up / Down. |
a / d |
Scroll Ground Truth list Up / Down. |
i / k |
Tandem Scroll: Moves both Track and GT lists Up/Down simultaneously (caps lock supported). |
t |
Jump to Next Mark (Bookmark). |
o |
Jump to Next Auto-Ignore (Flag 4). |
p |
Jump GT list to the ID matching the Prediction (from filename). |
f |
Find Cow: Jumps GT list to the Cow ID currently assigned to the selected Track. |
g |
Find Track: Jumps Track list to the ID currently assigned to the selected GT row. |
The tool saves progress automatically to the ./Progress/ directory.
Contains the tracking data merged with your manual assignments.
| Column | Description |
|---|---|
| track_id | Original ID from the image filename. |
| cowID | The Cow ID you assigned (or ignore_N). |
| flag | Status code indicating how the assignment was made (see below). |
| mark | 1 if the row is bookmarked, 0 otherwise. |
| pred_cow_id | The prediction extracted from the filename. |
Updates your original GT CSV to track which cows have been found.
| Column | Description |
|---|---|
| assignedTrackID | The Track ID assigned to this cow (or ignore_gt_N). |
| flag | Status code (synchronized with the Track file). |
| Flag | Color | Meaning |
|---|---|---|
1 |
🔵 | Blue Manual Match: User explicitly linked Track to GT. |
2 |
🟠 | Orange Interpolated: Automatically filled based on start/end manual matches. |
3 |
🔴 | Red Manual Ignore: User explicitly ignored this image. |
4 |
🌸 | Pink Auto Ignore: Automatically filled because it did not fit the sequence or was remaining at the end. |
