Skip to main content

Computer vision processing library for visualizing and analyzing detection results from ML models

Project description

PixelFlow

PyPI version Python 3.8+ License: MIT

The computer vision library that gets out of your way.

PixelFlow provides a unified, intuitive API for object detection, tracking, annotation, and video processing. Write clean, readable pipelines that work with any ML framework.

import pixelflow as pf
from ultralytics import YOLO

model = YOLO("yolo11n.pt")
video = pf.VideoReader("traffic.mp4", width=640)
tracker = pf.tracker.ByteTracker()
zones = pf.Zones()
zones.add_zone([(100, 400), (500, 400), (500, 600), (100, 600)], zone_id="entrance")

for frame in video:
    detections = pf.detections.from_ultralytics(model.predict(frame))
    detections = tracker.update(detections)
    zones.update(detections)

    frame = pf.annotate.box(frame, detections)
    frame = pf.annotate.label(frame, detections)
    frame = pf.annotate.zones(frame, zones)

    if pf.show_frame("Live", frame) == ord('q'):
        break

Installation

pip install pixelflow

Core Concepts

Detections - One Format, Every Framework

Convert outputs from any ML framework into a unified format:

import pixelflow as pf

# Ultralytics YOLO
from ultralytics import YOLO
model = YOLO("yolo11n.pt")
detections = pf.detections.from_ultralytics(model.predict(image))

# Detectron2
from detectron2.engine import DefaultPredictor
predictor = DefaultPredictor(cfg)
detections = pf.detections.from_detectron2(predictor(image), class_names=["person", "car"])

# HuggingFace Transformers
from transformers import pipeline
detector = pipeline("object-detection")
detections = pf.detections.from_transformers(detector(image))

# Florence-2
detections = pf.detections.from_florence2(model_output)

# SAM (Segment Anything)
detections = pf.detections.from_sam(masks, scores)

# OCR Engines
detections = pf.detections.from_tesseract(tesseract_output)
detections = pf.detections.from_paddleocr(paddleocr_output)
detections = pf.detections.from_easyocr(easyocr_output)

Powerful Filtering

Chain filters for complex queries with zero overhead:

# Get high-confidence people in the parking zone, tracked for 5+ seconds
results = (detections
    .filter_by_confidence(min_confidence=0.7)
    .filter_by_class_id("person")
    .filter_by_zones(["parking_lot"])
    .filter_by_tracking_duration(min_seconds=5.0))

# Size-based filtering
large_objects = detections.filter_by_size(min_area=10000)
tall_objects = detections.filter_by_dimensions(min_height=200)
squares = detections.filter_by_aspect_ratio(min_ratio=0.9, max_ratio=1.1)

