add more methods for DictValue, add Dict::set()
MODIFY
build.rs
build.rs
@@ -391,7 +391,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut config = cpp_build::Config::new();
config.flag_if_supported("-Wno-class-memaccess");
- config.flag_if_supported("-Wignored-qualifiers");
+ config.flag_if_supported("-Wno-ignored-qualifiers");
config.include(opencv_header_dir);
config.build("src/lib.rs");
Ok(())

MODIFY
gen_rust.py
gen_rust.py
@@ -13,7 +13,7 @@ from string import Template
# fixme returning MatAllocator (trait) by reference is bad, check knearestneighbour
# fixme field comments //! in the end are transferred to the next field
-# fixme dnn::net::Dict needs set method (generic or only DictValue?), DictValue needs constructors
+# fixme add support for arrays in dnn::DictValue
# fixme VectorOfMat::get allows to mutate?
def template(text):
@@ -379,6 +379,13 @@ func_rename = {
"cv_dnn_readNetFromDarknet_const_char_X_size_t_const_char_X_size_t": "read_net_from_darknet_str",
"cv_dnn_Net_getMemoryConsumption_const_int_VectorOfVectorOfint_size_t_size_t": "get_memory_consumption_for_layer",
"cv_dnn_Net_getMemoryConsumption_const_VectorOfVectorOfint_VectorOfint_VectorOfsize_t_VectorOfsize_t": "get_memory_consumption_for_layers",
+ "cv_dnn_DictValue_DictValue_bool": "from_bool",
+ "cv_dnn_DictValue_DictValue_int64": "from_i64",
+ "cv_dnn_DictValue_DictValue_int": "from_i32",
+ "cv_dnn_DictValue_DictValue_unsigned": "from_u32",
+ "cv_dnn_DictValue_DictValue_double": "from_f64",
+ "cv_dnn_DictValue_DictValue_const_char_X": "from_str",
+ "cv_dnn_DictValue_DictValue_String": "-", # effectively duplicate of cv_dnn_DictValue_DictValue_const_char_X
}
# list of classes to skip, elements are regular expressions for re.match() against ClassInfo.fullname
@@ -729,6 +736,11 @@ def decl_patch(module, decl):
idx_arg = decl[3][0]
if idx_arg[0] == "const int*" and idx_arg[1] == "idx":
decl[3][0][0] = "const int[]"
+ elif module == "dnn":
+ # set method takes generic, force it to take DictValue wrapper
+ if decl[0] == "cv.dnn.Dict.set":
+ decl[1] = "DictValue&"
+ decl[3][1][0] = "DictValue&"
elif module == "ml":
# loadFromCSV is not parsed correctly due to default value being a comma
if decl[0] == "cv.ml.TrainData.loadFromCSV" and len(decl[3]) == 8 and decl[3][6][0] == "'":

