Open Source Project

ChickEye

AI-powered chicken monitoring with custom-trained YOLO models

Identify individual chickens in real time using computer vision. Built with YOLO11, FastAPI, and a live React dashboard โ€” self-hosted on your own hardware.

Scroll to explore
โ†“

What is ChickEye?

A complete, self-hosted monitoring system for your chicken coop

๐ŸŽฅ

Real-time Detection

Processes live video from IP cameras or webcams at up to 5 FPS using optimized YOLO inference running locally on your hardware.

๐Ÿ”

Individual Identification

Distinguishes specific chickens by name โ€” Babette, Matilda, Eggbert, and Lottie โ€” each with a unique color-coded bounding box.

๐Ÿงช

Built-in Training

Train custom YOLO models directly from the web interface. Select your dataset, configure epochs and image size, and watch live training logs โ€” no terminal needed.

๐Ÿ“ฑ

Live Dashboard

A React web interface streams the annotated video feed and shows each chicken's last-seen timestamp in real time via WebSocket.

๐Ÿ“

Video File Support

Use RTSP streams, webcams, or upload video files directly from the browser. Video files loop automatically โ€” great for testing your model offline.

๐Ÿ”—

REST & WebSocket API

Full API with JSON endpoints and WebSocket support for building your own integrations, dashboards, or notification systems.

Detection Pipeline

๐Ÿ“ท
IP Camera
RTSP stream
โ†’
๐Ÿ–ฅ๏ธ
Frame Capture
OpenCV
โ†’
๐Ÿง 
YOLO Inference
Custom model
โ†’
๐Ÿ”Ž
Temporal Filter
80% threshold
โ†’
๐Ÿ“ก
WebSocket
Live feed

The Live Dashboard

A React web app that shows the live camera feed with detections in real time

Screen recording of the live dashboard โ€” chickens detected and named in real time
๐Ÿ“น

Live Video Stream

The left panel shows the camera feed rendered on an HTML <canvas> element. Each frame arrives over a WebSocket connection as a hex-encoded JPEG and is decoded in the browser โ€” no extra plugins needed. Bounding boxes and labels are overlaid directly by the backend before sending.

๐Ÿ“‹

Detection Status Cards

The right panel shows a live card for every configured chicken. When detected, the card highlights in the chicken's color and shows a confidence progress bar. When absent, a "Last seen" timestamp tells you when it was last in frame.

Babette
94%
Matilda Last seen 14:32
Eggbert
88%
Lottie
91%
๐Ÿท๏ธ

Per-chicken Colors & Names

Every chicken has a unique color used consistently across the bounding boxes, egg icons, and name labels. When detected, the name is shown in full color. When absent, the name is struck through in grey โ€” so you always know exactly who is missing.

Babette Matilda Eggbert Lottie
๐Ÿ“Š

Confidence Score

When a chicken is actively detected, the model's confidence is shown as a percentage below the name (e.g. 94%). This lets you tune the CONFIDENCE setting in docker-compose.yml or the .env file โ€” raise it to reduce false positives, lower it to catch more detections.

๐Ÿ•

Last Seen Timestamp

When a chicken is not currently visible, the dashboard shows the last time it was detected (e.g. Last seen: 14:32). This is tracked in React state and persists for the whole browser session โ€” useful for spotting if a chicken hasn't appeared all day.

โšก

FPS & Latency Monitor

A metrics panel above the video shows live performance data: current frames per second, the server-side timestamp when the frame was captured, the frontend timestamp when it was received, and the calculated end-to-end latency in milliseconds โ€” handy for diagnosing network or processing delays.

Training Your Custom YOLO Model

A step-by-step guide to building a chicken recognition model from scratch

01

Collect Video Footage

Record your chickens from the exact camera angle you'll use for monitoring

The quality of your training data determines the quality of your model. Use the camera in its final installed position โ€” the model learns the specific viewpoint, lighting, and resolution it's trained on.

  • Record at least 30โ€“60 minutes of footage across multiple sessions
  • Capture different times of day (morning, noon, evening) for varied lighting conditions
  • Record each individual chicken separately, so you have clear examples of each class
  • Record all chickens together to teach the model to differentiate them
  • Include challenging cases: partially hidden chickens, chickens close together, chickens in motion
  • Ensure your recording resolution matches what the final system will use (e.g. 640 ร— 480 or 1280 ร— 720)
02

Extract Frames from Video

Convert your recordings into individual images for labeling

Extract frames at a rate that gives enough diversity without excessive redundancy. Every 1โ€“2 seconds (every 30โ€“60th frame at 30 FPS) usually works well. Aim for 500โ€“2 000 images total across all chickens.

python โ€” extract_frames.py
import cv2
import os

