Specification#
Analyzers are callbacks passed to match_exhaustive
to enable custom analysis workflows of exhaustive searches. Rather than storing all intermediate results in memory, analyzers accumulate only the most relevant data.
Key characteristics of analyzers
Called individually for each rotation in the search space
Support distributed computation with result merging capabilities
Maintain internal state that evolves throughout the matching process
AbstractAnalyzer
defines the interface specification that all analyzers must implement.
Abstract base class for template matching analyzers. |
How Analyzers Work#
Analyzers follow a stateful, three-phase pattern
- 1. Initialization Phase
The analyzer creates an initial state using
AbstractAnalyzer.init_state()
. This state contains empty data structures that will accumulate results across all rotations. For example, an analyzer might initialize empty arrays for storing top scores, coordinates, and rotation matrices.- 2. Accumulation Phase
For each rotation tested during template matching, the analyzer’s
AbstractAnalyzer.__call__()
method is invoked withCurrent state from previous iterations
New scores array from the current rotation
Rotation matrix that generated these scores
The analyzer updates its state by incorporating the new data according to its specific logic (e.g., keeping only top N scores, filtering by threshold, etc.) and returns the updated state for the next iteration
# For each rotation in the search space for rotation in rotations: # Compute correlation scores for this rotation scores = compute_scores(template, target, rotation) # Update analyzer state with new results analyzer_state = analyzer(analyzer_state, scores, rotation)
- 3. Finalization Phase
After all rotations are processed,
AbstractAnalyzer.result()
converts the accumulated state into the final output format. This may include post-processing operations like coordinate transformations or convolution mode corrections.
State Management#
Analyzers use a stateful accumulation pattern that ensures data ownership remains external to analyzer instances. This design maintains compatibility with just-in-time compilation features, particularly for the JAX backend.
Parallel Processing#
Analyzers support parallel processing through
Shared Memory: The
AbstractAnalyzer.shareable
property enables multi-process operation using shared memory buffers, avoiding expensive data copying.Result Merging: The
AbstractAnalyzer.merge()
class method combines results from different processes or data splits into unified output.
Custom Analyzer Implementation#
To implement a custom analyzer:
Inherit from AbstractAnalyzer:
class MyAnalyzer(AbstractAnalyzer): pass
Define the state structure in
init_state()
Implement accumulation logic in
__call__()
Handle finalization in
result()
Support merging in
merge()
Set shareability via the
shareable
property
This flexible architecture allows for diverse analysis strategies including peak detection, clustering, statistical analysis, and custom filtering without modifying the core template matching algorithms.