meteor_detect/docs/hook_system.md
2025-03-16 21:32:43 +08:00

8.2 KiB

Frame Hook System

Overview

The Frame Hook System provides a flexible and extensible mechanism for processing video frames at various stages in the meteor detection pipeline. It allows for modular frame processing capabilities such as overlay addition, filtering, enhancement, and analysis without modifying the core detection pipeline.

Purpose

This hook-based architecture offers several key benefits:

  1. Modularity: New frame processing capabilities can be added without modifying existing code
  2. Configurability: Individual hooks can be enabled or disabled as needed
  3. Reusability: Common frame processing tasks can be encapsulated and reused
  4. Prioritization: Hooks can be ordered to ensure correct processing sequence
  5. Extensibility: Third-party hooks can be easily integrated

Core Components

FrameHook Trait

The foundation of the hook system is the FrameHook trait, defined in src/hooks/mod.rs:

pub trait FrameHook: Send + Sync {
    fn process_frame(&mut self, frame: &mut core::Mat, timestamp: DateTime<Utc>) -> Result<()>;
    fn get_id(&self) -> &str;
    fn get_name(&self) -> &str;
    fn get_description(&self) -> &str;
    fn is_enabled(&self) -> bool;
    fn set_enabled(&mut self, enabled: bool);
}

This trait defines the essential capabilities that all hooks must implement:

  • Processing Function: The process_frame method receives a frame and applies transformations
  • Identification: Methods to get the hook's ID, name, and description
  • State Management: Methods to check and change the hook's enabled state

HookManager

The HookManager class manages a collection of hooks and is responsible for:

  • Registering new hooks
  • Removing hooks
  • Executing hooks in sequence on frames
  • Providing access to hooks for configuration
pub struct HookManager {
    hooks: Vec<SharedFrameHook>,
}

The manager maintains a vector of thread-safe hook references (SharedFrameHook) to allow concurrent access.

BasicFrameHook

For simple use cases, the BasicFrameHook implementation provides a convenient way to create hooks with closures:

pub struct BasicFrameHook {
    id: String,
    name: String,
    description: String,
    enabled: bool,
    processor: Box<dyn Fn(&mut core::Mat, DateTime<Utc>) -> Result<()> + Send + Sync>,
}

This allows for creating hooks without implementing the full trait:

let hook = BasicFrameHook::new(
    "brightness",
    "Brightness Adjustment",
    "Adjusts frame brightness by a configurable amount",
    true,
    |frame, _| {
        // Increase brightness by 30
        frame.convert_to(frame, -1, 1.0, 30.0)?;
        Ok(())
    }
);

Usage Examples

Watermark Overlay Hook

The watermark overlay system is integrated using the hook system:

// Create a watermark hook
let watermark_hook = hooks::BasicFrameHook::new(
    "watermark",
    "Watermark Overlay",
    "Adds timestamp, GPS, and sensor data overlay to frames",
    config.watermark.enabled,
    move |frame, timestamp| {
        let mut watermark_instance = watermark.lock().unwrap();
        watermark_instance.apply(frame, timestamp)?;
        Ok(())
    }
);

// Register with the hook manager
hook_manager.lock().await.register_hook(Box::new(watermark_hook));

Image Enhancement Hook

A hook for enhancing low-light frames could be implemented as:

let enhancement_hook = hooks::BasicFrameHook::new(
    "enhance",
    "Low-light Enhancement",
    "Enhances visibility in low-light conditions",
    true,
    |frame, _| {
        // Convert to YUV color space
        let mut yuv = core::Mat::default();
        imgproc::cvt_color(frame, &mut yuv, imgproc::COLOR_BGR2YUV, 0)?;
        
        // Split channels
        let mut channels = types::VectorOfMat::new();
        core::split(&yuv, &mut channels)?;
        
        // Apply CLAHE to Y channel
        let clahe = imgproc::create_clahe(2.0, core::Size::new(8, 8))?;
        clahe.apply(&channels.get(0)?, &mut channels.get_mut(0)?)?;
        
        // Merge channels back
        core::merge(&channels, &mut yuv)?;
        
        // Convert back to BGR
        imgproc::cvt_color(&yuv, frame, imgproc::COLOR_YUV2BGR, 0)?;
        
        Ok(())
    }
);