def extract_frames(video_path, output_dir, frame_interval=30):
    """Extract one frame every `frame_interval` frames."""
    os.makedirs(output_dir, exist_ok=True)
    cap = cv2.VideoCapture(video_path)
    frame_count = 0
    saved_count = 0

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        if frame_count % frame_interval == 0:
            filename = f"{output_dir}/frame{saved_count:06d}.jpg"
            cv2.imwrite(filename, frame)
            saved_count += 1
        frame_count += 1

    cap.release()
    print(f"Saved {saved_count} frames from {frame_count} total")

# Usage
extract_frames("coop_recording.mp4", "data/images", frame_interval=30)
03

Label Your Images

Draw bounding boxes around each chicken and assign class names

Labeling is the most time-intensive step. Use a tool like Roboflow, Label Studio, or labelImg to annotate bounding boxes and export in YOLO format.

  • Draw tight bounding boxes that encompass the full body of each chicken
  • Use a separate class for each individual chicken (e.g. Babette, Matilda, Lottie)
  • Aim to label at least 100โ€“200 images per class for reliable accuracy
  • Roboflow offers a free tier with annotation tools and automatic train/val splitting
  • Export in YOLOv8 format โ€” this generates a .txt file alongside each image
YOLO label format โ€” each .txt file contains one line per object:
class_id  center_x  center_y  width  height
All values are normalized to [0, 1] relative to image dimensions. Example:
0 0.512 0.438 0.124 0.201  โ†’ class 0 (Babette) at the given position.
04

Organize the Dataset

Arrange files in the folder structure expected by Ultralytics YOLO

YOLO expects a specific folder layout with a central data.yaml config file. An 80 / 20 train / validation split is a good starting point.

folder structure
dataset/chicken/
โ”œโ”€โ”€ data.yaml              โ† dataset config
โ”œโ”€โ”€ images/
โ”‚   โ”œโ”€โ”€ train/             โ† training images (.jpg)
โ”‚   โ””โ”€โ”€ val/               โ† validation images (.jpg)
โ””โ”€โ”€ labels/
    โ”œโ”€โ”€ train/             โ† training labels (.txt)
    โ””โ”€โ”€ val/               โ† validation labels (.txt)
yaml โ€” data/data.yaml
path: ./dataset/chicken   # root directory of the dataset
train: images/train       # training images (relative to path)
val: images/val           # validation images

names:
  0: Babette
  1: Matilda
  2: Eggbert
  3: Lottie
05

Train the YOLO Model

Fine-tune a pretrained YOLO checkpoint on your chicken dataset

Start from a pretrained YOLO checkpoint โ€” this is called transfer learning and dramatically reduces both training time and the amount of labeled data you need. The yolo11n.pt (nano) or yolo11m.pt (medium) are good starting points depending on your hardware. These base weights are not included in the repository โ€” Ultralytics downloads them automatically on first use. To use them in the built-in Train tab, place the downloaded .pt file into the models/ folder first.

Install the Ultralytics library first:

bash
pip install ultralytics opencv-python
python โ€” train.py
from ultralytics import YOLO

# Load a pretrained YOLO11 checkpoint
model = YOLO('yolo11n.pt')   # nano   โ€” fastest, good for most hardware
# model = YOLO('yolo11m.pt') # medium โ€” better accuracy, needs more VRAM
# model = YOLO('yolo11l.pt') # large  โ€” highest accuracy, GPU recommended

# Train on your labeled dataset
model.train(
    data='dataset/chicken/data.yaml',  # path to your dataset config
    epochs=100,                        # training epochs
    imgsz=640,                         # input image size
    project='/tmp/yolo_runs',          # output directory
    name='train',
    exist_ok=True,
)
# Trained weights saved to /tmp/yolo_runs/train/weights/best.pt
# Copy best.pt into your models/ folder and select it in the Setup tab
Using ChickEye's built-in Train tab
If you're running ChickEye via Docker, you can skip the script above โ€” the Train tab in the dashboard handles this automatically. Place your dataset in dataset/, open the Train tab, pick your base model, set epochs, and hit Start Training. The trained model appears in the Setup model selector when done.
Hardware tips
  • A GPU with 4+ GB VRAM is strongly recommended โ€” training will be 10โ€“50ร— faster
  • CPU-only training is possible but expect several hours for 100 epochs
  • Google Colab (free tier) provides a capable GPU for one-off training sessions
  • 100 epochs with ~1 000 images takes roughly 15โ€“45 minutes on a modern GPU
06

Evaluate & Iterate

Check model accuracy and improve it until it performs reliably

After training, YOLO saves metrics and plots to runs/train/chickeye_v1/. Check results.csv and the generated charts for these key metrics:

  • mAP50 โ€” Mean Average Precision at 50% IoU. Aim for > 0.85 for reliable detection
  • Precision โ€” How often a detection is actually correct (minimizes false positives)
  • Recall โ€” How often chickens are successfully detected (minimizes misses)
