Protege Model
Welcome to the Filter Protege Model documentation. This documentation provides comprehensive information about using the generic filter for various Protege AI tasks.
OverviewDirect link to Overview
The FilterProtegeModel is designed to be generic and work with multiple Protege task types without requiring code changes. The same filter class can handle OCR, object detection, classification, multilabel classification, and other AI tasks by simply changing the configuration.
Quick StartDirect link to Quick Start
The FilterProtegeModel is a generic filter that works with multiple Protege task types (OCR, Detection, Classification) using the same filter class.
Basic UsageDirect link to Basic Usage
from filter_protege_model import FilterProtegeModel, FilterProtegeModelConfig
# Configure for OCR
config = FilterProtegeModelConfig(
model_artifact_path="/path/to/model",
protege_task="ocr",
model_config={"ocr_img_height": 32}
)
# Use the filter
filter = FilterProtegeModel()
filter.setup(config)
Key BenefitsDirect link to Key Benefits
- Single Filter Class: Same
FilterProtegeModelworks with all task types - Task-specific Configuration: Each task type has its own configuration options
- Automatic Task Detection: Task type is automatically detected from model configuration
- Environment Variable Support: Full configuration through environment variables
- Extensible Design: Easy to add new task types by implementing new model classes
Key FeaturesDirect link to Key Features
- Multi-task Support: Same filter class for OCR, Detection, Classification
- Automatic Detection: Task type and configuration auto-detected from model
- Task-specific Configuration: Each task type has its own configuration options
- Environment Variables: Full configuration through environment variables
- Extensible Design: Easy to add new task types
Task Types SupportedDirect link to Task Types Supported
OCR (Optical Character Recognition)Direct link to OCR (Optical Character Recognition)
- Text recognition from images/video
- Configurable preprocessing dimensions
- Uppercase output option
Object DetectionDirect link to Object Detection
- Detect objects in images/video
- Configurable NMS threshold
- Custom class names support
Image ClassificationDirect link to Image Classification
- Classify images into categories
- Top-K predictions
- Softmax probability support
Configuration StructureDirect link to Configuration Structure
The filter uses a generic configuration structure with task-specific options:
from filter_protege_model import FilterProtegeModel, FilterProtegeModelConfig
config = FilterProtegeModelConfig(
# Basic filter settings
draw_visualization=True,
visualization_topic="viz",
visualization_alpha=0.7,
visualization_source_topic=None, # e.g., "main", "viz_chit", "viz_bowl"
# Topic forwarding settings
forward_main=False, # Forward the main topic to the output
# Result aggregation settings
add_predictions_to_all_topics=True, # Add predictions to all output topics
aggregate_results=True, # Enable result aggregation
aggregation_strategy="append", # Strategy: "append", "replace", "merge"
max_aggregated_results=10, # Maximum results to keep per topic
# Protege Runtime settings
model_artifact_path="/path/to/model",
device="cuda", # or "cpu"
protege_confidence_threshold=0.5,
protege_task="ocr", # or None for auto-detection
# Task-specific configuration
model_config={
# Task-specific settings go here
"ocr_img_height": 32,
"detection_nms_threshold": 0.5,
"classification_top_k": 5
}
)
Task-Specific ExamplesDirect link to Task-Specific Examples
OCR (Optical Character Recognition)Direct link to OCR (Optical Character Recognition)
Use Case: Text recognition from images or video frames.
def example_ocr_configuration():
"""Example configuration for OCR task."""
config = FilterProtegeModelConfig(
# Basic filter settings
draw_visualization=True,
visualization_topic="ocr_viz",
visualization_alpha=0.7,
# Protege Runtime settings
model_artifact_path="/path/to/ocr/model",
device="cuda", # or "cpu"
protege_confidence_threshold=0.5,
protege_task="ocr", # or None for auto-detection
# Model-specific configuration for OCR
model_config={
"ocr_img_height": 32,
"ocr_img_width": 100,
"ocr_uppercase_output": True
}
)
return config
OCR Configuration Options:
ocr_img_height: Input image height for OCR preprocessing (default: 32)ocr_img_width: Input image width for OCR preprocessing (default: 100)ocr_uppercase_output: Convert OCR results to uppercase (default: True)
Output Data Structure:
{
"ocr_texts": ["fgj235", "another_text"],
"ocr_confidence": 0.999,
"ocr_architecture": "TPS_ResNet_BiLSTM_Attn",
"ocr_processing_time": 0.040160179138183594,
"ocr_timestamp": 1754418436.610824
}
Object DetectionDirect link to Object Detection
Use Case: Detect objects in images or video frames.
def example_detection_configuration():
"""Example configuration for Detection task."""
config = FilterProtegeModelConfig(
# Basic filter settings
draw_visualization=True,
visualization_topic="detection_viz",
visualization_alpha=0.8,
# Protege Runtime settings
model_artifact_path="/path/to/detection/model",
device="cuda",
protege_confidence_threshold=0.6,
protege_task="detection", # or None for auto-detection
# Model-specific configuration for Detection
model_config={
"detection_nms_threshold": 0.5,
"detection_max_detections": 100,
"detection_class_names": ["person", "car", "bicycle"],
"max_objects_per_frame": 10 # Limit objects per frame
}
)
return config
Detection Configuration Options:
detection_nms_threshold: Non-maximum suppression threshold (default: 0.5)detection_max_detections: Maximum number of detections to return (default: 100)detection_class_names: List of class names for detectionmax_objects_per_frame: Maximum number of objects to detect per frame (default: None, no limit)
Tracking Configuration Options (ByteTrack):
enable_tracking: Attach a track id to each detection (default:false)track_activation_threshold: Confidence a detection needs before a track starts (default: 0.5)lost_track_buffer: Frames a track survives without a match before it is dropped (default: 30)minimum_matching_threshold: IoU needed to match a detection to an existing track (default: 0.8)track_frame_rate: Frame rate the tracker assumes, which is whatlost_track_buffercounts in (default: 30)
Tracking needs the optional dependency: pip install filter-protege-model[tracking]. The shipped image does not carry it, so a pipeline turning tracking on must install it or build an image that does; the filter raises at start-up rather than running untracked.
One ByteTrack instance is kept per topic. Two camera streams sharing a model instance would otherwise match an object in one feed against an object in the other and hand out ids that jump between cameras.
Tracking output: when enable_tracking is on, each detection entry carries a tracker_ids list parallel to rois, one id per box, in the same order. A box the tracker has not accepted yet reads -1. It is a parallel list rather than a field inside each roi so that consumers indexing into rois positionally keep working unchanged.
{
"detections": [
{
"class": "car",
"rois": [[x1, y1, x2, y2], [x3, y3, x4, y4]],
"tracker_ids": [7, -1]
}
]
}
Moving from filter-deimv2-detection: that filter names these options enable_byte_track, bt_track_activation_threshold, bt_lost_track_buffer and bt_frame_rate, and defaults tracking on. A pipeline moving here hits all four renames plus the flipped default, so tracking is off until enable_tracking is set explicitly.
Output Data Structure:
{
"detections": [
{
"class": "person",
"rois": [[x1, y1, x2, y2]]
},
{
"class": "car",
"rois": [[x1, y1, x2, y2], [x3, y3, x4, y4]]
}
],
"detection_confidence": 0.91
}
Image ClassificationDirect link to Image Classification
Use Case: Classify images into predefined categories.
def example_classification_configuration():
"""Example configuration for Classification task."""
config = FilterProtegeModelConfig(
# Basic filter settings
draw_visualization=True,
visualization_topic="classification_viz",
visualization_alpha=0.6,
# Protege Runtime settings
model_artifact_path="/path/to/classification/model",
device="cpu", # Classification might work well on CPU
protege_confidence_threshold=0.7,
protege_task="classification", # or None for auto-detection
# Model-specific configuration for Classification
model_config={
"classification_top_k": 5,
"classification_softmax": True,
"classification_class_names": ["cat", "dog", "bird", "fish"]
}
)
return config
Classification Configuration Options:
classification_top_k: Number of top predictions to return (default: 5)classification_softmax: Apply softmax to output probabilities (default: True)classification_class_names: List of class names for classification
Output Data Structure:
{
"classifications": ["cat", "dog"],
"classification_scores": [0.95, 0.03]
}
Multilabel ClassificationDirect link to Multilabel Classification
Use Case: Classify images with multiple labels simultaneously (non-exclusive classification).
def example_multilabel_classification_configuration():
"""Example configuration for Multilabel Classification task."""
config = FilterProtegeModelConfig(
# Basic filter settings
draw_visualization=True,
visualization_topic="multilabel_viz",
visualization_alpha=0.7,
# Protege Runtime settings
model_artifact_path="/path/to/multilabel/model",
device="cuda",
protege_confidence_threshold=0.8, # Higher threshold for multilabel
protege_task="multilabel_classification", # or None for auto-detection
# Model-specific configuration for Multilabel Classification
model_config={
"classification_confidence_threshold": 0.8,
"classification_sigmoid": True, # Use sigmoid for independent probabilities
"classification_class_names": ["avocado", "fish", "chicken", "vegetables"]
}
)
return config
Multilabel Classification Configuration Options:
classification_confidence_threshold: Confidence threshold for each class (default: 0.8)classification_sigmoid: Use sigmoid activation for independent probabilities (default: True)classification_class_names: List of class names for multilabel classification
Key Differences from Regular Classification:
- Non-exclusive: Multiple classes can be detected simultaneously
- Independent probabilities: Each class has its own confidence score
- Sigmoid activation: Uses sigmoid instead of softmax for independent class predictions
- Enhanced visualization: Larger fonts and spacing for better readability
Output Data Structure:
{
"classes": ["avocado", "fish"],
"confidences": [0.9828291535377502, 0.8622298240661621],
"architecture": "resnet50",
"timestamp": 1760985061.0605319,
"filter_id": "filter_protege_multilabel_classification"
}
JSON Output Format:
{
"main": {
"meta": {
"id": 9,
"ts": 1760985060.999788,
"src": "file:///path/to/video.mp4",
"src_fps": 10.0,
"classification_filter_protege_multilabel_classification": {
"classes": ["avocado", "fish"],
"confidences": [0.9828291535377502, 0.8622298240661621],
"architecture": "resnet50",
"timestamp": 1760985061.0605319,
"filter_id": "filter_protege_multilabel_classification"
},
"classification": {
"classes": ["avocado", "fish"],
"confidences": [0.9828291535377502, 0.8622298240661621],
"architecture": "resnet50",
"timestamp": 1760985061.0605319,
"filter_id": "filter_protege_multilabel_classification"
}
}
},
"viz": {
"meta": {
"task": "multilabel_classification",
"classes": ["avocado", "fish"],
"confidences": [0.9828291535377502, 0.8622298240661621],
"architecture": "resnet50",
"timestamp": 1760985061.0605319,
"filter_id": "filter_protege_multilabel_classification",
"classification_filter_protege_multilabel_classification": {
"classes": ["avocado", "fish"],
"confidences": [0.9828291535377502, 0.8622298240661621],
"architecture": "resnet50",
"timestamp": 1760985061.0605319,
"filter_id": "filter_protege_multilabel_classification"
}
}
}
}
Visualization Features:
- Larger fonts: Improved readability for multiple labels
- Consistent colors: All multilabel classes use green color scheme
- Enhanced spacing: Larger spacing to prevent overlap
- Position flexibility: Support for left, right, top, bottom positioning
- Background rectangles: Colored backgrounds for better text visibility
Environment Variables ConfigurationDirect link to Environment Variables Configuration
You can configure the filter entirely through environment variables:
# Basic filter settings
export FILTER_DRAW_VISUALIZATION=true
export FILTER_VISUALIZATION_TOPIC=my_viz
export FILTER_VISUALIZATION_ALPHA=0.7
export FILTER_VISUALIZATION_SOURCE_TOPIC=viz_chit # choose image source for main visualization
# Topic forwarding settings
export FILTER_FORWARD_MAIN=true
# Result aggregation settings
export FILTER_ADD_PREDICTIONS_TO_ALL_TOPICS=true
export FILTER_AGGREGATE_RESULTS=true
export FILTER_AGGREGATION_STRATEGY=append
export FILTER_MAX_AGGREGATED_RESULTS=10
# Protege Runtime settings
export FILTER_MODEL_ARTIFACT_PATH=/path/to/model
export FILTER_DEVICE=cuda
export FILTER_PROTEGE_CONFIDENCE_THRESHOLD=0.5
export FILTER_PROTEGE_TASK=ocr
# Model-specific settings (these will be passed to model_config)
export FILTER_OCR_IMG_HEIGHT=32
export FILTER_OCR_IMG_WIDTH=100
export FILTER_OCR_UPPERCASE_OUTPUT=true
# Multilabel Classification settings
export FILTER_CLASSIFICATION_CONFIDENCE_THRESHOLD=0.8
export FILTER_CLASSIFICATION_SIGMOID=true
export FILTER_CLASSIFICATION_CLASS_NAMES="avocado,fish,chicken,vegetables"
# Topic forwarding settings
export FILTER_FORWARD_MAIN=true
Then use the filter with default configuration:
config = FilterProtegeModelConfig()
filter = FilterProtegeModel()
filter.setup(config)
Result Aggregation ConfigurationDirect link to Result Aggregation Configuration
The filter supports advanced result aggregation for complex pipelines where the same filter is called multiple times or when you need to combine results from different processing stages.
Aggregation FeaturesDirect link to Aggregation Features
- Multiple Strategies: Choose from
append,replace, ormergeaggregation strategies - Cross-Topic Predictions: Add predictions to all output topics, not just the ones being processed
- Configurable Limits: Set maximum number of aggregated results to prevent memory issues
- Namespaced Results: Each filter instance gets its own namespace to avoid conflicts
Aggregation StrategiesDirect link to Aggregation Strategies
Append Strategy ("append"):
- Adds new results to existing ones
- Maintains chronological order
- Useful for tracking results over time
Replace Strategy ("replace"):
- Replaces existing results with new ones
- Keeps only the most recent results
- Useful for real-time processing
Merge Strategy ("merge"):
- Intelligently merges results of the same type
- Combines OCR texts, detection boxes, classification classes
- Useful for combining complementary results
Use CasesDirect link to Use Cases
- Multi-Stage Processing: When the same filter processes different topics in sequence
- Pipeline Cascading: When multiple filters of the same type are chained together
- Result Accumulation: When you need to collect results from multiple processing steps
- Cross-Topic Analysis: When you want predictions available on all topics for downstream processing
Topic Forwarding ConfigurationDirect link to Topic Forwarding Configuration
The forward_main parameter controls whether the main topic from the input frames is forwarded to the output. This is useful in pipeline scenarios where you want to preserve the original main frame alongside processed results.
forward_main ParameterDirect link to forward_main Parameter
Default: False
Behavior:
- When
True: The main topic from input frames is preserved and forwarded to the output - When
False: Only processed frames are returned (no main topic forwarding)
Use Cases:
- Pipeline Processing: When you want to preserve the original main frame for downstream filters
- Multi-topic Processing: When processing specific topics but want to keep the main frame intact
- Data Preservation: When you need both processed results and original frame data
Example:
# Forward main topic to preserve original frame
config = FilterProtegeModelConfig(
forward_main=True,
topic_pattern='license_plate', # Process only license_plate topics
# Main topic will be preserved and forwarded
)
Output Behavior:
- With
forward_main=True: Output includes both processed topics and the original main topic - With
forward_main=False: Output includes only processed topics
Visualization Topics with forward_mainDirect link to Visualization Topics with forward_main
When forward_main=True and visualization is enabled (draw_visualization=True), the filter creates two visualization topics:
Standard Visualization Topic (viz):
- Uses the processed frame (may be cropped/modified by the model)
- Shows results applied to the frame that was actually processed by the model
- Useful for seeing exactly what the model processed
Main Frame Visualization Topic (viz_main):
- Uses the original main frame (unmodified)
- Shows results applied to the complete original image
- Useful for seeing results in full context
Example Output Structure:
# When forward_main=True and draw_visualization=True:
{
"main": Frame(original_image, results_metadata, "BGR"), # Original main frame
"viz": Frame(processed_image_with_annotations, viz_data, "BGR"), # Processed frame visualization
"viz_main": Frame(original_image_with_annotations, viz_data, "BGR") # Original frame visualization
}
# When forward_main=False and draw_visualization=True:
{
"main": Frame(processed_image, results_metadata, "BGR"), # Processed frame
"viz": Frame(processed_image_with_annotations, viz_data, "BGR") # Processed frame visualization
}
Use Cases for Dual Visualization:
- Context Comparison: Compare results on processed vs original frame
- Debugging: Understand how the model crops/processes the input
- Full Context: See detections in the complete original image
- Pipeline Analysis: Track how data transforms through processing stages
Advanced Pipeline ConfigurationDirect link to Advanced Pipeline Configuration
Multi-Source Webvis ConfigurationDirect link to Multi-Source Webvis Configuration
In complex pipelines, you may need to visualize multiple data streams simultaneously. The Webvis filter supports advanced source configuration for combining different data streams:
(Webvis, dict(
sources=[
'tcp://localhost:5558', # Main pipeline output
'tcp://localhost:5556;license_plate>license_plate_ocr' # Renamed topic stream
],
))
Source Configuration Syntax:
'tcp://localhost:5558': Standard source connection'tcp://localhost:5556;license_plate>license_plate_ocr': Source with topic renamingtcp://localhost:5556: Connection to filter outputlicense_plate: Original topic name>license_plate_ocr: Renamed topic for visualization
Use Cases:
- Topic Renaming: Avoid naming conflicts when combining multiple streams
- Multi-Stream Visualization: Display different processing stages simultaneously
- Pipeline Debugging: Compare original vs processed data in real-time
- Data Flow Tracking: Visualize how data transforms through the pipeline
Example Pipeline Flow:
VideoIn → FilterLicensePlateDetection → FilterCrop → FilterProtegeModel → FilterLicenseAnnotationDemo
↓ ↓
tcp://localhost:5550 tcp://localhost:5556 → tcp://localhost:5558
↓
Webvis (combined streams)
Automatic Task DetectionDirect link to Automatic Task Detection
The filter can automatically detect the task type from the model configuration:
# Let the filter auto-detect the task type
config = FilterProtegeModelConfig(
model_artifact_path="/path/to/model",
protege_task=None, # Auto-detect from model
model_config={} # Auto-detect configuration from model
)
Supported Auto-detection:
- Task type from model configuration
- Model-specific parameters (dimensions, thresholds, etc.)
- Architecture and capabilities
Usage PatternsDirect link to Usage Patterns
Pattern 1: Explicit ConfigurationDirect link to Pattern 1: Explicit Configuration
config = FilterProtegeModelConfig(
protege_task="ocr",
model_config={"ocr_img_height": 32}
)
Pattern 2: Auto-detectionDirect link to Pattern 2: Auto-detection
config = FilterProtegeModelConfig(
protege_task=None, # Auto-detect
model_config={} # Auto-detect
)
Pattern 3: Environment VariablesDirect link to Pattern 3: Environment Variables
# Set environment variables, then use default config
config = FilterProtegeModelConfig()
Pattern 4: Mixed ConfigurationDirect link to Pattern 4: Mixed Configuration
config = FilterProtegeModelConfig(
protege_task="ocr", # Explicit task
model_config={} # Auto-detect model config
)
Data Access PatternsDirect link to Data Access Patterns
Accessing Results by Task TypeDirect link to Accessing Results by Task Type
# Access frame metadata
frame_meta = frame.data.get('meta', {})
# For OCR models
if 'ocr_texts' in frame_meta:
texts = frame_meta['ocr_texts']
confidence = frame_meta['ocr_confidence']
architecture = frame_meta['ocr_architecture']
print(f"Detected texts: {texts}")
print(f"Confidence: {confidence}")
print(f"Architecture: {architecture}")
# For Detection models
elif 'detections' in frame_meta:
detections = frame_meta['detections']
confidence = frame_meta['detection_confidence']
print(f"Detected objects: {detections}")
print(f"Confidence: {confidence}")
# For Classification models
elif 'classifications' in frame_meta:
classifications = frame_meta['classifications']
scores = frame_meta['classification_scores']
print(f"Classifications: {classifications}")
print(f"Scores: {scores}")
# For Multilabel Classification models
elif 'classes' in frame_meta:
classes = frame_meta['classes']
confidences = frame_meta['confidences']
architecture = frame_meta.get('architecture', 'unknown')
print(f"Detected classes: {classes}")
print(f"Confidences: {confidences}")
print(f"Architecture: {architecture}")
# Process multilabel results
if classes:
for class_name, confidence in zip(classes, confidences):
print(f" {class_name}: {confidence:.3f}")
else:
print("No classes detected above threshold")
Error HandlingDirect link to Error Handling
# Check for errors in results
frame_meta = frame.data.get('meta', {})
if "error" in frame_meta:
error_msg = frame_meta["error"]
print(f"Processing error: {error_msg}")
# Check for empty results
if not frame_meta.get("ocr_texts", []):
print("No text detected in this frame")
Extending for New Task TypesDirect link to Extending for New Task Types
To add support for a new task type:
- Create a new model class inheriting from
BaseModel - Add task detection in
model_detection.py - Update factory function in
models/__init__.py - Add configuration options to the documentation
Example for a new "segmentation" task:
# In models/segmentation_model.py
class SegmentationModel(BaseModel):
def __init__(self, runtime, confidence_threshold, **kwargs):
# Implementation
pass
# In models/__init__.py
elif task_type == "segmentation":
return SegmentationModel(runtime, confidence_threshold, **kwargs)
# In model_detection.py
def _detect_segmentation_config(model_config, current_config):
# Detect segmentation-specific configuration
pass
Getting HelpDirect link to Getting Help
- Technical Issues: Check the Technical Documentation
- Usage Questions: See this comprehensive usage guide
- Examples: Run
python scripts/filter_ocr.pyor other example scripts
ContributingDirect link to Contributing
To add support for new task types:
- Create a new model class inheriting from
BaseModel - Add task detection in
model_detection.py - Update factory function in
models/__init__.py - Add configuration options to documentation
See the Development Guide for detailed instructions.
Best PracticesDirect link to Best Practices
- Use auto-detection when possible to reduce configuration complexity
- Set appropriate confidence thresholds for your use case
- Enable visualization during development for debugging
- Disable visualization in production for better performance
- Use environment variables for deployment flexibility
- Handle empty results gracefully in downstream processing
- Monitor processing times for performance optimization
TroubleshootingDirect link to Troubleshooting
Common IssuesDirect link to Common Issues
Task not detected correctly:
- Check model configuration in artifact
- Verify
protege_tasksetting - Review model architecture compatibility
Configuration not applied:
- Ensure configuration keys match expected format
- Check environment variable names
- Verify model supports the configuration
Performance issues:
- Disable visualization if not needed
- Use appropriate device (CPU vs GPU)
- Adjust confidence thresholds
- Monitor processing times in results
Empty results:
- Check confidence threshold settings
- Verify model input requirements
- Review preprocessing configuration
- Check for errors in results metadata