hook_manager.lock().await.register_hook(Box::new(enhancement_hook));

Debug Information Hook

A hook for adding debug information to frames during development:

let debug_hook = hooks::BasicFrameHook::new(
    "debug",
    "Debug Overlay",
    "Adds debug information for development",
    cfg!(debug_assertions),
    |frame, timestamp| {
        // Add frame rate information
        static mut LAST_FRAME: Option<DateTime<Utc>> = None;
        static mut FRAME_COUNTER: u32 = 0;
        static mut FRAME_RATE: f64 = 0.0;
        
        unsafe {
            FRAME_COUNTER += 1;
            
            if let Some(last) = LAST_FRAME {
                let duration = timestamp - last;
                if duration.num_milliseconds() > 1000 {
                    FRAME_RATE = FRAME_COUNTER as f64 / duration.num_seconds() as f64;
                    FRAME_COUNTER = 0;
                    LAST_FRAME = Some(timestamp);
                }
            } else {
                LAST_FRAME = Some(timestamp);
            }
            
            imgproc::put_text(
                frame,
                &format!("FPS: {:.1}", FRAME_RATE),
                core::Point::new(10, 30),
                imgproc::FONT_HERSHEY_SIMPLEX,
                1.0,
                core::Scalar::new(0.0, 255.0, 0.0, 255.0),
                2,
                imgproc::LINE_AA,
                false,
            )?;
        }
        
        Ok(())
    }
);

Advanced Usage

Hook Prioritization

Although not explicitly implemented in the current version, the hook system design allows for future extension to support ordered hook execution:

// Future enhancement - add priority to hooks
hook_manager.register_hook_with_priority(Box::new(preprocessing_hook), 10);
hook_manager.register_hook_with_priority(Box::new(enhancement_hook), 20);
hook_manager.register_hook_with_priority(Box::new(watermark_hook), 30);

Conditional Hooks

Hooks can be created that only activate under certain conditions:

let night_mode_hook = hooks::BasicFrameHook::new(
    "night_mode",
    "Night Mode Enhancement",
    "Enhances frames during night time",
    true,
    move |frame, timestamp| {
        // Only apply during night hours (8 PM to 6 AM)
        let hour = timestamp.hour();
        if hour >= 20 || hour < 6 {
            // Apply night-time enhancement
            // ...
        }
        Ok(())
    }
);

Dynamic Hook Configuration

The hook system allows for runtime configuration changes:

// Find a hook by ID and update its configuration
if let Some(hook) = hook_manager.lock().await.get_hook("watermark") {
    let mut hook = hook.lock().unwrap();
    hook.set_enabled(new_config.watermark.enabled);
}

Performance Considerations

The hook system is designed with performance in mind:

  1. Minimal Overhead: Hooks that are disabled have almost zero impact on performance
  2. Thread Safety: The use of Arc<Mutex<>> enables safe concurrent access
  3. Lazy Evaluation: Hooks are only processed when frames are being processed
  4. Efficient Registration: Hook registration is a one-time cost at startup

For resource-constrained environments, consider:

  • Limiting the number of active hooks
  • Optimizing individual hook processing functions
  • Using condition checks to skip processing when not needed

Extending the System

The hook system can be extended in several ways:

  1. Adding New Hooks: Implement the FrameHook trait for new functionality
  2. Hook Factory: Create a factory pattern for generating hooks from configuration
  3. Hook Pipelines: Group hooks into pipelines for different processing scenarios
  4. Hook Events: Add event callbacks for hook lifecycle events

Conclusion

The Frame Hook System provides a powerful and flexible architecture for extending the frame processing capabilities of the meteor detection system. By breaking down frame processing into modular hooks, it enables a clean separation of concerns and allows for easy addition of new features without modifying existing code.