python โ€” evaluate.py
from ultralytics import YOLO

# Load your trained model
model = YOLO('models/best11n.pt')  # path to your trained model

# Run validation to see full metrics
metrics = model.val(data='dataset/chicken/data.yaml')
print(f"mAP50:    {metrics.box.map50:.3f}")
print(f"mAP50-95: {metrics.box.map:.3f}")

# Test on a single image โ€” shows bounding boxes in a preview window
results = model('dataset/chicken/images/val/chicken_00007.jpg', conf=0.6)
results[0].show()

# Save predictions to disk
results[0].save(filename='prediction.jpg')

If accuracy is insufficient, common improvements:

  • Add more labeled images, especially for underperforming classes
  • Try a larger model variant (yolo11m.pt or yolo11l.pt)
  • Lower the confidence threshold to catch more chickens (at the cost of more false positives)
  • Add data augmentation or train for more epochs
  • Review mislabeled annotations โ€” label quality is often the limiting factor

Hosting Your Own Server

Deploy ChickEye on your own hardware โ€” no cloud required

๐Ÿณ
Docker Compose
๐Ÿ–ฅ๏ธ
Local Development

Docker Compose (Recommended)

One command spins up all three services โ€” model server, streaming backend, and the React frontend behind nginx.

bash โ€” build & start
git clone https://github.com/yourname/chickeye.git
cd chickeye

# Optional: copy and edit environment overrides
cp .env.example .env

docker compose up --build

The dashboard is available at http://localhost:80 (or the HOST_PORT you set in .env).

ini โ€” .env (example)
# Video source โ€” RTSP URL, webcam index, or leave empty to configure in the UI
VIDEO_SOURCE=rtsp://user:password@192.168.1.100:554/stream

# Confidence threshold for detections (0.0 โ€“ 1.0)
CONFIDENCE=0.6

# Class names and colors (comma-separated, must match model training order)
CLASS_NAMES=Babette,Matilda,Eggbert,Lottie
CLASS_COLORS=#ef4444,#94a3b8,#3b82f6,#f59e0b

# Active model (relative to models/ directory)
MODEL_PATH=/app/models/best11n.pt

# 0 = detection, 1 = segmentation
MODEL_TYPE=0

# Port exposed on the host
HOST_PORT=80

API Endpoints

Method Endpoint Description
GET /health Service health check โ€” returns status and currently loaded model
GET /config Active runtime config: class names, colors, video source, and model path
GET /models List of .pt model files available in the models/ directory
GET /datasets List of datasets in dataset/ that contain a data.yaml
POST /setup Save configuration (video source, class names, active model) and reload the model server
POST /train/start Start a training job in the background; accepts dataset, model, epochs, imgsz, output name
GET /train/status Current training state: running flag, recent log lines, error, and output model name
POST /upload-video Upload a video file to use as the video source; returns the server-side path
WS /ws/video WebSocket stream of annotated JPEG frames with per-frame detection JSON

Tech Stack

Built with proven open-source tools

YOLO11
State-of-the-art real-time object detection by Ultralytics. Pretrained on COCO and fine-tuned on custom chicken data using transfer learning. Three size variants: nano, medium, and large.
Computer Vision
FastAPI
High-performance async Python web framework powering the REST API, WebSocket endpoints, and model inference server.
Backend
OpenCV
Frame capture, resizing, and JPEG encoding from RTSP streams and webcams. Also used for drawing bounding boxes on output frames.
Video Processing
React + TypeScript
Live web dashboard built with React 19 and TypeScript. Renders the annotated video feed on a canvas element via WebSocket, with real-time detection cards and a built-in training interface.
Frontend
Docker Compose
Orchestrates three services: a YOLO inference server, a FastAPI WebSocket streaming backend, and an nginx-proxied React frontend โ€” all from a single docker compose up.
Deployment
Vite + nginx
Frontend built with Vite and React 19, served in production via nginx which also proxies WebSocket and REST requests to the backend containers.
Frontend Tooling

Choosing a Model Variant

All three best11*.pt models are included in the repository and trained on the chicken dataset. Pick based on your hardware.

Model Size Speed Accuracy Best For
best11n.pt (nano) ~5 MB โšกโšกโšก โ˜…โ˜…โ˜† Fast CPU or any GPU
best11m.pt (medium) ~40 MB โšกโšกโ˜† โ˜…โ˜…โ˜… Balanced โ€” GPU recommended
best11l.pt (large) ~51 MB โšกโ˜†โ˜† โ˜…โ˜…โ˜… Best accuracy โ€” GPU required