# Spatial filtering
left_side = detections.filter_by_position(max_x=frame_width // 2)

# Remove overlapping detections
unique = detections.remove_duplicates(iou_threshold=0.5)

# OCR-specific filters
titles = detections.filter_by_text_level("title")
english_text = detections.filter_by_text_language("en")

Media Handling

Purpose-built classes for videos, cameras, and images:

import pixelflow as pf

# Read a video file
video = pf.VideoReader("video.mp4", width=640)
print(f"{video.width}x{video.height}, {video.fps}fps, {len(video)} frames")

for frame in video:       # Replayable — resets on each iteration
    if pf.show_frame("Preview", frame) == ord('q'):
        break

# Load a single image
image = pf.read_image("photo.jpg", width=640)

# Webcam / network stream
cam = pf.CameraStream(0, width=640)
cam = pf.CameraStream("rtsp://camera.local/stream")

# Write processed video
writer = pf.VideoWriter("output.mp4", fps=video.fps)
for frame in video:
    processed = process(frame)
    writer.write(processed)
writer.close()

Zone-Based Analytics

Define spatial regions and track what enters them:

import pixelflow as pf

zones = pf.Zones()

# Define zones with different trigger strategies
zones.add_zone(
    polygon=[(100, 400), (300, 400), (300, 600), (100, 600)],
    zone_id="entrance",
    name="Main Entrance",
    trigger_strategy="bottom_center"  # Trigger when bottom-center of bbox enters
)

zones.add_zone(
    polygon=[(500, 200), (700, 200), (700, 500), (500, 500)],
    zone_id="restricted",
    trigger_strategy="percentage",
    overlap_threshold=0.3  # Trigger when 30% of bbox is inside
)

# Update detections with zone info
zones.update(detections)

# Access zone statistics
print(zones.get_zone_counts())  # {'entrance': 3, 'restricted': 1}
print(zones.get_zone_stats())   # Detailed stats including total_entered

# Filter by zone
entrance_only = zones.filter_by_zones(detections, ["entrance"])
not_restricted = zones.filter_by_zones(detections, ["restricted"], exclude=True)

Trigger Strategies:

  • center - Bounding box center point (default)
  • bottom_center - Bottom-center point (great for people/vehicles)
  • percentage - Percentage of bbox overlap
  • overlap - Any intersection
  • Multiple strategies with mode="any" or mode="all"

Object Tracking

Built-in ByteTrack for multi-object tracking:

import pixelflow as pf

tracker = pf.tracker.ByteTracker()

for frame in media.frames:
    detections = pf.detections.from_ultralytics(model.predict(frame))
    detections = tracker.update(detections)

    for det in detections:
        print(f"Track ID: {det.tracker_id}, Class: {det.class_name}")
        print(f"First seen: {det.first_seen_time}, Duration: {det.total_time}s")

Rich Annotations

Beautiful, customizable visualizations:

import pixelflow as pf

# Bounding boxes and labels
frame = pf.annotate.box(frame, detections, thickness=2)
frame = pf.annotate.label(frame, detections, font_scale=0.6)

# Segmentation masks
frame = pf.annotate.mask(frame, detections, opacity=0.4)

# Keypoints and skeletons (pose estimation)
frame = pf.annotate.keypoint(frame, detections)
frame = pf.annotate.keypoint_skeleton(frame, detections)

# Zone visualization
frame = pf.annotate.zones(frame, zones)
frame = pf.annotate.crossings(frame, crossings)

# Privacy protection
frame = pf.annotate.blur(frame, detections, kernel_size=51)
frame = pf.annotate.pixelate(frame, detections, pixel_size=15)

# Shapes
frame = pf.annotate.oval(frame, detections)
frame = pf.annotate.polygon(frame, detections)

Image Transforms

Comprehensive image and detection-aware transformations:

import pixelflow as pf

# Image-only transforms
rotated = pf.transform.rotate(image, 45)
flipped = pf.transform.flip_horizontal(image)
cropped = pf.transform.crop(image, [100, 50, 500, 400])

# Enhancement
enhanced = pf.transform.clahe(image)
gray = pf.transform.to_grayscale(image)
corrected = pf.transform.gamma_correction(image, gamma=1.2)

# Detection-aware transforms (coordinates update automatically)
rotated_img, rotated_dets = pf.transform.rotate_detections(image, detections, 45)
flipped_img, flipped_dets = pf.transform.flip_horizontal_detections(image, detections)
cropped_img, cropped_dets = pf.transform.crop_detections(image, detections, bbox=[100, 50, 500, 400])

# Automatic inverse transforms (undo all transforms)
original_coords = pf.transform.inverse_transforms(transformed_detections)

Sliced Inference for Large Images

Detect small objects in high-resolution images:

import pixelflow as pf

slicer = pf.SlicedInference(
    slice_height=640,
    slice_width=640,
    overlap_ratio_h=0.2,
    overlap_ratio_w=0.2
)

def detector(image):
    return pf.detections.from_ultralytics(model.predict(image))

# Run on 4K image - automatically slices, detects, and merges
large_image = cv2.imread("satellite.jpg")  # 4000x3000
detections = slicer.predict(large_image, detector)

Line Crossing Detection

Track objects crossing defined lines:

import pixelflow as pf

crossings = pf.Crossings()
crossings.add_line(
    start=(100, 300),
    end=(500, 300),
    line_id="entry_line",
    direction="down"  # Only count downward crossings
)

for frame in media.frames:
    detections = tracker.update(pf.detections.from_ultralytics(model.predict(frame)))
    crossings.update(detections)

    print(f"Crossed: {crossings.get_counts()}")
    frame = pf.annotate.crossings(frame, crossings)

Serialization

Export and import detection data:

# To JSON
json_str = detections.to_json()

# To dictionary (for pandas, etc.)
data = detections.to_dict()
df = pd.DataFrame(data)

# With metrics
report = detections.to_json_with_metrics()

Supported Frameworks

Framework Converter Features
Ultralytics (YOLO) from_ultralytics() Boxes, masks, keypoints
Detectron2 from_detectron2() Boxes, masks, keypoints
HuggingFace Transformers from_transformers() Boxes, scores
Florence-2 from_florence2() Boxes, phrases
SAM from_sam() Masks, scores
Tesseract OCR from_tesseract() Text, boxes, confidence
PaddleOCR from_paddleocr() Text, boxes, structure
EasyOCR from_easyocr() Text, boxes
PP-Structure from_ppstructure() Tables, formulas, layouts

Documentation

Full documentation available at https://datamarkin.com/docs/pixelflow/

Contributing

Contributions welcome! Please read our contributing guidelines.

License

MIT License - see LICENSE file for details.


Built with love by Datamarkin

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pixelflow-0.1.3.tar.gz (150.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pixelflow-0.1.3-py3-none-any.whl (173.9 kB view details)

Uploaded Python 3

File details

Details for the file pixelflow-0.1.3.tar.gz.

File metadata

  • Download URL: pixelflow-0.1.3.tar.gz
  • Upload date:
  • Size: 150.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for pixelflow-0.1.3.tar.gz
Algorithm Hash digest
SHA256 3d3e176ffca6762ed0ba44b80fce057f790fd38de4b0daac64097fde6503ff72
MD5 1f740bc165ff2779d4f1d53a292fb612
BLAKE2b-256 412a4c580806182093035d68583d35c5c705d51243b4a4f2829b32c526d3abce

See more details on using hashes here.

File details

Details for the file pixelflow-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: pixelflow-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 173.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for pixelflow-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 cda7cb418ae87841397951156f358651b2d9d2ba0b554ed60372fcc84185bfef
MD5 27932df1503945dc043e9a8b01c9b0ac
BLAKE2b-256 ccd3894b4bc6123292fa4a959016579efc323b14da3521cad4ee53458505f305

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page