CoolFace
Datasetpublic

anilbhujel/viewpoint-aware-pig-posture-recognition

Viewpoint-Aware Pig Posture Recognition Dataset This dataset supports multi-camera, viewpoint-aware pig posture recognition in livestock barn environments. It contains real-world pig images, bounding box annotations, posture class labels, and per-instance camera viewpoint angles (azimuth and elevation) derived from PnP-based camera calibration. Code: Anil-Bhujel/viewpoint-aware-pig-posture-recognition on GitHub Dataset Summary Images were captured from 2… See the full description on the dataset page: https://huggingface.co/datasets/anilbhujel/viewpoint-aware-pig-posture-recognition.

sourceHugging Facecc-by-4.0updated 4mo agoView on Hugging Face
2likes248downloads
Dataset Card

Viewpoint-Aware Pig Posture Recognition Dataset

This dataset supports multi-camera, viewpoint-aware pig posture recognition in livestock barn environments. It contains real-world pig images, bounding box annotations, posture class labels, and per-instance camera viewpoint angles (azimuth and elevation) derived from PnP-based camera calibration.

Code: Anil-Bhujel/viewpoint-aware-pig-posture-recognition on GitHub

Dataset Summary

Images were captured from 2 real-world pig pens using 4 cameras per pen — 2 overhead fisheye turret cameras and 2 RGB Orbbec depth cameras — installed at different positions and angles. This multi-viewpoint setting captures natural variation in how postures appear under different camera perspectives.

Each annotation includes:

  • A bounding box around an individual pig
  • A posture class label (5 classes)
  • Camera viewpoint angles (azimuth and elevation) for that pig's position
  • The source image filename and resolution

Posture Classes

Class IDLabelDescription
0Lateral_lying_leftPig lying on its side, left laterally
1Lateral_lying_rightPig lying on its side, right laterally
2SittingPig in sitting posture
3StandingPig standing upright
4Sternal_lyingPig lying on sternum (chest-down, sphinx-like)

Dataset Structure

viewpoint_aware_pig_posture_recognition/
├── train.csv                  # Training annotations with viewpoint angles
├── seenVP_test.csv            # Test set — seen viewpoints (cameras in training)
├── unseenVP_test.csv          # Test set — unseen viewpoints (held-out cameras)
├── train_images/              # Training images (full frames, multi-camera)
├── seenVP_test_images/        # Test images — seen viewpoint cameras
└── unseenVP_test_images/      # Test images — unseen viewpoint cameras

Dataset Statistics

SplitInstancesImages
Train22,9333,090
Seen-VP test2,603300
Unseen-VP test11,7081,350

CSV Columns

Each CSV file has the following columns:

ColumnTypeDescription
row_idstrUnique instance identifier
image_idstrFilename of the source image
widthintImage width in pixels
heightintImage height in pixels
bboxstrBounding box in [x, y, w, h] format (XYWH, pixel coords)
class_idintPosture class label (0–4, see table above)
world_xfloatPig floor position X (normalised, floor_width = 1.0)
world_yfloatPig floor position Y (normalised)
azimuth_degfloatCamera-to-pig azimuth angle in degrees (−180 to +180)
elevation_degfloatCamera elevation angle in degrees (zenith convention: 0 = overhead, 90 = horizontal)
elevation_down_degfloatPositive-down elevation (0–90°, always overhead positive)
azimuth_sinfloatsin(azimuth) — used directly as model feature
azimuth_cosfloatcos(azimuth) — used directly as model feature
elevation_sinfloatsin(elevation) — used directly as model feature
elevation_cosfloatcos(elevation) — used directly as model feature
angle_validint1 = valid angle computed; 0 = outside pen or undistort failed
cam_pos_sourcestr"pnp" (PnP pipeline) or "config" (manual config pipeline)
arrow_ufloatAzimuth direction unit vector X component (visualisation helper)
arrow_vfloatAzimuth direction unit vector Y component (visualisation helper)

The unseen-VP test CSV also includes auxiliary columns incl_class and orient_class for sub-category analysis.


Camera Setup

[image]

Camera IDTypeModelResolution
pen1_tur_cam1, pen1_tur_cam2FisheyeTurret overhead1280 × 720
pen2_tur_cam1, pen2_tur_cam2FisheyeTurret overhead1280 × 720
pen1_orb_cam1, pen1_orb_cam2PinholeOrbbec Femto RGB1920 × 1080
pen2_orb_cam1, pen2_orb_cam2PinholeOrbbec Femto RGB1920 × 1080

Camera intrinsics (checkerboard .npz for fisheye cameras and manufacturer .ini for Orbbec pinhole cameras) are available in the companion code repository.


Viewpoint Angle Convention

Angles follow the zenith convention:

  • Azimuth (azimuth_deg): angle of the horizontal projection of the camera-to-pig ray, measured from the +X axis, counter-clockwise positive (−180° to +180°).
  • Elevation (elevation_deg, zenith): 0° means the camera is directly overhead the pig; 90° means the camera is at the same height as the pig (horizontal line of sight).

The (sin, cos) encoding avoids angle-wrapping discontinuities and is used directly as the four-dimensional angle feature vector [azimuth_sin, azimuth_cos, elevation_sin, elevation_cos] in model training.


How to Load

Using HuggingFace datasets

python
from datasets import load_dataset

ds = load_dataset("anilbhujel/viewpoint-aware-pig-posture-recognition")
print(ds)

