[Feature]: Optimize `pyrdown_f32` with separable convolution and Rayon parallelism
#763 opened on Feb 25, 2026
Repository metrics
- Stars
- (675 stars)
- PR merge metrics
- (PR metrics pending)
Description
🚀 Feature Description
Optimize the pyrdown_f32 function (currently found in crates/kornia-imgproc/src/pyramid.rs) to use separable 1D Gaussian convolutions and parallelize the execution using rayon.
📂 Feature Category
Performance Optimization
💡 Motivation
Currently, pyrdown_f32 is implemented as a single-threaded, fully-nested 5x5 convolution loop. This makes it an $O(25)$ operation per pixel and a significant bottleneck for algorithms that rely heavily on floating-point pyramids, such as the Pyramidal Lucas-Kanade Optical Flow (PR #756).
For comparison, generating a 128x112 downsampled image via pyrdown_f32 currently takes ~87µs, while generating a massive 512x448 upsampled image via pyrup_f32takes only ~75µs - solely because pyrup_f32 utilizes separable convolutions and rayon. Bringing pyrdown_f32up to par with the other pyramid functions will yield severe performance improvements.
💭 Proposed Solution
- Introduce pyrdown_horizontal_pass_f32 and pyrdown_vertical_pass_f32 helper functions to match the parallel structure of the existing pyrdown_u8 passes.
- Use floating-point Gaussian weights: 0.0625, 0.25, 0.375, 0.25, 0.0625.
- The horizontal pass will convolve and downsample in the X direction, writing to an intermediate buffer. The vertical pass will convolve and downsample in the Y direction reading from the buffer and writing directly to the destination.
- Utilize rayon's par_chunks_mut() across rows during both passes.
- Ensure the OpenCV-compatible reflect_101 border mode is preserved to maintain exact mathematical correctness.
📚 Library Reference
This optimization brings the implementation in line with the already existing pyrdown_u8, pyrup_u8, and pyrup_f32 functions in kornia-imgproc/src/pyramid.rs. It also matches the standard OpenCV optimization strategy for Image Pyramids (cv::pyrDown).
🔄 Alternatives Considered
Vectorization (SIMD): We could manually unroll the loops and write explicit SIMD instructions using std::arch. However, since the rest of the crates rely on standard auto-vectorization and rayon data-parallelism, adding separable kernels + rayon is the idiomatic, safest, and most generic approach for kornia-rs.
🎯 Use Cases
- Pyramidal Lucas-Kanade Optical Flow: Massively speeds up the computation of image pyramids during the initialization step of tracking.
- Feature Extraction (SIFT/SURF equivalents): Any multi-scale algorithms involving Difference-of-Gaussians or scale-space generation that operate on f32 tensors.
📝 Additional Context
- This change is purely an internal performance optimization and will not alter the public API signature of pyrdown_f32.
- Mathematical correctness will be verified against the existing slow implementation via unit tests.
🤝 Contribution Intent
- I plan to submit a PR to implement this feature
- I'm requesting this feature but not planning to implement it