The ImageProcessor class is a new functional class that extracts all image processing functionality from the VesselTracer class, providing better separation of concerns and more modular code architecture. This design allows you to use image processing methods independently or as part of the full VesselTracer pipeline.
- VesselTracer: Orchestrates the pipeline, manages data flow, handles I/O, and coordinates analysis
- ImageProcessor: Focuses solely on image processing algorithms and operations
- ImageModel/ROI: Pure data models without processing logic
- Use individual processing methods without running the entire pipeline
- Easy to test specific processing steps in isolation
- Better code reusability across different contexts
- Processing algorithms are centralized in one class
- Easier to add new processing methods
- Cleaner interfaces and dependencies
VesselTracer/
├── image_model.py # Data models (ImageModel, ROI)
├── image_processor.py # Processing algorithms (ImageProcessor)
├── tracer.py # Pipeline orchestration (VesselTracer, VesselTracerConfig)
└── plotting.py # Visualization utilities
The core processing class that contains all image processing methods:
from VesselTracer import ImageProcessor, VesselTracerConfig
# Create configuration
config = VesselTracerConfig()
config.micron_gauss_sigma = 2.0
config.micron_median_filter_size = 25.0
# Create processor
processor = ImageProcessor(
config=config,
verbose=2,
use_gpu=False # Set to True for GPU acceleration
)- normalize_image(image_model) - Normalize image to [0,1] range
- segment_roi(image_model, ...) - Extract region of interest
- median_filter_background_subtraction(roi_model) - Background subtraction
- detrend_volume(roi_model) - Remove linear intensity trend
- smooth_volume(roi_model) - Gaussian smoothing
- binarize_volume(roi_model, method) - Threshold-based binarization
- determine_regions(roi_model) - Find vessel depth regions
- create_region_map_volume(roi_model, region_bounds) - Create region labels
- trace_vessel_paths(roi_model, region_bounds, ...) - Skeletonize and trace paths
import numpy as np
from VesselTracer import ImageModel, ROI, VesselTracerConfig, ImageProcessor
# Create your data
volume = np.random.rand(50, 100, 100).astype(np.float32)
# Create data models
image_model = ImageModel(
volume=volume,
pixel_size_x=0.5, # microns per pixel
pixel_size_y=0.5,
pixel_size_z=1.0
)
# Create configuration
config = VesselTracerConfig()
config.find_roi = False # Use entire volume
config.micron_gauss_sigma = 1.0
# Create processor
processor = ImageProcessor(config=config, verbose=2)
# Run individual processing steps
roi = processor.segment_roi(image_model)
smoothed_vol = processor.smooth_volume(roi)
binary_vol = processor.binarize_volume(roi)The VesselTracer class now uses ImageProcessor internally:
from VesselTracer import VesselTracer
# Initialize tracer (now creates ImageProcessor internally)
tracer = VesselTracer("path/to/image.czi")
# Activate GPU acceleration (delegates to ImageProcessor)
tracer.activate_gpu()
# Run analysis (uses ImageProcessor methods internally)
tracer.run_analysis()# Create custom configuration
config = VesselTracerConfig()
config.micron_gauss_sigma = 2.0 # Heavier smoothing
config.binarization_method = 'otsu' # Use Otsu instead of triangle
config.regions = ['surface', 'middle', 'deep']
# Create processor with custom settings
processor = ImageProcessor(config=config, verbose=2)
# Run custom pipeline
roi = processor.segment_roi(image_model)
corrected, background = processor.median_filter_background_subtraction(roi)
detrended = processor.detrend_volume(roi)
smoothed = processor.smooth_volume(roi)
binary = processor.binarize_volume(roi, method='otsu')
# Analyze regions and trace paths
region_bounds = processor.determine_regions(roi)
region_map = processor.create_region_map_volume(roi, region_bounds)
paths, stats = processor.trace_vessel_paths(roi, region_bounds, split_paths=True)GPU acceleration is handled transparently by the ImageProcessor:
# Create processor with GPU enabled
processor = ImageProcessor(config=config, use_gpu=True)
# Activate GPU (tests CUDA functionality)
if processor.activate_gpu():
print("GPU activated successfully!")
else:
print("Falling back to CPU processing")
# All subsequent operations will use GPU if available
smoothed = processor.smooth_volume(roi) # Uses GPU automatically
binary = processor.binarize_volume(roi) # Uses GPU automaticallyThe VesselTracerConfig class manages all processing parameters in microns:
config = VesselTracerConfig()
# Set parameters in microns (automatically converted to pixels)
config.micron_gauss_sigma = 2.0 # Gaussian smoothing
config.micron_median_filter_size = 25.0 # Median filter size
config.micron_close_radius = 1.5 # Morphological closing
# Processing parameters
config.min_object_size = 64 # Minimum object size (voxels)
config.binarization_method = 'triangle' # Thresholding method
# Region analysis parameters
config.regions = ['superficial', 'intermediate', 'deep']
config.region_peak_distance = 2
config.region_height_ratio = 0.80If you were using VesselTracer methods directly, the interface remains the same:
# Old way (still works)
tracer = VesselTracer("image.czi")
tracer.smooth()
tracer.binarize()
# New way (more flexible)
tracer = VesselTracer("image.czi")
# ImageProcessor is created automatically and used internally
tracer.smooth() # Delegates to processor.smooth_volume()
tracer.binarize() # Delegates to processor.binarize_volume()
# Direct access to processor
tracer.processor.smooth_volume(tracer.roi_model)The ImageProcessor provides clear error messages:
try:
# This will raise ValueError if no volume data
processor.smooth_volume(empty_roi)
except ValueError as e:
print(f"Processing error: {e}")
try:
# This will raise ValueError if CuPy not available
processor.activate_gpu()
except Exception as e:
print(f"GPU activation failed: {e}")You can now test individual processing steps easily:
import pytest
from VesselTracer import ImageProcessor, VesselTracerConfig, ROI
def test_smoothing():
# Create test data
volume = np.random.rand(10, 20, 20)
roi = ROI(volume=volume, pixel_size_x=1.0, pixel_size_y=1.0, pixel_size_z=1.0)
# Create processor
config = VesselTracerConfig()
processor = ImageProcessor(config)
# Test smoothing
smoothed = processor.smooth_volume(roi)
# Verify results
assert smoothed.shape == volume.shape
assert smoothed.dtype == volume.dtype- GPU Acceleration: Significant speedup for large volumes when CuPy is available
- Parallel Processing: Median filtering uses multithreading on CPU
- Memory Efficiency: Processing is done in-place where possible
- Caching: Pixel conversions are cached to avoid recomputation
The modular architecture makes it easy to add new features:
- New Processing Methods: Add methods to
ImageProcessor - Alternative Algorithms: Easy to implement different binarization or smoothing methods
- Custom Pipelines: Create specialized processors for different imaging modalities
- Batch Processing: Process multiple images with the same
ImageProcessorinstance
See example_usage.py for a complete example showing:
- Basic processing pipeline
- GPU acceleration usage
- Custom parameter configuration
- Direct method usage
- Error handling
python example_usage.pyThis will run through all the different ways to use the ImageProcessor class.