ADD
src/manual/dnn.rs
+use std::fmt;
+
+use crate::{
+ dnn::DictValue,
+ Result,
+ sys,
+};
+
+impl DictValue {
+ #[inline]
+ pub fn get_f64(&self, idx: i32) -> Result<f64> {
+ let me = self.as_raw_DictValue();
+ cpp!(unsafe [me as "const dnn::DictValue*", idx as "int"] -> sys::cv_return_value_double as "cv_return_value_double" {
+ try {
+ return { Error::Code::StsOk, NULL, me->get<double>(idx) };
+ } CVRS_CATCH(cv_return_value_double)
+ }).into_result()
+ }
+
+ #[inline]
+ pub fn get_i64(&self, idx: i32) -> Result<i64> {
+ let me = self.as_raw_DictValue();
+ cpp!(unsafe [me as "const dnn::DictValue*", idx as "int"] -> sys::cv_return_value_int64 as "cv_return_value_int64" {
+ try {
+ return { Error::Code::StsOk, NULL, me->get<int64>(idx) };
+ } CVRS_CATCH(cv_return_value_int64)
+ }).into_result()
+ }
+
+ #[inline]
+ pub fn get_string(&self, idx: i32) -> Result<String> {
+ let me = self.as_raw_DictValue();
+ cpp!(unsafe [me as "const dnn::DictValue*", idx as "int"] -> sys::cv_return_value_char_X as "cv_return_value_char_X" {
+ try {
+ return { Error::Code::StsOk, NULL, strdup(me->get<String>(idx).c_str()) };
+ } CVRS_CATCH(cv_return_value_char_X)
+ }).into_result().map(crate::templ::receive_string_mut)
+ }
+}
+
+impl fmt::Debug for DictValue {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut d = f.debug_struct("DictValue");
+ d.field("is_int", &self.is_int().map_err(|_| fmt::Error)?)
+ .field("is_real", &self.is_real().map_err(|_| fmt::Error)?)
+ .field("is_string", &self.is_string().map_err(|_| fmt::Error)?);
+ if self.is_string().map_err(|_| fmt::Error)? {
+ d.field("value", &self.get_string(-1).map_err(|_| fmt::Error)?);
+ } else if self.is_int().map_err(|_| fmt::Error)? {
+ d.field("value", &self.get_i64(-1).map_err(|_| fmt::Error)?);
+ } else if self.is_real().map_err(|_| fmt::Error)? {
+ d.field("value", &self.get_f64(-1).map_err(|_| fmt::Error)?);
+ }
+ d.finish()
+ }
+}

MODIFY
src/manual/mod.rs
src/manual/mod.rs
pub mod core;
+pub mod dnn;
pub mod sys;
pub mod types;

MODIFY
tests/dnn.rs
tests/dnn.rs
+use matches::assert_matches;
+
use opencv::{
+ core,
+ dnn::{Dict, DictValue, LayerParams, Net},
+ Error,
prelude::*,
- dnn::{Dict, LayerParams, Net},
Result,
types::VectorOfMat,
};
@@ -21,6 +25,10 @@ fn net() -> Result<()> {
assert_eq!(params.name()?, "param name");
assert_eq!(params._type()?, "param type");
assert!(!params.has("test")?);
+ params.set("test", &mut DictValue::from_f64(345.9)?)?;
+ assert!(params.has("test")?);
+ let v = params.get("test")?;
+ assert_eq!(345.9, v.get_real_value(-1)?);
let blobs = params.blobs()?;
assert_eq!(1, blobs.len());
let res = net.add_layer("layer", "type", &mut params)?;
@@ -28,3 +36,39 @@ fn net() -> Result<()> {
assert!(!net.empty()?);
Ok(())
}
+
+#[test]
+fn dict() -> Result<()> {
+ {
+ let v = DictValue::from_f64(123.456)?;
+ assert!(v.is_real()?);
+ assert!(!v.is_int()?);
+ assert!(!v.is_string()?);
+ assert_eq!(1, v.size()?);
+ assert_eq!(123.456, v.get_real_value(-1)?);
+ assert_matches!(v.get_int_value(-1), Err(Error{code: core::StsAssert, ..}));
+ }
+
+ {
+ let v = DictValue::from_i64(123)?;
+ assert!(v.is_int()?);
+ assert!(v.is_real()?);
+ assert!(!v.is_string()?);
+ assert_eq!(1, v.size()?);
+ assert_eq!(123, v.get_int_value(-1)?);
+ assert_eq!(123., v.get_real_value(-1)?);
+ assert_matches!(v.get_string_value(-1), Err(Error{code: core::StsAssert, ..}));
+ }
+
+ {
+ let v = DictValue::from_str("876543.123")?;
+ assert!(!v.is_int()?);
+ assert!(!v.is_real()?);
+ assert!(v.is_string()?);
+ assert_eq!(1, v.size()?);
+ assert_eq!(1, v.get_int_value(-1)?);
+ assert_eq!(1., v.get_real_value(-1)?);
+ assert_matches!(v.get_string_value(-1), Err(Error{code: core::StsAssert, ..}));
+ }
+ Ok(())
+}

add more methods for DictValue, add Dict::set()