Cowcatcher / README.md
CowcatcherAI's picture
Update README.md
91ea409 verified
|
Raw History Blame Contribute Delete
11.2 kB
---
license: agpl-3.0
library_name: ultralytics
pipeline_tag: object-detection
tags:
- yolo
- ultralytics
- object-detection
- agriculture
- livestock
- cattle
- estrus-detection
- computer-vision
---
# Cowcatcher
<p align="left">
<a href="https://jacobsfarm.github.io/website/"><img src="https://img.shields.io/badge/Website-cowcatcherai.com-blue?logo=googlechrome&logoColor=white" alt="Website"></a>
<a href="https://huggingface.co/spaces/CowcatcherAI/CowCatcherAI"><img src="https://img.shields.io/badge/πŸ€—%20Hugging%20Face-Spaces-yellow" alt="Hugging Face"></a>
<a href="https://t.me/+SphG4deaWVNkYTQ8"><img src="https://img.shields.io/badge/Telegram-Join%20Chat-2CA5E0?logo=telegram&logoColor=white" alt="Telegram"></a>
<a href="https://github.com/eschouten/ai-detector"><img src="https://img.shields.io/badge/GitHub-AI--Detector-181717?logo=github&logoColor=white" alt="AI-Detector Repo"></a>
<a href="https://github.com/CowCatcherAI/CowCatcherAI"><img src="https://img.shields.io/badge/GitHub-CowCatcherAI-181717?logo=github&logoColor=white" alt="CowCatcherAI Repo"></a>
<a href="https://github.com/CowCatcherAI/CalvingCatcherAI"><img src="https://img.shields.io/badge/GitHub-CalvingCatcherAI-181717?logo=github&logoColor=white" alt="CalvingCatcherAI Repo"></a>
</p>
###
Check out the website for all the information: [cowcatcherai.com](https://jacobsfarm.github.io/website/)
**The website is available in multiple languages such as Deutsch, FranΓ§ais, Nederlands, and EspaΓ±ol.**
Cowcatcher is a vision model that detects **mounting behaviour** in cattle from camera images.
Mounting is one of the clearest visual signals that a cow is in heat, so a reliable detector lets a barn
camera flag oestrus automatically instead of relying on someone watching the herd.
All models are single-class (`mounting`) Ultralytics models, trained at 640 px on farm camera footage
from multiple dairy and beef sites, in daylight, night/IR and robot-barn conditions.
**Latest and best model: `cowcatcherV17.2.pt`.** It is the only model in the comparison that produces
**zero false alarms** on the null set, at any threshold from 0.50 upward.
---
## Available models
| File | Task | Base | Train imgsz / epochs | Size | Notes |
|---|---|---|---|---|---|
| **`cowcatcherV17.2.pt`** | Detection | `yolo26m` | 640 / 50 | 44 MB | **Recommended.** Best precision and best confidence separation |
| `cowcatcherV17.pt` | Detection | `yolo26m` | 640 / 400 | 131 MB | Previous main model, higher recall at low thresholds |
| `cowcatcherV16.pt` | Detection | `yolo26m` | 640 / 400 | 88 MB | Highest recall at 0.88, but 21 false alarms |
| `cowcatcherV15.pt` | Detection | `yolo12m` | 640 / 100 | 81 MB | Older generation |
| `cowcatcherV14.pt` | Detection | `yolo12m` | 640 / 100 | 41 MB | Older generation, very few false alarms but low recall |
| `cowcatcherV13.pt` | Detection | `yolo12m` | 640 / 100 | 81 MB | Oldest published model, kept for reference |
| `cowcatcherV1-seg.pt` | Segmentation | `yolo11m` | 640 / 100 | 45 MB | Experimental mask model, not part of the benchmark below |
All six detection models are published here and all six appear in the benchmark tables below.
---
## Quick start
```bash
pip install ultralytics
```
```python
from ultralytics import YOLO
model = YOLO("cowcatcherV17.2.pt")
# Single image
results = model.predict("barn_frame.jpg", conf=0.50)
for r in results:
for box in r.boxes:
print("mounting", float(box.conf), box.xyxy.tolist())
```
```python
# Live camera / RTSP stream
for result in model.predict(source="rtsp://camera/stream", stream=True, conf=0.50):
if len(result.boxes):
print("Mounting detected")
```
### Which confidence threshold?
For `cowcatcherV17.2` the false-positive count stays at **0** across the entire 0.50–0.99 sweep, so the
threshold only trades away recall. F1 peaks at **0.50**; anything up to ~0.80 is still a sensible
operating point if you want extra headroom.
| Threshold | Found (TP) | Missed (FN) | False alarms | Recall | Precision | F1 |
|---|---|---|---|---|---|---|
| **0.50** | 896 | 4 | 0 | 99.56% | 100% | **99.78%** |
| 0.60 | 892 | 8 | 0 | 99.11% | 100% | 99.55% |
| 0.70 | 879 | 21 | 0 | 97.67% | 100% | 98.82% |
| 0.80 | 869 | 31 | 0 | 96.56% | 100% | 98.25% |
| 0.88 | 822 | 78 | 0 | 91.33% | 100% | 95.47% |
| 0.92 | 638 | 262 | 0 | 70.89% | 100% | 82.96% |
| 0.95 | 125 | 775 | 0 | 13.89% | 100% | 24.39% |
---
## Training
Every model in this repository was trained with the same script ([`train.py`](train.py)) β€” only the base
checkpoint and the epoch count change per version.
```python
from ultralytics import YOLO
# Load model
model = YOLO("yolo26m.pt")
# Train with added augmentation
model.train(
data="dataset.yaml",
imgsz=640,
batch=16,
epochs=50,
patience=10,
#fraction=0.05, # currently uses 100% of the dataset; 0.8 = 80% of the set
save_period=5,
workers=0,
device=0,
#close_mosaic=10,
# Augmentation settings
augment=True, # General augmentation on/off
degrees=10, # Rotation up to 10 degrees
translate=0.1, # Translation up to 10%
scale=0.5, # Scaling between 0.5 and 1.5
fliplr=0.5, # 50% chance of horizontal flip
hsv_h=0.015, # Minor hue variations
hsv_s=0.7, # Saturation variations
hsv_v=0.4, # Brightness variations
mosaic=1.0 # Mosaic augmentation (combines 4 images)
)
```
Per-version settings β€” everything else in the script stays identical:
| Model | Base checkpoint | Epochs |
|---|---|---|
| `cowcatcherV17.2.pt` | `yolo26m.pt` | 50 |
| `cowcatcherV17.pt` | `yolo26m.pt` | 400 |
| `cowcatcherV16.pt` | `yolo26m.pt` | 400 |
| `cowcatcherV15.pt` | `yolo12m.pt` | 100 |
| `cowcatcherV14.pt` | `yolo12m.pt` | 100 |
| `cowcatcherV13.pt` | `yolo12m.pt` | 100 |
| `cowcatcherV1-seg.pt` | `yolo11m-seg.pt` | 100 |
`dataset.yaml` points at the single-class (`mounting`) farm-camera dataset, which is not published here.
`patience=10` stops a run early once validation stops improving, so the effective epoch count can be
lower than the number listed. Training ran on a single GPU (`device=0`), with `workers=0` for Windows
compatibility.
---
## Benchmark
**Test set:** 1000 held-out images β€” 900 real mounting events and 100 null/noise images (cattle, barns
and robots without mounting). Six models evaluated on 2026-07-23.
Of the 900 mounting events, 11 are found by *no* model at 0.88, and 536 are missed by at least one model.
### Performance at threshold 0.88
| Model | Recall % | Precision % | F1 % | False alarms | Missed | Accuracy % | ms/image |
|---|---|---|---|---|---|---|---|
| **cowcatcherV17.2** | 91.33 | **100.00** | 95.47 | **0** | 78 | 92.2 | 24.1 |
| cowcatcherV16 | **96.33** | 97.64 | **96.98** | 21 | 33 | 94.6 | 24.4 |
| cowcatcherV17 | 86.89 | 99.11 | 92.60 | 7 | 118 | 87.5 | 24.3 |
| cowcatcherV15 | 74.44 | 97.95 | 84.60 | 14 | 230 | 75.6 | 27.3 |
| cowcatcherV14 | 65.00 | 99.66 | 78.68 | 2 | 315 | 68.3 | 27.4 |
| cowcatcherV13 | 50.11 | 99.34 | 66.62 | 3 | 449 | 54.8 | 29.0 |
Note that 0.88 is a legacy production threshold. It suits V16, but it sits far above the optimum for
V17.2 β€” see the next table.
### Best achievable operating point (max F1)
| Model | Best threshold | Found | Missed | False alarms | Recall % | Precision % | F1 % |
|---|---|---|---|---|---|---|---|
| **cowcatcherV17.2** | 0.50 | 896 | 4 | **0** | 99.56 | **100.00** | **99.78** |
| cowcatcherV17 | 0.50 | 897 | 3 | 14 | 99.67 | 98.46 | 99.06 |
| cowcatcherV14 | 0.50 | 886 | 14 | 24 | 98.44 | 97.36 | 97.90 |
| cowcatcherV16 | 0.80 | 891 | 9 | 33 | 99.00 | 96.43 | 97.70 |
| cowcatcherV15 | 0.61 | 894 | 6 | 41 | 99.33 | 95.61 | 97.44 |
| cowcatcherV13 | 0.50 | 867 | 33 | 24 | 96.33 | 97.31 | 96.82 |
### Confidence separation
The gap between the mean confidence on real mounts and on null images decides how easy the model is to
threshold. V17.2 is in a different class here: it is almost silent on noise (mean 0.008) while staying
confident on real events (mean 0.918).
| Model | Avg conf β€” real mounts | Avg conf β€” null noise | Margin |
|---|---|---|---|
| **cowcatcherV17.2** | 0.9180 | **0.0079** | **0.9101** |
| cowcatcherV17 | 0.9026 | 0.1469 | 0.7557 |
| cowcatcherV14 | 0.8718 | 0.2215 | 0.6503 |
| cowcatcherV13 | 0.8409 | 0.2250 | 0.6159 |
| cowcatcherV16 | 0.9316 | 0.4190 | 0.5126 |
| cowcatcherV15 | 0.8893 | 0.3875 | 0.5018 |
The same effect shows in the safety margin (5th percentile of real mounts minus 95th percentile of
nulls). Every other model is negative β€” its distributions overlap β€” while V17.2 reaches **+0.827**:
| Model | Lowest conf on a real mount | Highest conf on a null | P05 mounts | P95 nulls | Safety margin |
|---|---|---|---|---|---|
| **cowcatcherV17.2** | 0.1558 | 0.4382 | 0.8450 | 0.0176 | **+0.8274** |
| cowcatcherV16 | 0.0051 | 0.9304 | 0.8866 | 0.9130 | βˆ’0.0264 |
| cowcatcherV17 | 0.4547 | 0.9107 | 0.8251 | 0.8907 | βˆ’0.0656 |
| cowcatcherV15 | 0.4584 | 0.9060 | 0.8194 | 0.8965 | βˆ’0.0772 |
| cowcatcherV14 | 0.0004 | 0.8925 | 0.7553 | 0.8407 | βˆ’0.0854 |
| cowcatcherV13 | 0.0001 | 0.8995 | 0.6154 | 0.8643 | βˆ’0.2489 |
### Confidence distribution on null images
Number of null images falling in each confidence bin β€” lower and further left is better.
| Bin | V13 | V14 | V15 | V16 | V17 | **V17.2** |
|---|---|---|---|---|---|---|
| 0.00–0.20 | 68 | 70 | 51 | 47 | 79 | **99** |
| 0.20–0.60 | 11 | 6 | 6 | 7 | 9 | **1** |
| 0.60–0.86 | 15 | 19 | 28 | 17 | 4 | **0** |
| 0.86–0.94 | 6 | 5 | 15 | 29 | 8 | **0** |
| 0.94–1.00 | 0 | 0 | 0 | 0 | 0 | **0** |
---
## Choosing a model
- **Default choice β€” `cowcatcherV17.2`.** Best F1, zero false alarms, widest usable threshold window.
Pick this unless you have a specific reason not to.
- **`cowcatcherV16`** still has the highest raw recall at the legacy 0.88 threshold, but pays for it with
21 false alarms out of 100 nulls and heavily overlapping confidence distributions.
## Limitations
- Single class only: the model detects mounting, not cow identity, lameness or other behaviours.
- Trained and evaluated on fixed barn cameras. Very different mounting angles, heavy occlusion or
unusual camera placements are under-represented.
- The 100-image null set is small; a false-positive rate of 0 on it should be read as "no false alarms
observed", not as a guarantee.
- Benchmark timings (24–29 ms/image) were measured on the evaluation machine and will differ on other
hardware.
## License
**AGPL-3.0.**
These weights are trained with [Ultralytics](https://github.com/ultralytics/ultralytics), which is
licensed under AGPL-3.0. Every checkpoint in this repository carries the Ultralytics AGPL-3.0 notice in
its metadata, so the derived weights inherit that license.
In practice this means that if you use these models in a network-accessible service, AGPL-3.0 requires
you to make the corresponding source of that service available to its users. If that does not work for
your deployment, Ultralytics sells a commercial Enterprise License that removes the copyleft obligation β€”
see [ultralytics.com/license](https://www.ultralytics.com/license).