From 84f76c258b1fd261f5a957647189108cf12875b2 Mon Sep 17 00:00:00 2001 From: Pro Date: Mon, 22 Apr 2024 20:20:35 +0200 Subject: [PATCH] Cleanup --- CHANGES.md | 3 +- binding-generator/src/element.rs | 3 +- binding-generator/src/func.rs | 2 +- binding-generator/src/settings.rs | 2 ++ ci/msrv.sh | 1 - ci/script.sh | 2 -- examples/cuda.rs | 35 ++++++++++------------ src/manual/core/input_output_array.rs | 40 +++++-------------------- src/manual/core/mat.rs | 12 ++++++-- src/manual/core/vector/vector_extern.rs | 2 +- src/traits/boxed.rs | 8 ++--- src/traits/opencv_type.rs | 14 ++++----- tests/marshalling_only_latest_opencv.rs | 8 ++--- tests/mat.rs | 34 ++++++++++++++++++++- 14 files changed, 89 insertions(+), 77 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 004710d0..444da0f2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,7 +9,8 @@ semantics. * Some constructors have received `_mut` suffix where appropriate. * Unsafe `Mat` constructors (`*_with_data`) have received `_unsafe` suffix and safe versions have been introduced that return - `BoxedRef`/`BoxedRefMut` + `BoxedRef`/`BoxedRefMut`. Consequently, `Mat::from_slice_rows_cols` was replaced by `Mat::new_rows_cols_with_data`, note the + different order and types of the arguments. * `MatSize::new` is now unsafe and accepts a pointer. * 0.90.0 diff --git a/binding-generator/src/element.rs b/binding-generator/src/element.rs index e6a4e927..1544ba99 100644 --- a/binding-generator/src/element.rs +++ b/binding-generator/src/element.rs @@ -60,7 +60,8 @@ impl DefaultElement { | EntityKind::ClassTemplate | EntityKind::ClassTemplatePartialSpecialization | EntityKind::FunctionTemplate - | EntityKind::Method => { + | EntityKind::Method + | EntityKind::FunctionDecl => { // handle anonymous enums inside classes and anonymous namespaces if let Some(parent_name) = parent.get_name() { parts.push(parent_name); diff --git a/binding-generator/src/func.rs b/binding-generator/src/func.rs index 6813d502..7599170d 100644 --- a/binding-generator/src/func.rs +++ b/binding-generator/src/func.rs @@ -629,7 +629,7 @@ impl Element for Func<'_, '_> { }; is_unavailable || settings::FUNC_EXCLUDE.contains(identifier.as_str()) - || (self.is_generic()) + || self.is_generic() || self.arguments().iter().any(|a| a.type_ref().exclude_kind().is_ignored()) || kind.as_operator().map_or(false, |(_, kind)| match kind { OperatorKind::Unsupported => true, diff --git a/binding-generator/src/settings.rs b/binding-generator/src/settings.rs index 44ae567a..93b12731 100644 --- a/binding-generator/src/settings.rs +++ b/binding-generator/src/settings.rs @@ -85,6 +85,8 @@ pub static PRIMITIVE_TYPEDEFS: Lazy> = Lazy::new(|| pub static STATIC_MODULES: Lazy> = Lazy::new(|| BTreeSet::from(["core", "sys", "types"])); +/// Types that can be used as `Mat` element +/// cpp_name(Reference) pub static DATA_TYPES: Lazy> = Lazy::new(|| { HashSet::from([ "unsigned char", diff --git a/ci/msrv.sh b/ci/msrv.sh index 90977d74..1a525d76 100755 --- a/ci/msrv.sh +++ b/ci/msrv.sh @@ -10,5 +10,4 @@ rustc --version rustc --print=cfg cargo update -rm -vf examples/cuda.rs # no CUDA support in CI cargo check -vv --all-targets --all-features --workspace --tests diff --git a/ci/script.sh b/ci/script.sh index 463e1dcd..abdda57d 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -53,8 +53,6 @@ if [[ "${OPENCV_VERSION:-}" != "4.9.0" ]]; then rm -vf tests/*_only_latest_opencv.rs rm -vf examples/dnn_face_detect.rs examples/gapi_api_example.rs examples/text_detection.rs fi -# the following examples don't work in CI -rm -vf examples/cuda.rs echo "=== Current directory: $(pwd)" echo "=== Environment variable dump:" diff --git a/examples/cuda.rs b/examples/cuda.rs index a2a361cc..1bb04886 100644 --- a/examples/cuda.rs +++ b/examples/cuda.rs @@ -1,8 +1,9 @@ use std::{env, time}; +use time::Instant; -use opencv::core::{GpuMat, Size}; +use opencv::core::Size; use opencv::prelude::*; -use opencv::{core, cudafilters, cudaimgproc, imgcodecs, imgproc, Result}; +use opencv::{core, imgcodecs, imgproc, Result}; const ITERATIONS: usize = 100; @@ -25,40 +26,36 @@ fn main() -> Result<()> { } ); println!("Timing CPU implementation... "); - let img = imgcodecs::imread(&img_file, imgcodecs::IMREAD_COLOR)?; - let start = time::Instant::now(); + let img = imgcodecs::imread_def(&img_file)?; + let start = Instant::now(); for _ in 0..ITERATIONS { let mut gray = Mat::default(); - imgproc::cvt_color(&img, &mut gray, imgproc::COLOR_BGR2GRAY, 0)?; + imgproc::cvt_color_def(&img, &mut gray, imgproc::COLOR_BGR2GRAY)?; let mut blurred = Mat::default(); - imgproc::gaussian_blur(&gray, &mut blurred, Size::new(7, 7), 1.5, 0., core::BORDER_DEFAULT)?; + imgproc::gaussian_blur_def(&gray, &mut blurred, Size::new(7, 7), 1.5)?; let mut edges = Mat::default(); - imgproc::canny(&blurred, &mut edges, 0., 50., 3, false)?; + imgproc::canny_def(&blurred, &mut edges, 0., 50.)?; } println!("{:#?}", start.elapsed()); + #[cfg(all(ocvrs_has_module_cudafilters, ocvrs_has_module_cudaimgproc))] if cuda_available { + use opencv::core::GpuMat; + use opencv::{cudafilters, cudaimgproc}; + println!("Timing CUDA implementation... "); - let img = imgcodecs::imread(&img_file, imgcodecs::IMREAD_COLOR)?; + let img = imgcodecs::imread_def(&img_file)?; let mut img_gpu = GpuMat::new_def()?; img_gpu.upload(&img)?; let mut stream = core::Stream::default()?; - let start = time::Instant::now(); + let start = Instant::now(); for _ in 0..ITERATIONS { let mut gray = GpuMat::new_def()?; cudaimgproc::cvt_color(&img_gpu, &mut gray, imgproc::COLOR_BGR2GRAY, 0, &mut stream)?; let mut blurred = GpuMat::new_def()?; - let mut filter = cudafilters::create_gaussian_filter( - gray.typ()?, - blurred.typ()?, - Size::new(7, 7), - 1.5, - 0., - core::BORDER_DEFAULT, - core::BORDER_DEFAULT, - )?; + let mut filter = cudafilters::create_gaussian_filter_def(gray.typ()?, blurred.typ()?, Size::new(7, 7), 1.5)?; filter.apply(&gray, &mut blurred, &mut stream)?; let mut edges = GpuMat::new_def()?; - let mut detector = cudaimgproc::create_canny_edge_detector(0., 50., 3, false)?; + let mut detector = cudaimgproc::create_canny_edge_detector_def(0., 50.)?; detector.detect(&blurred, &mut edges, &mut stream)?; stream.wait_for_completion()?; } diff --git a/src/manual/core/input_output_array.rs b/src/manual/core/input_output_array.rs index c430bedf..d0c98ff2 100644 --- a/src/manual/core/input_output_array.rs +++ b/src/manual/core/input_output_array.rs @@ -194,80 +194,56 @@ impl ToInputArray for [u8; N] { } } -impl ToInputArray for BoxedRef<'_, T> -where - T: Boxed + ToInputArray, -{ +impl ToInputArray for BoxedRef<'_, T> { #[inline] fn input_array(&self) -> Result> { self.reference.input_array() } } -impl ToInputArray for &BoxedRef<'_, T> -where - T: Boxed + ToInputArray, -{ +impl ToInputArray for &BoxedRef<'_, T> { #[inline] fn input_array(&self) -> Result> { (*self).input_array() } } -impl ToInputArray for BoxedRefMut<'_, T> -where - T: Boxed + ToInputArray, -{ +impl ToInputArray for BoxedRefMut<'_, T> { #[inline] fn input_array(&self) -> Result> { self.reference.input_array() } } -impl ToInputArray for &BoxedRefMut<'_, T> -where - T: Boxed + ToInputArray, -{ +impl ToInputArray for &BoxedRefMut<'_, T> { #[inline] fn input_array(&self) -> Result> { (*self).input_array() } } -impl ToOutputArray for BoxedRefMut<'_, T> -where - T: Boxed + ToOutputArray, -{ +impl ToOutputArray for BoxedRefMut<'_, T> { #[inline] fn output_array(&mut self) -> Result> { self.reference.output_array() } } -impl ToOutputArray for &mut BoxedRefMut<'_, T> -where - T: Boxed + ToOutputArray, -{ +impl ToOutputArray for &mut BoxedRefMut<'_, T> { #[inline] fn output_array(&mut self) -> Result> { (*self).output_array() } } -impl ToInputOutputArray for BoxedRefMut<'_, T> -where - T: Boxed + ToInputOutputArray, -{ +impl ToInputOutputArray for BoxedRefMut<'_, T> { #[inline] fn input_output_array(&mut self) -> Result> { self.reference.input_output_array() } } -impl ToInputOutputArray for &mut BoxedRefMut<'_, T> -where - T: Boxed + ToInputOutputArray, -{ +impl ToInputOutputArray for &mut BoxedRefMut<'_, T> { #[inline] fn input_output_array(&mut self) -> Result> { (*self).input_output_array() diff --git a/src/manual/core/mat.rs b/src/manual/core/mat.rs index d9bd3295..dfd2f4b6 100644 --- a/src/manual/core/mat.rs +++ b/src/manual/core/mat.rs @@ -100,11 +100,14 @@ fn match_is_continuous(mat: &(impl MatTraitConst + ?Sized)) -> Result<()> { #[inline] fn match_length(sizes: &[i32], len: usize) -> Result<()> { + if sizes.is_empty() { + return Err(Error::new(core::StsUnmatchedSizes, "Dimensions must not be empty")); + } let data_len = i32::try_from(len)?; if sizes.iter().product::() != data_len { let msg = if sizes.len() == 2 { format!( - "The length of the slice: {data_len} must match the passed row count: {rows} and column count: {cols} exactly", + "The length of the slice: {data_len} must match the passed row: {rows} and column: {cols} counts exactly", rows = sizes[0], cols = sizes[1], ) @@ -204,7 +207,7 @@ impl Mat { Ok(out) } - /// Create a new `Mat` from a single-dimensional slice with custom shape + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_rows_cols_with_data(rows: i32, cols: i32, data: &[T]) -> Result> { match_length(&[rows, cols], data.len())?; @@ -214,6 +217,7 @@ impl Mat { Ok(>::from(m)) } + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_rows_cols_with_data_mut(rows: i32, cols: i32, data: &mut [T]) -> Result> { match_length(&[rows, cols], data.len())?; @@ -222,6 +226,7 @@ impl Mat { Ok(>::from(m)) } + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_size_with_data(size: Size, data: &[T]) -> Result> { match_length(&[size.width, size.height], data.len())?; @@ -229,6 +234,7 @@ impl Mat { Ok(>::from(m)) } + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_size_with_data_mut(size: Size, data: &mut [T]) -> Result> { match_length(&[size.width, size.height], data.len())?; @@ -236,6 +242,7 @@ impl Mat { Ok(>::from(m)) } + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_nd_with_data<'data, T: DataType>(sizes: &[i32], data: &'data [T]) -> Result> { match_length(sizes, data.len())?; @@ -243,6 +250,7 @@ impl Mat { Ok(>::from(m)) } + /// Create a new `Mat` that references a single-dimensional slice with custom shape #[inline] pub fn new_nd_with_data_mut<'data, T: DataType>(sizes: &[i32], data: &'data mut [T]) -> Result> { match_length(sizes, data.len())?; diff --git a/src/manual/core/vector/vector_extern.rs b/src/manual/core/vector/vector_extern.rs index 5259a20a..ed66d05b 100644 --- a/src/manual/core/vector/vector_extern.rs +++ b/src/manual/core/vector/vector_extern.rs @@ -1,7 +1,7 @@ use crate::core::Vector; use crate::platform_types::size_t; use crate::traits::OpenCVType; -use crate::{extern_arg_send, extern_container_send, extern_receive, extern_send}; +use crate::{extern_arg_send, extern_container_send, extern_receive}; /// This trait is implemented by any type that can be stored inside `Vector`. /// diff --git a/src/traits/boxed.rs b/src/traits/boxed.rs index f8c8c9f6..5279d034 100644 --- a/src/traits/boxed.rs +++ b/src/traits/boxed.rs @@ -75,22 +75,22 @@ macro_rules! opencv_type_boxed { ($type: ty) => { impl $crate::traits::Boxed for $type { #[inline] - unsafe fn from_raw(ptr: extern_receive!($type)) -> Self { + unsafe fn from_raw(ptr: $crate::extern_receive!($type)) -> Self { Self { ptr } } #[inline] - fn into_raw(self) -> extern_send!(mut $type) { + fn into_raw(self) -> $crate::extern_send!(mut $type) { ::std::mem::ManuallyDrop::new(self).ptr } #[inline] - fn as_raw(&self) -> extern_send!($type) { + fn as_raw(&self) -> $crate::extern_send!($type) { self.ptr } #[inline] - fn as_raw_mut(&mut self) -> extern_send!(mut $type) { + fn as_raw_mut(&mut self) -> $crate::extern_send!(mut $type) { self.ptr } } diff --git a/src/traits/opencv_type.rs b/src/traits/opencv_type.rs index a02bccd6..73df450f 100644 --- a/src/traits/opencv_type.rs +++ b/src/traits/opencv_type.rs @@ -72,7 +72,7 @@ pub trait OpenCVTypeExternContainerMove: OpenCVTypeExternContainer { #[macro_export] macro_rules! extern_receive { ($typ: ty) => { - extern_receive!($typ: '_) + $crate::extern_receive!($typ: '_) }; ($typ: ty: $lt: lifetime) => { <$typ as $crate::traits::OpenCVType<$lt>>::ExternReceive @@ -96,16 +96,16 @@ macro_rules! extern_send { #[macro_export] macro_rules! extern_container_send { (mut $typ: ty: $lt: lifetime) => { - extern_send!(mut <$typ as $crate::traits::OpenCVTypeArg<$lt>>::ExternContainer) + $crate::extern_send!(mut <$typ as $crate::traits::OpenCVTypeArg<$lt>>::ExternContainer) }; ($typ: ty: $lt: lifetime) => { - extern_send!(<$typ as $crate::traits::OpenCVTypeArg<$lt>>::ExternContainer) + $crate::extern_send!(<$typ as $crate::traits::OpenCVTypeArg<$lt>>::ExternContainer) }; (mut $typ: ty) => { - extern_container_send!(mut $typ: '_) + $crate::extern_container_send!(mut $typ: '_) }; ($typ: ty) => { - extern_container_send!($typ: '_) + $crate::extern_container_send!($typ: '_) }; } @@ -114,10 +114,10 @@ macro_rules! extern_container_send { #[macro_export] macro_rules! extern_arg_send { (mut $typ: ty: $lt: lifetime) => { - extern_container_send!(mut <$typ as $crate::traits::OpenCVType<$lt>>::Arg: $lt) + $crate::extern_container_send!(mut <$typ as $crate::traits::OpenCVType<$lt>>::Arg: $lt) }; ($typ: ty: $lt: lifetime) => { - extern_container_send!(<$typ as $crate::traits::OpenCVType<$lt>>::Arg: $lt) + $crate::extern_container_send!(<$typ as $crate::traits::OpenCVType<$lt>>::Arg: $lt) }; } diff --git a/tests/marshalling_only_latest_opencv.rs b/tests/marshalling_only_latest_opencv.rs index 8ecb0024..10a53bdc 100644 --- a/tests/marshalling_only_latest_opencv.rs +++ b/tests/marshalling_only_latest_opencv.rs @@ -1,13 +1,11 @@ //! Tests that will not be run in CI on OpenCV 4.2.0, 4.5.4 and 3.4.16 due to missing classes -use opencv::prelude::*; -use opencv::Result; - /// Setting and getting fields through Ptr #[test] -fn field_access_on_ptr() -> Result<()> { - #![cfg(all(ocvrs_has_module_aruco, any(ocvrs_opencv_branch_34, ocvrs_opencv_branch_4)))] +#[cfg(all(ocvrs_has_module_aruco, any(ocvrs_opencv_branch_34, ocvrs_opencv_branch_4)))] +fn field_access_on_ptr() -> opencv::Result<()> { use opencv::aruco::EstimateParameters; + use opencv::prelude::*; // the location and parameters are wildly different between even the minor release in the OpenCV branches, so for now // let's just limit to only those fields that are stable // #[cfg(ocvrs_opencv_branch_34)] diff --git a/tests/mat.rs b/tests/mat.rs index 95627500..7e91d645 100644 --- a/tests/mat.rs +++ b/tests/mat.rs @@ -6,7 +6,7 @@ use matches::assert_matches; use opencv::core::{MatConstIterator, MatIter, Point, Point2d, Rect, Scalar, Size, Vec2b, Vec2s, Vec3d, Vec3f, Vec4w}; use opencv::prelude::*; use opencv::types::{VectorOfMat, VectorOfi32}; -use opencv::{core, Error, Result}; +use opencv::{core, imgproc, Error, Result}; const PIXEL: &[u8] = include_bytes!("pixel.png"); @@ -1026,6 +1026,38 @@ fn mat_from_slice() -> Result<()> { assert_eq!(111, src_u8[6]); } + { + let mut src_u8 = src_u8; + let mut mat = Mat::from_slice_mut(&mut src_u8)?; + core::divide_def(100., &[2; 10], &mut mat)?; + assert_eq!([50; 10], src_u8); + } + + { + let src: &[u8] = &[]; + let mat_res = Mat::new_nd_with_data(&[], src); + assert_matches!( + mat_res, + Err(Error { + code: core::StsUnmatchedSizes, + .. + }) + ); + } + + { + let src = [1u8; 20]; + let src_mat = Mat::new_rows_cols_with_data(4, 5, &src)?; + let mut dst = [0u8; 10]; + let mut dst_mat = Mat::new_rows_cols_with_data_mut(2, 5, &mut dst)?; + assert_eq!(Size::new(5, 2), dst_mat.size()?); + // this reallocates a `Mat` and disconnects in from the `dst` internally, so it's left untouched + imgproc::cvt_color_def(&src_mat, &mut dst_mat, imgproc::COLOR_GRAY2BGR)?; + assert_eq!(3, dst_mat.channels()); + assert_eq!(Size::new(5, 4), dst_mat.size()?); + assert_eq!([0; 10], dst); + } + { let mat_res = Mat::new_rows_cols_with_data(3, 3, &src_u8); assert_matches!(