File size: 10,056 Bytes
58b3e34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# Pose Classifier Guide

## Overview

The pose classifier predicts the orientation of animals (zebras, giraffes, etc.) relative to the camera position from aerial drone footage. This is critical for navigation and behavior analysis.

## 8-Class Pose Classification System

### Pose Classes

The classifier identifies **8 discrete pose orientations** arranged in a circle around the animal:

1. **front** - Animal facing directly toward camera
2. **front-left** - Animal facing camera, angled to the left (~45°)
3. **left** - Animal's left side visible, perpendicular to camera
4. **back-left** - Animal facing away, angled to the left (~45°)
5. **back** - Animal facing directly away from camera
6. **back-right** - Animal facing away, angled to the right (~45°)
7. **right** - Animal's right side visible, perpendicular to camera
8. **front-right** - Animal facing camera, angled to the right (~45°)

### Visual Reference

![Pose Reference Diagram](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/_reference.png)

The diagram shows the 8 pose classes arranged in a circle. The camera is positioned at the bottom, and the animal (zebra) is in the center. Each orange dot represents one of the 8 possible pose classifications.

## Example Poses

### Front Pose
**Label:** `front`

The animal is facing directly toward the camera, with the head and front body visible.

![Front Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/front/mpala_session_1_DJI_0002_partition_1_DJI_0002_000171_c0_004.jpg)

---

### Front-Left Pose
**Label:** `front-left`

