eye-cv 1.2.1
Eye - Simple & Powerful Computer Vision. Auto-convert, smart tracking, jitter reduction.
Requires Python: >=3.8

# Eye 👁️

**Production-ready computer vision toolkit** — detection, tracking, and annotation.

Auto-converts from 13+ model formats (YOLO, Detectron2, Roboflow, TensorFlow, PyTorch, ONNX, …), bundles 3 trackers (SORT, ByteTrack, BoT-SORT) with box-inflation for tiny/fast objects, and ships professional annotators — all in a single `pip install`.

## Installation

```bash
pip install eye-cv                 # core
pip install "eye-cv[all]"          # + tracking + smoothing + web
```

Optional extras: `[track]` (lap), `[smooth]` (filterpy), `[web]` (Flask/FastAPI).

## Quick Start

```python
import eye
from ultralytics import YOLO

model = YOLO("yolo11n.pt")
tracker = eye.Tracker(eye.TrackerType.BYTETRACK, inflation_factor=2.0)
box_ann = eye.BoxAnnotator()

for frame in eye.get_video_frames_generator("input.mp4"):
    detections = eye.detect(model(frame)[0])   # auto-converts any format
    detections = tracker.update(detections)
    annotated = box_ann.annotate(frame, detections)
```

## Features

| Category | Highlights |
|---|---|
| **Detection** | `eye.detect()` auto-converts YOLO, Roboflow, Detectron2, MMDet, TF, PyTorch, OpenCV, ONNX, TensorRT, PaddlePaddle, OpenVINO, numpy |
| **Tracking** | SORT, ByteTrack, BoT-SORT — box inflation, built-in smoothing, `reset()` |
| **Annotators** | Box, Label, Trace, Heatmap, Mask, Gradient, Neon, Shadow, Corner, FPS, Info |
| **Filtering** | `FilterPipeline` with Confidence, Area, AspectRatio, Class filters + stats |
| **Zones** | Polygon & line zones with counting, multiple trigger types |
| **Video** | OpenCV & FFmpeg backends, frame generators, progress callbacks |
| **Web** | `create_flask_app()` / `create_fastapi_app()` — REST API in 5 lines |

## API Cheatsheet

```python
# Detect (any model format)
detections = eye.detect(model_output)

# Filter
detections = detections[detections.confidence > 0.5]

# Track
tracker = eye.Tracker(eye.TrackerType.BYTETRACK, inflation_factor=2.0)
detections = tracker.update(detections)
tracker.reset()  # between clips

# Annotate
annotated = eye.BoxAnnotator().annotate(frame, detections)
annotated = eye.LabelAnnotator().annotate(annotated, detections, labels)
annotated = eye.TraceAnnotator().annotate(annotated, detections)

# Filter pipeline
pipeline = eye.FilterPipeline([
    eye.ConfidenceFilter(0.3),
    eye.AreaFilter(min_area=100),
    eye.ClassFilter([0, 2, 5])
])
filtered = pipeline(detections)
```

## Box Inflation

Eye's key innovation: inflates bounding boxes *only for tracker matching*, so tiny or fast objects that would have zero IoU between frames get associated correctly.

| Object type | Inflation |
|---|---|
| Large & slow | 1.3–1.5× |
| Medium | 1.5–2.0× |
| Tiny & fast | 2.0–3.0× |

## Examples

### Traffic Monitoring with Zone Counting

```python
import eye
from ultralytics import YOLO

model = YOLO("yolo11n.pt")
tracker = eye.Tracker(eye.TrackerType.BYTETRACK, inflation_factor=2.0)

# Define a counting zone
zone = eye.PolygonZone(polygon=np.array([[100,300],[500,300],[500,500],[100,500]]))

box_ann = eye.BoxAnnotator()
trace_ann = eye.TraceAnnotator()

for frame in eye.get_video_frames_generator("traffic.mp4"):
    detections = eye.detect(model(frame)[0])
    detections = tracker.update(detections)
    zone.trigger(detections)

    frame = box_ann.annotate(frame, detections)
    frame = trace_ann.annotate(frame, detections)
    print(f"Objects in zone: {zone.current_count}")
```

### Filter + Annotate Pipeline

```python
import eye

# Only keep confident, large-enough person detections
pipeline = eye.FilterPipeline([
    eye.ConfidenceFilter(0.4),
    eye.AreaFilter(min_area=500),
    eye.ClassFilter([0])  # person class
])

detections = eye.detect(model(frame)[0])
detections = pipeline(detections)

annotated = eye.BoxAnnotator().annotate(frame, detections)
labels = [f"{c:.0%}" for c in detections.confidence]
annotated = eye.LabelAnnotator().annotate(annotated, detections, labels)
```

### REST API in 5 Lines

```python
from ultralytics import YOLO
import eye

model = YOLO("yolo11n.pt")
app = eye.create_flask_app(model, class_names=model.names)
app.run(host="0.0.0.0", port=5000)
# POST /detect with {"image": "<base64>"} → JSON detections
```

### BoT-SORT with Appearance Features

```python
from eye import BoTSORTTracker
import numpy as np

bot = BoTSORTTracker(max_age=30, appearance_thresh=0.25)

# dets: Nx5 array [x1,y1,x2,y2,score], features: NxD embeddings
tracked = bot.update(dets, features=embeddings)
# tracked[:, 4] contains persistent track IDs
```

### Modern Annotators

```python
import eye

# Gradient boxes with rounded corners
gradient_ann = eye.GradientBoxAnnotator(thickness=3, corner_radius=12)
frame = gradient_ann.annotate(frame, detections)

# Neon trails with glow effect
neon_ann = eye.NeonTraceAnnotator(thickness=4, trace_length=50, glow=True)
frame = neon_ann.annotate(frame, detections)

# Shadow boxes for depth effect
shadow_ann = eye.ShadowBoxAnnotator(shadow_offset=5)
frame = shadow_ann.annotate(frame, detections)

# FPS overlay
fps_ann = eye.FPSAnnotator(position="top-left")
fps_ann.update(30.0)
frame = fps_ann.annotate(frame)
```

<!-- 20+ full examples in [`examples/`](examples/) — from quickstart to production traffic monitoring. -->

## License

MIT — free for commercial use.