add manual Mat
MODIFY
gen_rust.py
gen_rust.py
@@ -125,6 +125,11 @@ renamed_funcs = { # todo check if any "new" is required
"cv_Mat_ptr_const_int_row_int_col": "ptr_2d",
"cv_Mat_ptr_int_i0_int_i1_int_i2": "ptr_3d_mut",
"cv_Mat_ptr_const_int_i0_int_i1_int_i2": "ptr_3d",
+ "cv_Mat_at_int_i0": "at_mut",
+ "cv_Mat_at_int_row_int_col": "at_2d_mut",
+ "cv_Mat_at_const_int_row_int_col": "at_2d",
+ "cv_Mat_at_int_i0_int_i1_int_i2": "at_3d_mut",
+ "cv_Mat_at_const_int_i0_int_i1_int_i2": "at_3d",
"cv_Mat_resize_size_t_sz": "resize",
"cv_Mat_resize_size_t_sz_Scalar_s": "resize_with_default",
"cv_Mat_rowRange_const_Range_r": "row_range",
@@ -296,7 +301,37 @@ renamed_funcs = { # todo check if any "new" is required
"cv_dnn_Dict_ptr_const_String_key": "ptr",
}
-func_manual_implementation = {}
+_templ_const = template("""
+// identifier: ${identifier}
+${doc_comment}${visibility}fn ${r_name}<T: core::ValidMatElement>(${args}) -> Result<&T> { ${pre_call_args}self._${r_name}(${forward_args}) }
+
+""")
+_templ_mut = template("""
+// identifier: ${identifier}
+${doc_comment}${visibility}fn ${r_name}<T: core::ValidMatElement>(${args}) -> Result<&mut T> { ${pre_call_args}self._${r_name}(${forward_args}) }
+
+""")
+
+func_manual_implementation = {
+ "cv_Mat_at_int_i0": {
+ "rust_safe": _templ_mut,
+ },
+ "cv_Mat_at_const_int_i0": {
+ "rust_safe": _templ_const,
+ },
+ "cv_Mat_at_int_i0_int_i1_int_i2": {
+ "rust_safe": _templ_mut,
+ },
+ "cv_Mat_at_const_int_i0_int_i1_int_i2": {
+ "rust_safe": _templ_const,
+ },
+ "cv_Mat_at_int_row_int_col": {
+ "rust_safe": _templ_mut,
+ },
+ "cv_Mat_at_const_int_row_int_col": {
+ "rust_safe": _templ_const,
+ },
+}
class_ignore_list = (
# core

MODIFY
src/hub/manual/core.rs
src/hub/manual/core.rs
+pub use self::mat::*;
+
macro_rules! valid_types {
($trait: ident, $($rust_type: ty),+) => {
// todo, make sealed
@@ -8,3 +10,5 @@ macro_rules! valid_types {
)+
};
}
+
+mod mat;

ADD
src/hub/manual/core/mat.rs
+use std::{fmt, slice};
+use std::intrinsics::transmute;
+
+use crate::{
+ Error,
+ hub::core::{self, Mat},
+ Result,
+ sys,
+};
+
+// todo, make sealed
+pub trait ValidMatElement {
+ fn typ() -> i32;
+}
+
+macro_rules! valid_mat_element {
+ ($rust_type: ty, $mat_type: expr) => {
+ impl ValidMatElement for $rust_type {
+ fn typ() -> i32 { $mat_type }
+ }
+ };
+}
+
+// int
+valid_mat_element!(u8, core::CV_8U);
+valid_mat_element!(i8, core::CV_8S);
+valid_mat_element!(u16, core::CV_16U);
+valid_mat_element!(i16, core::CV_16S);
+valid_mat_element!(i32, core::CV_32S);
+
+// float
+valid_mat_element!(f32, core::CV_32F);
+valid_mat_element!(f64, core::CV_64F);
+
+// vec int
+valid_mat_element!(core::Vec2b, core::CV_8UC2);
+valid_mat_element!(core::Vec3b, core::CV_8UC3);
+valid_mat_element!(core::Vec4b, core::CV_8UC4);
+valid_mat_element!(core::Vec2s, core::CV_16SC2);
+valid_mat_element!(core::Vec3s, core::CV_16SC3);
+valid_mat_element!(core::Vec4s, core::CV_16SC4);
+valid_mat_element!(core::Vec2i, core::CV_32SC2);
+valid_mat_element!(core::Vec3i, core::CV_32SC3);
+valid_mat_element!(core::Vec4i, core::CV_32SC4);
+
+// vec float
+valid_mat_element!(core::Vec2f, core::CV_32FC2);
+valid_mat_element!(core::Vec3f, core::CV_32FC3);
+valid_mat_element!(core::Vec4f, core::CV_32FC4);
+valid_mat_element!(core::Vec2d, core::CV_64FC2);
+valid_mat_element!(core::Vec3d, core::CV_64FC3);
+valid_mat_element!(core::Vec4d, core::CV_64FC4);
+
+// scalar
+valid_mat_element!(core::Scalar, core::CV_64FC4);
+
+
+//struct Mat_<T> {
+// mat: Mat,
+// _d: PhantomData<T>,
+//}
+
+//impl<T: MatElement> Mat_<T> {
+// pub fn try_from_mat(mat: Mat) -> Result<Self> {
+// if mat.typ()? == T::typ() {
+// Ok(Self { mat, _d: PhantomData })
+// } else {
+// Err(Error { code: -1, message: "".into() }) // fixme
+// }
+// }
+//}
+
+impl Mat {
+ #[inline(always)]
+ fn match_format<T: ValidMatElement>(&self) -> Result<()> {
+ let mat_type = self.typ()?;
+ let out_type = T::typ();
+ if mat_type == out_type {
+ Ok(())
+ } else {
+ Err(Error::new(core::StsUnmatchedFormats, format!("Mat type is: {}, but requested type is: {}", mat_type, out_type)))
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at<T: ValidMatElement>(&self, i0: i32) -> Result<&T> {
+ self.match_format::<T>().and_then(|_| self.ptr(i0).map(|x| unsafe { &*(x as *const _ as *const T) }))
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at_mut<T: ValidMatElement>(&mut self, i0: i32) -> Result<&mut T> {
+ self.match_format::<T>().and_then(|_| self.ptr_mut(i0).map(|x| unsafe { &mut *(x as *mut _ as *mut T) }))
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at_2d<T: ValidMatElement>(&self, row: i32, col: i32) -> Result<&T> {
+ self.match_format::<T>().and_then(|_| self.ptr_2d(row, col).map(|x| unsafe { &*(x as *const _ as *const T) }))
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at_2d_mut<T: ValidMatElement>(&mut self, row: i32, col: i32) -> Result<&mut T> {
+ self.match_format::<T>().and_then(|_| self.ptr_2d_mut(row, col).map(|x| unsafe { &mut *(x as *mut _ as *mut T) }))
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at_3d<T: ValidMatElement>(&self, i0: i32, i1: i32, i2: i32) -> Result<&T> {
+ self.match_format::<T>().and_then(|_| self.ptr_3d(i0, i1, i2).map(|x| unsafe { &*(x as *const _ as *const T) }))
+ }
+
+ #[inline(always)]
+ pub(crate) fn _at_3d_mut<T: ValidMatElement>(&mut self, i0: i32, i1: i32, i2: i32) -> Result<&mut T> {
+ self.match_format::<T>().and_then(|_| self.ptr_3d_mut(i0, i1, i2).map(|x| unsafe { &mut *(x as *mut _ as *mut T) }))
+ }
+
+ pub fn at_row<T: ValidMatElement>(&self, i0: i32) -> Result<&[T]> {
+ let width = self.size()?.width as usize;
+ self._at(i0).map(|x| unsafe { slice::from_raw_parts(x, width) })
+ }
+
+ pub fn at_row_mut<T: ValidMatElement>(&mut self, i0: i32) -> Result<&mut [T]> {
+ let width = self.size()?.width as usize;
+ self._at_mut(i0).map(|x| unsafe { slice::from_raw_parts_mut(x, width) })
+ }
+
+ pub fn data<T: ValidMatElement>(&self) -> Result<&[T]> {
+ let total = self.total()?;
+ self._at(0).map(|x| unsafe { slice::from_raw_parts(x, total) })
+ }
+
+ pub fn data_mut<T: ValidMatElement>(&mut self) -> Result<&mut [T]> {
+ let total = self.total()?;
+ self._at_mut(0).map(|x| unsafe { slice::from_raw_parts_mut(x, total) })
+ }
+
+ #[inline]
+ pub fn from_slice<T: ValidMatElement + Copy>(s: &[T]) -> Result<Mat> {
+ Self::from_slice_2d(&[s])
+ }
+
+ pub fn from_slice_2d<T: ValidMatElement + Copy>(s: &[impl AsRef<[T]>]) -> Result<Mat> {
+ let row_count: i32 = s.len() as _;
+ let col_count: i32 = if row_count > 0 {
+ s[0].as_ref().len() as _
+ } else {
+ 0
+ };
+ let mut out = Mat::new_rows_cols(row_count, col_count, T::typ())?;
+ for (row_n, row) in s.into_iter().enumerate() {
+ let trg = out.at_row_mut(row_n as _)?;
+ let src = row.as_ref();
+ if trg.len() != src.len() {
+ return Err(Error::new(core::StsBadArg, format!("Unexpected number of items: {} in a row index: {}, expected: {}", trg.len(), row_n, src.len())));
+ }
+ trg.copy_from_slice(src);
+ }
+ Ok(out)
+ }
+
+ pub fn to_vec_2d<T: ValidMatElement + Copy>(&self) -> Result<Vec<Vec<T>>> {
+ self.match_format::<T>().and_then(|_| {
+ let size = self.size()?;
+ let width = size.width as usize;
+ let data = self.data()?;
+ Ok((0..size.height)
+ .map(|row_n| {
+ let row_n = row_n as usize;
+ let mut row = Vec::with_capacity(width);
+ unsafe { row.set_len(width); }
+ row[0..width].copy_from_slice(&data[row_n * width..(row_n + 1) * width]);
+ row
+ })
+ .collect()
+ )
+ })
+ }
+}
+
+impl fmt::Debug for Mat {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Mat")
+ .field("channels", &self.channels().unwrap())
+ .field("depth", &self.depth().unwrap())
+ .field("elem_size", &self.elem_size().unwrap())
+ .field("elem_size1", &self.elem_size1().unwrap())
+ .field("is_continuous", &self.is_continuous().unwrap())
+ .field("is_submatrix", &self.is_submatrix().unwrap())
+ .field("total", &self.total().unwrap())
+ .field("type", &self.typ().unwrap())
+ .field("size", &self.size().unwrap())
+ .finish()
+ }
+}
+
+
+mod private {
+ pub trait Sealed {}
+}

MODIFY
tests/mat.rs
tests/mat.rs
-extern crate opencv;
use opencv::core;
#[test]
@@ -16,3 +15,45 @@ fn mat_for_rows_and_cols() {
assert_eq!(core::CV_8U, mat.depth().unwrap());
assert_eq!(3, mat.channels().unwrap());
}
+
+#[test]
+fn mat_at() {
+ let mut mat = core::Mat::new_rows_cols(100, 100, core::CV_32F).unwrap();
+ assert_eq!(*mat.at_2d::<f32>(0, 0).unwrap(), 0.);
+ *mat.at_2d_mut::<f32>(0, 0).unwrap() = 1.;
+ assert_eq!(*mat.at_2d::<f32>(0, 0).unwrap(), 1.);
+
+ if let Ok(..) = mat.at::<i32>(0) {
+ assert!(false, "different types");
+ }
+
+ let row = mat.at_row::<f32>(0).unwrap();
+ assert_eq!(row.len(), 100);
+ assert_eq!(row[0], 1.);
+
+ let row = mat.at_row_mut::<f32>(1).unwrap();
+ row[0..4].copy_from_slice(&[10., 20., 30., 40.]);
+
+ let data = mat.data::<f32>().unwrap();
+ assert_eq!(data[0], 1.);
+ assert_eq!(data[100], 10.);
+ assert_eq!(data[103], 40.);
+
+ // todo unallocated Mat, zero sized Mat
+}
+
+#[test]
+fn mat_vec() {
+ let s = vec![
+ vec![1.0f32, 2., 3.],
+ vec![4., 5., 6.],
+ vec![7., 8., 9.],
+ ];
+
+ let mat = core::Mat::from_slice_2d(&s).unwrap();
+ assert_eq!(mat.size().unwrap(), core::Size { width: 3, height: 3 });
+ assert_eq!(*mat.at_2d::<f32>(1, 1).unwrap(), 5.);
+
+ let v = mat.to_vec_2d::<f32>().unwrap();
+ assert_eq!(s, v);
+}

add manual Mat