The animal is facing toward the camera but angled to its left (camera's right), showing both the front and left side.

![Front-Left Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/front-left/mpala_session_1_DJI_0002_partition_1_DJI_0002_000471_c0_005.jpg)

---

### Front-Right Pose
**Label:** `front-right`

The animal is facing toward the camera but angled to its right (camera's left), showing both the front and right side.

![Front-Right Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/front-right/mpala_session_2_DJI_0006_partition_2_DJI_0006_006552_c0_004.jpg)

---

### Left Pose
**Label:** `left`

The animal's left side is visible, perpendicular to the camera. This is a pure profile view.

![Left Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/left/mpala_session_1_DJI_0002_partition_1_DJI_0002_000321_c1_001.jpg)

---

### Right Pose
**Label:** `right`

The animal's right side is visible, perpendicular to the camera. This is a pure profile view from the opposite side.

![Right Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/right/mpala_session_1_DJI_0002_partition_1_DJI_0002_000171_c0_002.jpg)

---

### Back-Left Pose
**Label:** `back-left`

The animal is facing away from the camera but angled to its left, showing the rear-left quarter.

![Back-Left Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/back-left/mpala_session_1_DJI_0002_partition_1_DJI_0002_000171_c1_001.jpg)

---

### Back-Right Pose
**Label:** `back-right`

The animal is facing away from the camera but angled to its right, showing the rear-right quarter.

![Back-Right Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/back-right/mpala_session_1_DJI_0002_partition_1_DJI_0002_000171_c1_000.jpg)

---

### Back Pose
**Label:** `back`

The animal is facing directly away from the camera, with the rear and back visible.

![Back Pose Example](https://huggingface.co/imageomics/mmla-dino-pose/resolve/main/back/mpala_session_1_DJI_0002_partition_1_DJI_0002_000321_c1_000.jpg)

---

## Model Architecture

### DINOv2 + MLP Head

The pose classifier uses a **frozen DINOv2 backbone** with a **trainable MLP classification head**:

```
Input Image (224×224)

DINOv2 Vision Transformer (frozen)
    - Small: 384-dim features
    - Base: 768-dim features
    - Large: 1024-dim features

MLP Head (trainable)
    - LayerNorm
    - Linear(feat_dim -> 256) + GELU + Dropout(0.3)
    - Linear(256 -> 128) + GELU + Dropout(0.3)
    - Linear(128 -> 8)

Output Logits (8 classes)
```

### Why DINOv2?

- **Self-supervised learning** on diverse images provides strong visual features
- **Frozen backbone** reduces training time and prevents overfitting
- **Small memory footprint** suitable for deployment
- **Robust to varying image quality** from aerial footage

## Training Pipeline

### Data Organization

Training data is organized in folder structure:
```
pose_labels/
  _reference.png          # Visual guide
  front/                  # Front-facing animals
  front-left/             # Front-left quarter
  left/                   # Left profile
  back-left/              # Back-left quarter
  back/                   # Back-facing animals
  back-right/             # Back-right quarter
  right/                  # Right profile
  front-right/            # Front-right quarter
```

Or via CSV files with columns: `image_path, pose`

### Data Augmentation

**Geometric Augmentation with Label Swapping:**
- Horizontal flip applied with 50% probability
- When flipped, pose labels are swapped according to symmetry:
  - `left` <-> `right`
  - `front-left` <-> `front-right`
  - `back-left` <-> `back-right`
  - `front` and `back` remain unchanged

**Color/Transform Augmentation:**
- Random crop (256px -> 224px)
- Color jitter: brightness (±30%), contrast (±30%), saturation (±20%)
- Random rotation (±15°)

**Class Balancing:**
- Weighted random sampler ensures equal representation of all 8 classes during training

### Training Configuration

```bash
python train_pose_classifier.py \
    --data_dir ./pose_labels \
    --model_size small \
    --epochs 30 \
    --batch_size 32 \
    --lr 1e-3
```

**Key Parameters:**
- **Model size**: `small`, `base`, or `large` (DINOv2 variant)
- **Optimizer**: AdamW with weight decay 0.01
- **Loss**: CrossEntropyLoss with label smoothing (0.1)
- **Scheduler**: CosineAnnealingLR
- **Mixed precision**: Automatic on GPU

**Training Output:**
- Best model saved to `checkpoints/best_pose_model.pth`
- Includes confusion matrix and per-class accuracy
- Optional ONNX export for deployment

## Usage in Navigation

### Integration with Detection Pipeline

The pose classifier is used in the navigation system after animal detection:

```python
from navigation.policy.pose_classifier import ViewPointClassifier
from PIL import Image

# Initialize classifier
classifier = ViewPointClassifier(
    weight_path="model_weights/best_june_24_2025_IA_classifier_016.pth",
    device="cpu",
    threshold=0.5
)

# Process detected animal crops
crops = [Image.open(path) for path in detection_crops]
poses = classifier(crops)  # Returns list of pose strings

# Use poses for navigation decisions
for pose in poses:
    if "front" in pose:
        print("Animal is facing camera - approach with caution")
    elif "back" in pose:
        print("Animal is facing away - good for following")
```

### Multi-Label Pose System (Alternative)

The `ViewPointClassifier` in `pose_classifier.py` uses a different approach:

- **5 multi-label classes**: `up, front, back, right, left`
- **EfficientNet-B4** backbone trained on zebra crops
- **Input size**: 512×512 pixels
- **Output**: Concatenated string (e.g., `"upfrontright"`)
- **Threshold**: 0.5 (configurable)

This allows detecting compound poses like "animal is facing front-right while looking up."

## Performance Considerations

### Inference Speed
- **DINOv2-small**: ~15-20ms per image (CPU)
- **DINOv2-base**: ~30-40ms per image (CPU)
- **GPU acceleration**: 5-10x faster

### Accuracy Targets
- **Overall accuracy**: >85% on validation set
- **Critical classes** (front/back): >90% accuracy
- **Confusion**: Most errors occur between adjacent classes (e.g., front vs. front-left)

### Deployment Notes
- Model checkpoint: ~150MB (small), ~350MB (base)
- ONNX export available for optimized inference
- Batch processing recommended for multiple detections

## Common Issues & Tips

### Issue: Poor performance on occluded animals
**Solution**: Train with more occluded examples or use confidence thresholding

### Issue: Confusion between adjacent poses
**Solution**: This is expected due to continuous nature of orientations; consider using pose groups (front-facing vs. side-facing vs. back-facing)

### Issue: Inconsistent predictions across frames
**Solution**: Apply temporal smoothing or majority voting across consecutive frames

### Issue: Different performance on zebras vs. other species
**Solution**: Retrain with balanced dataset across species, or train species-specific models

## Dataset Statistics

Current training data distribution (from folder structure):
- Folders: `front`, `front-left`, `front-right`, `left`, `right`, `back-left`, `back-right`, `back`
- Images per class: Variable (check with `train_pose_classifier.py --data_dir pose_labels`)
- Species: Primarily zebras and giraffes
- Source: Aerial drone footage from Mpala and OPC sessions

## References

- DINOv2 Paper: [https://arxiv.org/abs/2304.07193](https://arxiv.org/abs/2304.07193)
- VARe-ID (ViewPoint Classifier): [https://github.com/ziesski/VARe-ID](https://github.com/ziesski/VARe-ID)
- Individual identification of wildlife: [https://doi.org/10.1007/s10344-021-01549-4](Review on methods used for wildlife species and individual identification)
- Training script: [train_pose_classifier.py](train_pose_classifier.py)
- Navigation integration: [navigation/policy/pose_classifier.py](../navigation/policy/pose_classifier.py)

## Quick Start

1. **Prepare data**: Organize images in `pose_labels/` folders by class
2. **Train model**: `python train_pose_classifier.py --data_dir ./pose_labels --epochs 30`
3. **Evaluate**: Check confusion matrix and per-class accuracy in output
4. **Export**: Use `--export_onnx` flag for optimized deployment
5. **Integrate**: Load checkpoint and use for inference on detection crops