Manual download

python
from huggingface_hub import snapshot_download

snapshot_download(
    repo_id="anilbhujel/viewpoint-aware-pig-posture-recognition",
    repo_type="dataset",
    local_dir="./dataset"
)

Load CSV + images with pandas

python
import pandas as pd
from PIL import Image
from pathlib import Path
import ast

data_root = Path("dataset/viewpoint_aware_pig_posture_recognition")

# Load annotations
train_df = pd.read_csv(data_root / "train.csv")

# Parse one bounding box
row = train_df.iloc[0]
bbox = ast.literal_eval(row["bbox"])   # [x, y, w, h]
x, y, w, h = bbox

# Crop the pig from its source image
img_path = data_root / "train_images" / row["image_id"]
img = Image.open(img_path).convert("RGB")
crop = img.crop((x, y, x + w, y + h))

print(f"Class: {row['class_id']}, Azimuth: {row['azimuth_deg']:.1f}°, Elevation: {row['elevation_deg']:.1f}°")
crop.show()

PyTorch DataLoader

The full training pipeline, PigCropDataset, and all model code live in the companion GitHub repository. Clone it first, then point it at this dataset:

bash
git clone https://github.com/Anil-Bhujel/viewpoint-aware-pig-posture-recognition.git
cd viewpoint-aware-pig-posture-recognition
python
import sys
sys.path.insert(0, "dino_angles_domain")

from dataset import PigCropDataset
from utils import pad_to_square
import torchvision.transforms as T

val_tfms = T.Compose([
    T.Lambda(lambda im: pad_to_square(im, 224)),
    T.ToTensor(),
    T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
])

ds = PigCropDataset(
    csv_path="dataset/viewpoint_aware_pig_posture_recognition/unseenVP_test.csv",
    image_dir="dataset/viewpoint_aware_pig_posture_recognition/unseenVP_test_images",
    transform=val_tfms,
    use_angles=True,   # loads azimuth_sin/cos + elevation_sin/cos from CSV
)
print(f"Dataset size: {len(ds)}")
x, angles, label = ds[0]
print(f"Image shape: {x.shape}, Angles: {angles}, Label: {label}")

Using with the Code Repository

The GitHub repository contains the full pipeline for:

  • Camera calibration (PnP from 4 annotated floor corners)
  • Per-instance viewpoint angle computation
  • DINOv2-based posture classifier training and evaluation

Quick start with this dataset:

bash
# 1. Clone the code
git clone https://github.com/Anil-Bhujel/viewpoint-aware-pig-posture-recognition.git
cd viewpoint-aware-pig-posture-recognition

# 2. Install dependencies
pip install torch torchvision transformers
pip install opencv-python numpy pandas scikit-learn matplotlib seaborn Pillow

# 3. Download this dataset
pip install huggingface_hub
python -c "
from huggingface_hub import snapshot_download
snapshot_download(
    repo_id='anilbhujel/viewpoint-aware-pig-posture-recognition',
    repo_type='dataset',
    local_dir='dataset'
)"

# 4. Train (angle conditioning + domain adversarial)
cd dino_angles_domain
python dino_train.py \
    --data-root   ../dataset/viewpoint_aware_pig_posture_recognition \
    --dino-weight facebook/dinov2-base \
    --use-angles --use-domain-adv \
    --epochs 30 --batch 64 --lr 1e-4 \
    --out-dir runs/angle_domain_adv

For full instructions including camera re-calibration, all training flags, and evaluation, see the code README.


Benchmark Results

Results with the provided best_dino_angle_domain_model.pt checkpoint (DINOv2-base backbone + MLP head + angle conditioning + domain adversarial training):

Seen Viewpoints Test Set

ClassPrecisionRecallF1
Lateral lying left0.8200.9210.868
Lateral lying right0.8430.8770.860
Sitting0.8440.7710.806
Standing0.9860.9850.985
Sternal lying0.9040.8550.879
Macro avg0.8790.8820.880
Accuracy92.51%

Unseen Viewpoints Test Set

ClassPrecisionRecallF1
Lateral lying left0.8470.8700.858
Lateral lying right0.8670.8590.863
Sitting0.7460.7880.766
Standing0.9590.9840.972
Sternal lying0.8750.8210.847
Macro avg0.8590.8640.861
Accuracy91.07%

Seen vs. Unseen Viewpoint Splits

The dataset is split to evaluate viewpoint generalisation:

  • Seen-VP test set: Images from the same camera positions that appear in training. Tests in-distribution performance.
  • Unseen-VP test set: Images from camera positions held out from training. Tests how well the model generalises to new camera angles.

The large unseen-VP test set (11,708 instances) provides a realistic evaluation of cross-camera generalisation.


Data Collection

Images were collected from pig barn environments using ceiling- and wall-mounted cameras. Pigs were annotated with bounding boxes and posture labels. Camera calibration parameters were estimated using the PnP algorithm applied to 4 manually annotated pen-floor corner points per camera, without requiring physical measurement of the pen dimensions.


License

This dataset is released under the Creative Commons Attribution 4.0 (CC BY 4.0) license.


Citation

If you use this dataset, please cite:

bibtex
@inproceedings{CV4Animals2026,
  title     = {Viewpoint-Aware Pig Posture Recognition and Benchmark Dataset},
  author    = {Bhujel, Anil, Bashar Mk, and Morris, Daniel},
  year      = {2026}
}