Improve Matx & friends
MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -395,6 +395,7 @@ pub static FUNC_RENAME: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
"cv_getAffineTransform_const_Point2fX_const_Point2fX" => "+_slice",
"cv_getPerspectiveTransform_const_Point2fX_const_Point2fX" => "+_slice", // 3.2 3.4
"cv_getPerspectiveTransform_const_Point2fX_const_Point2fX_int" => "+_slice", // 4.x
+ "cv_getRotationMatrix2D__Point2f_double_double" => "get_rotation_matrix_2d_matx",
"cv_goodFeaturesToTrack_const__InputArrayX_const__OutputArrayX_int_double_double_const__InputArrayX_int_int_bool_double" => "+_with_gradient",
"cv_calcBackProject_const_MatX_int_const_intX_const_SparseMatX_const__OutputArrayX_const_floatXX_double_bool" => "-", // slice pointers
@@ -475,6 +476,9 @@ pub static FUNC_RENAME: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
// ### dnn ###
out.insert("cv_dnn_BackendNode_BackendNode_int", "-"); // missing in windows dll
+ // ### imgproc ###
+ out.insert("cv_getRotationMatrix2D__Point2f_double_double", "-"); // missing in windows dll
+
// ### stitching ###
out.insert("cv_createStitcherScans_bool", "-"); // missing in windows dll
out.insert("cv_createStitcher_bool", "-"); // missing in windows dll

