Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: cargo test --workspace --features ndarray

no-std-build:
name: no_std Build (core only, issue #83)
name: no_std Build (core + imgproc, issues #83/#84)
runs-on: ubuntu-latest

steps:
Expand Down
20 changes: 20 additions & 0 deletions crates/no-std-smoke/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ extern crate alloc;

use alloc::vec;
use purecv::core::error::Result;
use purecv::core::types::{BorderTypes, Size2i};
use purecv::core::{add, determinant, mean, Matrix};
use purecv::imgproc::gaussian_blur;

/// Exercises matrix construction, arithmetic, statistics, and linear algebra.
pub fn smoke() -> Result<f64> {
Expand All @@ -63,3 +65,21 @@ pub fn smoke() -> Result<f64> {

Ok(avg.v[0] + det)
}

/// Exercises the Phase 2 imgproc path: a scalar `gaussian_blur` under no_std.
pub fn smoke_imgproc() -> Result<f32> {
let src = Matrix::<f32>::from_vec(
3,
3,
1,
vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
);
let blurred = gaussian_blur(
&src,
Size2i::new(3, 3),
0.0,
0.0,
BorderTypes::Reflect101,
)?;
Ok(blurred.data[4])
}
3 changes: 3 additions & 0 deletions src/imgproc/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
*
*/

#[allow(unused_imports)]
use num_traits::Float;

#[cfg(feature = "parallel")]
use rayon::prelude::*;

Expand Down
8 changes: 5 additions & 3 deletions src/imgproc/derivatives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
*
*/

use alloc::{string::ToString, vec, vec::Vec};

use crate::core::error::{PureCvError, Result};
use crate::core::utils::border_interpolate;
use crate::core::{BorderTypes, Matrix};
Expand Down Expand Up @@ -337,15 +339,15 @@ where
// and use the SIMD 3x3 kernel for interior rows.
#[cfg(feature = "simd")]
{
if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() && rows > 2 && cols > 2 {
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<f32>() && rows > 2 && cols > 2 {
let row_len = cols * channels;

// Reinterpret src.data as &[f32] — safe because T == f32
let src_f32: &[f32] = unsafe {
std::slice::from_raw_parts(src.data.as_ptr() as *const f32, src.data.len())
core::slice::from_raw_parts(src.data.as_ptr() as *const f32, src.data.len())
};
let dst_f32: &mut [f32] = unsafe {
std::slice::from_raw_parts_mut(dst.data.as_mut_ptr() as *mut f32, dst.data.len())
core::slice::from_raw_parts_mut(dst.data.as_mut_ptr() as *mut f32, dst.data.len())
};

// Process interior rows with SIMD
Expand Down
6 changes: 5 additions & 1 deletion src/imgproc/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
*
*/

use alloc::vec::Vec;
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::error::{PureCvError, Result};
use crate::core::types::BorderTypes;
use crate::core::Matrix;
Expand Down Expand Up @@ -117,7 +121,7 @@ where
*m = magnitude as f32;

if magnitude > 1e-5 {
let angle = gy_f.atan2(gx_f) * 180.0 / std::f64::consts::PI;
let angle = gy_f.atan2(gx_f) * 180.0 / core::f64::consts::PI;
let normalized_angle = if angle < 0.0 { angle + 180.0 } else { angle };

if (0.0..22.5).contains(&normalized_angle)
Expand Down
6 changes: 5 additions & 1 deletion src/imgproc/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
//!
//! `pre_corner_detect` is an independent simpler map using first + second derivatives.

use alloc::vec::Vec;
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::error::{PureCvError, Result};
use crate::core::types::{BorderTypes, Point2f, Size2i, TermCriteria, TermType};
use crate::core::Matrix;
Expand Down Expand Up @@ -431,7 +435,7 @@ where
}

// Sort by response descending.
candidates.sort_unstable_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
candidates.sort_unstable_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(core::cmp::Ordering::Equal));

// Greedily select corners with minimum distance constraint.
let min_dist_sq = min_distance * min_distance;
Expand Down
11 changes: 8 additions & 3 deletions src/imgproc/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@
*
*/

use alloc::{format, string::ToString, vec, vec::Vec};
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::error::Result;
use crate::core::types::BorderTypes;
use crate::core::utils::border_interpolate;
use crate::core::{Matrix, Point2i, PureCvError, Size2i};
use core::any::TypeId;
use core::iter::Sum;
use num_traits::{FromPrimitive, NumCast, ToPrimitive};
use std::any::TypeId;
use std::iter::Sum;

#[cfg(not(feature = "parallel"))]
use crate::core::utils::ParIterFallback;
Expand Down Expand Up @@ -337,7 +341,8 @@ where
}
}
// Sort to find median
neighbors.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
neighbors
.sort_by(|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal));
let median = neighbors[neighbors.len() / 2];
*comp = median;
}
Expand Down
4 changes: 4 additions & 0 deletions src/imgproc/geometric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
*
*/

use alloc::{string::ToString, vec};
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::arithm::{invert, DecompTypes};
use crate::core::error::{PureCvError, Result};
use crate::core::simd::SimdElement;
Expand Down
14 changes: 12 additions & 2 deletions src/imgproc/hough.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
*
*/

use alloc::{vec, vec::Vec};
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::constants::CV_PI;
use crate::core::error::{PureCvError, Result};
use crate::core::types::BorderTypes;
Expand Down Expand Up @@ -131,7 +135,7 @@ pub fn hough_lines(
}

// Stage 3. Sort the detected lines by accumulator value descending
sort_buf.sort_by_key(|b| std::cmp::Reverse(b.1));
sort_buf.sort_by_key(|b| core::cmp::Reverse(b.1));

// Stage 4. Format output
let mut lines = Vec::with_capacity(sort_buf.len());
Expand Down Expand Up @@ -160,6 +164,12 @@ pub fn hough_lines(
///
/// # Returns
/// A vector of `[i32; 4]` representing `(x1, y1, x2, y2)` for each segment.
///
/// Requires the `std` feature: the probabilistic transform shuffles edge points
/// with the thread-local RNG ([`crate::core::rand_shuffle`]), which is std-only
/// until a no_std seedable RNG lands (see issue #82). The deterministic
/// [`hough_lines`] is available under `no_std`.
#[cfg(feature = "std")]
pub fn hough_lines_p(
image: &Matrix<u8>,
rho: f64,
Expand Down Expand Up @@ -452,7 +462,7 @@ pub fn hough_circles(
}

// Sort centers by votes
centers.sort_by_key(|b| std::cmp::Reverse(b.2));
centers.sort_by_key(|b| core::cmp::Reverse(b.2));

let mut circles = Vec::new();

Expand Down
7 changes: 7 additions & 0 deletions src/imgproc/morph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
*
*/

use alloc::{string::ToString, vec::Vec};
// `vec!` is only used by the SIMD-only separable kernel below.
#[cfg(feature = "simd")]
use alloc::vec;
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::arithm;
use crate::core::error::{PureCvError, Result};
use crate::core::simd::SimdElement;
Expand Down
4 changes: 4 additions & 0 deletions src/imgproc/pyramid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
//! These functions implement the classical Gaussian pyramid using the 5-tap
//! kernel `[1, 4, 6, 4, 1]` (sum = 16, outer product sum = 256).

use alloc::{string::ToString, vec, vec::Vec};
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::error::{PureCvError, Result};
use crate::core::simd::SimdElement;
use crate::core::types::{BorderTypes, Size};
Expand Down
4 changes: 4 additions & 0 deletions src/imgproc/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

//! Image resizing operations: [`resize`].

use alloc::string::ToString;
#[allow(unused_imports)]
use num_traits::Float;

use crate::core::error::{PureCvError, Result};
use crate::core::types::Size;
use crate::core::Matrix;
Expand Down
2 changes: 2 additions & 0 deletions src/imgproc/threshold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
*
*/

use alloc::string::ToString;

use crate::core::error::{PureCvError, Result};
use crate::core::simd::SimdElement;
use crate::core::Matrix;
Expand Down
9 changes: 1 addition & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub use alloc::format as __format;

// Global modules
//
// Only `core` and `version` build without `std` for now; the remaining modules
// `core`, `imgproc`, and `version` build without `std`; the remaining modules
// are gated until their own no_std phases land (see issue #82).
#[cfg(feature = "std")]
pub mod calib3d;
Expand All @@ -56,7 +56,6 @@ pub mod core;
pub mod features;
#[cfg(feature = "std")]
pub mod features2d;
#[cfg(feature = "std")]
pub mod imgproc;
pub mod version;
#[cfg(feature = "std")]
Expand All @@ -81,20 +80,14 @@ pub mod prelude {
draw_keypoints, draw_matches, filter_matches, BFMatcher, DMatch, DescriptorMatcher,
FastFeatureDetector, FastType, KeyPoint, NormType, Orb,
};
#[cfg(feature = "std")]
pub use crate::imgproc::derivatives::{laplacian, scharr, sobel};
#[cfg(feature = "std")]
pub use crate::imgproc::edge::canny;
#[cfg(feature = "std")]
pub use crate::imgproc::feature::{
corner_eigen_vals_and_vecs, corner_harris, corner_min_eigen_val, corner_sub_pix,
good_features_to_track, pre_corner_detect,
};
#[cfg(feature = "std")]
pub use crate::imgproc::filter::{bilateral_filter, box_filter, gaussian_blur};
#[cfg(feature = "std")]
pub use crate::imgproc::threshold::{threshold, ThresholdTypes};
#[cfg(feature = "std")]
pub use crate::imgproc::{
cvt_color, remap, warp_perspective, ColorConversionCode, InterpolationFlags,
};
Expand Down