MODIFY
src/manual/core/matx.rs
src/manual/core/matx.rs
@@ -13,17 +13,10 @@ macro_rules! matx_impl {
pub val: [T; $rows * $cols],
}
- impl<T: $type_trait> From<[T; $rows * $cols]> for $type<T> {
- fn from(s: [T; $rows * $cols]) -> Self {
- Self { val: s }
- }
- }
-
impl<T: $type_trait> $type<T> {
- #![allow(non_upper_case_globals)]
- pub const rows: usize = $rows;
- pub const cols: usize = $cols;
- pub const channels: usize = $rows * $cols;
+ pub const ROWS: usize = $rows;
+ pub const COLS: usize = $cols;
+ pub const CHANNELS: usize = $rows * $cols;
}
impl<T: $type_trait> $crate::core::MatxTrait for $type<T> {
@@ -31,18 +24,24 @@ macro_rules! matx_impl {
#[inline(always)] fn val(&self) -> &[Self::ElemType] { &self.val }
#[inline(always)] fn val_mut(&mut self) -> &mut [Self::ElemType] { &mut self.val }
- #[inline(always)] fn rows() -> usize { Self::rows }
- #[inline(always)] fn cols() -> usize { Self::cols }
- #[inline(always)] fn channels() -> usize { Self::channels }
+ #[inline(always)] fn rows(&self) -> usize { Self::ROWS }
+ #[inline(always)] fn cols(&self) -> usize { Self::COLS }
+ #[inline(always)] fn channels(&self) -> usize { Self::CHANNELS }
- fn all(alpha: T) -> Self {
+ fn all(alpha: Self::ElemType) -> Self {
Self::from([alpha; $rows * $cols])
}
}
+ impl<T: $type_trait> From<[T; $rows * $cols]> for $type<T> {
+ fn from(s: [T; $rows * $cols]) -> Self {
+ Self { val: s }
+ }
+ }
+
impl<T: $type_trait> std::default::Default for $type<T> {
fn default() -> Self {
- Self::from([T::default(); $rows * $cols])
+ Self::all(T::default())
}
}
@@ -59,30 +58,131 @@ macro_rules! matx_impl {
self.get_mut(index).expect("Index out of range")
}
}
+
+ impl<T: $type_trait> std::cmp::PartialEq for $type<T> {
+ fn eq(&self, other: &$type<T>) -> bool {
+ &self.val[..] == &other.val[..]
+ }
+ }
+
+ impl<T: $type_trait> std::fmt::Debug for $type<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ f.debug_struct(stringify!($type))
+ .field("rows", &self.rows())
+ .field("cols", &self.cols())
+ .field("channels", &self.channels())
+ .field("shortdim", &self.shortdim())
+ .finish()
+ }
+ }
};
}
+macro_rules! matx_input_output_array_impl {
+ ($type: ty, $extern_input: ident, $extern_output: ident, $extern_input_output: ident) => {
+ impl $crate::core::ToInputArray for $type {
+ fn input_array(&self) -> $crate::Result<$crate::core::_InputArray> {
+ extern "C" { fn $extern_input(instance: *const $type) -> $crate::sys::Result<*mut std::ffi::c_void>; }
+ unsafe { $extern_input(self) }
+ .into_result()
+ .map(|ptr| $crate::core::_InputArray { ptr })
+ }
+ }
+
+ impl $crate::core::ToInputArray for &$type {
+ #[inline]
+ fn input_array(&self) -> $crate::Result<$crate::core::_InputArray> {
+ (*self).input_array()
+ }
+ }
+
+ impl $crate::core::ToOutputArray for $type {
+ fn output_array(&mut self) -> $crate::Result<$crate::core::_OutputArray> {
+ extern "C" { fn $extern_output(instance: *mut $type) -> $crate::sys::Result<*mut std::ffi::c_void>; }
+ unsafe { $extern_output(self) }
+ .into_result()
+ .map(|ptr| $crate::core::_OutputArray { ptr })
+ }
+ }
+
+ impl $crate::core::ToOutputArray for &mut $type {
+ #[inline]
+ fn output_array(&mut self) -> $crate::Result<$crate::core::_OutputArray> {
+ (*self).output_array()
+ }
+ }
+
+ impl $crate::core::ToInputOutputArray for $type {
+ fn input_output_array(&mut self) -> $crate::Result<$crate::core::_InputOutputArray> {
+ extern "C" { fn $extern_input_output(instance: *mut $type) -> $crate::sys::Result<*mut std::ffi::c_void>; }
+ unsafe { $extern_input_output(self) }
+ .into_result()
+ .map(|ptr| $crate::core::_InputOutputArray { ptr })
+ }
+ }
+
+ impl $crate::core::ToInputOutputArray for &mut $type {
+ #[inline]
+ fn input_output_array(&mut self) -> $crate::Result<$crate::core::_InputOutputArray> {
+ (*self).input_output_array()
+ }
+ }
+ }
+}
+
matx_impl!(Matx12, 1, 2, ValidMatxType);
+matx_input_output_array_impl!(Matx12<f32>, cv_Matx12f_input_array, cv_Matx12f_output_array, cv_Matx12f_input_output_array);
+matx_input_output_array_impl!(Matx12<f64>, cv_Matx12d_input_array, cv_Matx12d_output_array, cv_Matx12d_input_output_array);
matx_impl!(Matx13, 1, 3, ValidMatxType);
+matx_input_output_array_impl!(Matx13<f32>, cv_Matx13f_input_array, cv_Matx13f_output_array, cv_Matx13f_input_output_array);
+matx_input_output_array_impl!(Matx13<f64>, cv_Matx13d_input_array, cv_Matx13d_output_array, cv_Matx13d_input_output_array);
matx_impl!(Matx14, 1, 4, ValidMatxType);
+matx_input_output_array_impl!(Matx14<f32>, cv_Matx14f_input_array, cv_Matx14f_output_array, cv_Matx14f_input_output_array);
+matx_input_output_array_impl!(Matx14<f64>, cv_Matx14d_input_array, cv_Matx14d_output_array, cv_Matx14d_input_output_array);
matx_impl!(Matx16, 1, 6, ValidMatxType);
+matx_input_output_array_impl!(Matx16<f32>, cv_Matx16f_input_array, cv_Matx16f_output_array, cv_Matx16f_input_output_array);
+matx_input_output_array_impl!(Matx16<f64>, cv_Matx16d_input_array, cv_Matx16d_output_array, cv_Matx16d_input_output_array);
matx_impl!(Matx21, 2, 1, ValidMatxType);
+matx_input_output_array_impl!(Matx21<f32>, cv_Matx21f_input_array, cv_Matx21f_output_array, cv_Matx21f_input_output_array);
+matx_input_output_array_impl!(Matx21<f64>, cv_Matx21d_input_array, cv_Matx21d_output_array, cv_Matx21d_input_output_array);
matx_impl!(Matx31, 3, 1, ValidMatxType);
+matx_input_output_array_impl!(Matx31<f32>, cv_Matx31f_input_array, cv_Matx31f_output_array, cv_Matx31f_input_output_array);
+matx_input_output_array_impl!(Matx31<f64>, cv_Matx31d_input_array, cv_Matx31d_output_array, cv_Matx31d_input_output_array);
matx_impl!(Matx41, 4, 1, ValidMatxType);
+matx_input_output_array_impl!(Matx41<f32>, cv_Matx41f_input_array, cv_Matx41f_output_array, cv_Matx41f_input_output_array);
+matx_input_output_array_impl!(Matx41<f64>, cv_Matx41d_input_array, cv_Matx41d_output_array, cv_Matx41d_input_output_array);
matx_impl!(Matx61, 6, 1, ValidMatxType);
+matx_input_output_array_impl!(Matx61<f32>, cv_Matx61f_input_array, cv_Matx61f_output_array, cv_Matx61f_input_output_array);
+matx_input_output_array_impl!(Matx61<f64>, cv_Matx61d_input_array, cv_Matx61d_output_array, cv_Matx61d_input_output_array);
matx_impl!(Matx22, 2, 2, ValidMatxType);
+matx_input_output_array_impl!(Matx22<f32>, cv_Matx22f_input_array, cv_Matx22f_output_array, cv_Matx22f_input_output_array);
+matx_input_output_array_impl!(Matx22<f64>, cv_Matx22d_input_array, cv_Matx22d_output_array, cv_Matx22d_input_output_array);
matx_impl!(Matx23, 2, 3, ValidMatxType);
+matx_input_output_array_impl!(Matx23<f32>, cv_Matx23f_input_array, cv_Matx23f_output_array, cv_Matx23f_input_output_array);
+matx_input_output_array_impl!(Matx23<f64>, cv_Matx23d_input_array, cv_Matx23d_output_array, cv_Matx23d_input_output_array);
matx_impl!(Matx32, 3, 2, ValidMatxType);
+matx_input_output_array_impl!(Matx32<f32>, cv_Matx32f_input_array, cv_Matx32f_output_array, cv_Matx32f_input_output_array);
+matx_input_output_array_impl!(Matx32<f64>, cv_Matx32d_input_array, cv_Matx32d_output_array, cv_Matx32d_input_output_array);
matx_impl!(Matx33, 3, 3, ValidMatxType);
+matx_input_output_array_impl!(Matx33<f32>, cv_Matx33f_input_array, cv_Matx33f_output_array, cv_Matx33f_input_output_array);
+matx_input_output_array_impl!(Matx33<f64>, cv_Matx33d_input_array, cv_Matx33d_output_array, cv_Matx33d_input_output_array);
matx_impl!(Matx34, 3, 4, ValidMatxType);
+matx_input_output_array_impl!(Matx34<f32>, cv_Matx34f_input_array, cv_Matx34f_output_array, cv_Matx34f_input_output_array);
+matx_input_output_array_impl!(Matx34<f64>, cv_Matx34d_input_array, cv_Matx34d_output_array, cv_Matx34d_input_output_array);
matx_impl!(Matx43, 4, 3, ValidMatxType);
+matx_input_output_array_impl!(Matx43<f32>, cv_Matx43f_input_array, cv_Matx43f_output_array, cv_Matx43f_input_output_array);
+matx_input_output_array_impl!(Matx43<f64>, cv_Matx43d_input_array, cv_Matx43d_output_array, cv_Matx43d_input_output_array);
matx_impl!(Matx44, 4, 4, ValidMatxType);
+matx_input_output_array_impl!(Matx44<f32>, cv_Matx44f_input_array, cv_Matx44f_output_array, cv_Matx44f_input_output_array);
+matx_input_output_array_impl!(Matx44<f64>, cv_Matx44d_input_array, cv_Matx44d_output_array, cv_Matx44d_input_output_array);
matx_impl!(Matx66, 6, 6, ValidMatxType);
+matx_input_output_array_impl!(Matx66<f32>, cv_Matx66f_input_array, cv_Matx66f_output_array, cv_Matx66f_input_output_array);
+matx_input_output_array_impl!(Matx66<f64>, cv_Matx66d_input_array, cv_Matx66d_output_array, cv_Matx66d_input_output_array);
#[inline(always)]
fn index_check(idx: (usize, usize), rows: usize, cols: usize) -> Result<()> {
@@ -95,61 +195,60 @@ fn index_check(idx: (usize, usize), rows: usize, cols: usize) -> Result<()> {
}
}
-pub trait MatxTrait: Default {
+pub trait MatxTrait {
type ElemType: ValidMatxType;
- fn rows() -> usize;
- fn cols() -> usize;
+ fn rows(&self) -> usize;
+ fn cols(&self) -> usize;
fn val(&self) -> &[Self::ElemType];
fn val_mut(&mut self) -> &mut [Self::ElemType];
fn all(alpha: Self::ElemType) -> Self where Self: Sized;
#[inline(always)]
- fn channels() -> usize {
- Self::rows() * Self::cols()
+ fn channels(&self) -> usize {
+ self.rows() * self.cols()
}
#[inline(always)]
- fn shortdim() -> usize {
- Self::rows().min(Self::cols())
+ fn shortdim(&self) -> usize {
+ self.rows().min(self.cols())
}
- fn zeros() -> Self where Self: Sized, Self::ElemType: Zero {
- Self::all(Zero::zero())
+ fn zeros() -> Self where Self: Sized {
+ Self::all(Self::ElemType::zero())
}
- fn ones() -> Self where Self: Sized, Self::ElemType: One {
- Self::all(One::one())
+ fn ones() -> Self where Self: Sized {
+ Self::all(Self::ElemType::one())
}
fn get(&self, idx: (usize, usize)) -> Option<&Self::ElemType> {
- index_check(idx, Self::rows(), Self::cols())
+ index_check(idx, self.rows(), self.cols())
.ok()
.map(|_| unsafe { self.get_unchecked(idx) })
}
unsafe fn get_unchecked(&self, idx: (usize, usize)) -> &Self::ElemType {
- self.val().get_unchecked(idx.0 * Self::cols() + idx.1)
+ self.val().get_unchecked(idx.0 * self.cols() + idx.1)
}
fn get_mut(&mut self, idx: (usize, usize)) -> Option<&mut Self::ElemType> {
- index_check(idx, Self::rows(), Self::cols())
+ index_check(idx, self.rows(), self.cols())
.ok()?;
Some(unsafe { self.get_unchecked_mut(idx) })
}
unsafe fn get_unchecked_mut(&mut self, idx: (usize, usize)) -> &mut Self::ElemType {
- let cols = Self::cols();
+ let cols = self.cols();
self.val_mut().get_unchecked_mut(idx.0 * cols + idx.1)
}
- fn eye() -> Self where Self: Sized, Self::ElemType: One {
- let mut out = Self::default();
- (0..Self::shortdim()).for_each(|i| {
+ fn eye() -> Self where Self: Sized {
+ let mut out = Self::zeros();
+ (0..out.shortdim()).for_each(|i| {
unsafe { out.get_unchecked_mut((i, i)) }.set_one();
});
out
}
}
-

MODIFY
src/manual/core/vec.rs
src/manual/core/vec.rs
@@ -24,15 +24,15 @@ macro_rules! vec_impl {
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct $type<T: $type_trait>(pub [T; $count]);
- impl<T: $type_trait> From<[T; $count]> for $type<T> {
- fn from(s: [T; $count]) -> Self {
- Self(s)
+ impl<T: $type_trait> $type<T> {
+ pub fn all(v0: T) -> Self {
+ Self::from([v0; $count])
}
}
- impl<T: $type_trait> $type<T> {
- pub fn all(v0: T) -> Self {
- Self([v0; $count])
+ impl<T: $type_trait> From<[T; $count]> for $type<T> {
+ fn from(s: [T; $count]) -> Self {
+ Self(s)
}
}
@@ -61,7 +61,13 @@ vec_impl!(Scalar_, 4, ValidScalarType);
impl<T: ValidScalarType> Scalar_<T> {
pub fn new(v0: T, v1: T, v2: T, v3: T) -> Self {
- Self([v0, v1, v2, v3])
+ Self::from([v0, v1, v2, v3])
+ }
+}
+
+impl<T: ValidScalarType> From<T> for Scalar_<T> {
+ fn from(v0: T) -> Self {
+ Self::from([v0, T::zero(), T::zero(), T::zero()])
}
}

MODIFY
src_cpp/manual-core.cpp
src_cpp/manual-core.cpp
@@ -4,31 +4,33 @@ template struct Result<void*>;
template struct Result<cv::Size>;
template struct Result<const unsigned char*>;
-extern "C" {
- Result<void*> cv_InputArray_input_array(cv::_InputArray* instance) {
+template<typename T> inline Result<void*> ocvrs_input_array(const T* instance) {
try {
return Ok<void*>(new cv::_InputArray(*instance));
} OCVRS_CATCH(Result<void*>)
}
- Result<void*> cv_OutputArray_output_array(cv::_OutputArray* instance) {
+template<typename T> inline Result<void*> ocvrs_output_array(T* instance) {
try {
return Ok<void*>(new cv::_OutputArray(*instance));
} OCVRS_CATCH(Result<void*>)
}
- Result<void*> cv_InputOutputArray_input_output_array(cv::_InputOutputArray* instance) {
+template<typename T> inline Result<void*> ocvrs_input_output_array(T* instance) {
try {
return Ok<void*>(new cv::_InputOutputArray(*instance));
} OCVRS_CATCH(Result<void*>)
}
- Result<void*> cv_Scalar_input_array(cv::Scalar* instance) {
- try {
- return Ok<void*>(new cv::_InputArray(*instance));
- } OCVRS_CATCH(Result<void*>)
- }
+#define ocvrs_matx(base) \
+ Result<void*> cv_##base##f_input_array(const cv::base##f * instance) { return ocvrs_input_array(instance); } \
+ Result<void*> cv_##base##f_output_array(cv::base##f * instance) { return ocvrs_output_array(instance); } \
+ Result<void*> cv_##base##f_input_output_array(cv::base##f * instance) { return ocvrs_input_output_array(instance); } \
+ Result<void*> cv_##base##d_input_array(const cv::base##d * instance) { return ocvrs_input_array(instance); } \
+ Result<void*> cv_##base##d_output_array(cv::base##d * instance) { return ocvrs_output_array(instance); } \
+ Result<void*> cv_##base##d_input_output_array(cv::base##d * instance) { return ocvrs_input_output_array(instance); }
+extern "C" {
Result<cv::Size> cv_manual_Mat_size(const cv::Mat* instance) {
try {
return Ok<cv::Size>(instance->size());
@@ -82,4 +84,31 @@ extern "C" {
return instance->ptr;
}
+ Result<void*> cv_InputArray_input_array(cv::_InputArray* instance) { return ocvrs_input_array(instance); }
+ Result<void*> cv_OutputArray_output_array(cv::_OutputArray* instance) { return ocvrs_output_array(instance); }
+ Result<void*> cv_InputOutputArray_input_output_array(cv::_InputOutputArray* instance) { return ocvrs_input_output_array(instance); }
+
+ Result<void*> cv_Scalar_input_array(cv::Scalar* instance) { return ocvrs_input_array(instance); }
+
+ ocvrs_matx(Matx12)
+ ocvrs_matx(Matx13)
+ ocvrs_matx(Matx14)
+ ocvrs_matx(Matx16)
+
+ ocvrs_matx(Matx21)
+ ocvrs_matx(Matx31)
+ ocvrs_matx(Matx41)
+ ocvrs_matx(Matx61)
+
+ ocvrs_matx(Matx22)
+ ocvrs_matx(Matx23)
+ ocvrs_matx(Matx32)
+
+ ocvrs_matx(Matx33)
+
+ ocvrs_matx(Matx34)
+ ocvrs_matx(Matx43)
+
+ ocvrs_matx(Matx44)
+ ocvrs_matx(Matx66)
}

MODIFY
tests/mat.rs
tests/mat.rs
@@ -185,8 +185,7 @@ fn mat_at_1d() -> Result<()> {
#[test]
fn mat_2d_i0_is_rows_i1_is_cols() -> Result<()> {
// Just a sanity check about which Mat dimension corresponds to which in Size
- let mat =
- Mat::new_rows_cols_with_default(5, 6, f32::typ(), Scalar::all(1.23))?;
+ let mat = Mat::new_size_with_default(Size::new(6, 5), f32::typ(), Scalar::all(1.23))?;
let size = mat.size()?;
assert_eq!(size.width, 6);
assert_eq!(size.height, 5);

MODIFY
tests/matx.rs
tests/matx.rs
+use matches::assert_matches;
+
use opencv::{
- core::Matx33d,
+ core::{self, Matx23f, Matx32f, Matx33d, Matx44d, Point2f, Scalar},
+ imgproc,
prelude::*,
+ Result,
};
#[test]
-fn matx() {
+fn matx_get() {
let mut a = Matx33d::eye();
assert_eq!(a[(0, 0)], 1.);
assert_eq!(a[(1, 0)], 0.);
assert_eq!(*a.get((0, 1)).unwrap(), 0.);
assert_eq!(*a.get_mut((1, 1)).unwrap(), 1.);
+ assert_matches!(a.get((3, 1)), None);
+ assert_matches!(a.get_mut((1, 3)), None);
+ assert_matches!(a.get((3, 3)), None);
+}
+
+#[cfg(all(feature = "opencv-4", not(target_env = "msvc")))]
+#[test]
+fn matx_return() -> Result<()> {
+ let mat = imgproc::get_rotation_matrix_2d_matx(Point2f::new(10., 10.), 90., 2.)?;
+ assert_eq!(2, mat.rows());
+ assert_eq!(3, mat.cols());
+ assert_eq!(mat[(0, 0)], mat[(1, 1)]);
+ assert_eq!(-mat[(0, 1)], mat[(1, 0)]);
+ Ok(())
+}
+
+#[cfg(feature = "contrib")]
+#[test]
+fn matx_arg() -> Result<()> {
+ use opencv::surface_matching::Pose3D;
+
+ let mut pose = Pose3D::default()?;
+ assert!(&pose.pose().val.iter().all(|&x| x == 0.));
+ pose.set_pose(Matx44d::all(9.));
+ assert!(&pose.pose().val.iter().all(|&x| x == 9.));
+ Ok(())
+}
+
+#[test]
+fn matx_input_array() -> Result<()> {
+ assert_eq!(Scalar::from(2.), core::sum_elems(&Matx32f::eye())?);
+ assert_eq!(Scalar::from(2.), core::sum_elems(&Matx23f::eye())?);
+ Ok(())
+}
+
+#[test]
+fn matx_input_output_array() -> Result<()> {
+ let mut mat = Matx33d::from([
+ 1., 2., 3.,
+ 4., 5., 6.,
+ 9., 8., 9.,
+ ]);
+ core::complete_symm(&mut mat, false)?;
+ let expected = Matx33d::from([
+ 1., 2., 3.,
+ 2., 5., 6.,
+ 3., 6., 9.,
+ ]);
+ assert_eq!(expected, mat);
+ Ok(())
}

Improve Matx & friends