diff --git a/ext/opencv/dnn.cpp b/ext/opencv/dnn.cpp index c31a163..d5fb939 100644 --- a/ext/opencv/dnn.cpp +++ b/ext/opencv/dnn.cpp @@ -8,9 +8,6 @@ #include "dnn_layer.hpp" #include "error.hpp" -// https://docs.opencv.org/trunk/d6/d0f/group__dnn.html#ga29d0ea5e52b1d1a6c2681e3f7d68473a -// https://github.com/opencv/opencv/blob/master/modules/dnn/src/caffe/caffe_importer.cpp - namespace rubyopencv { namespace Dnn { VALUE rb_module = Qnil; @@ -21,23 +18,22 @@ namespace rubyopencv { rb_scan_args(argc, argv, "11", &image, &options); cv::Mat *b = NULL; - cv::Mat *m = Mat::obj2mat(image); try { - cv::Mat r; + double scale_factor = 1.0; + cv::Size size; + cv::Scalar mean; + bool swap_rb = true; + bool crop = true; - if (NIL_P(options)) { - r = cv::dnn::blobFromImage(*m); - } else { + if (!NIL_P(options)) { Check_Type(options, T_HASH); - double scale_factor = NUM2DBL_DEFAULT(HASH_LOOKUP(options, "scale_factor"), 1.0); - cv::Size size; - cv::Scalar mean; - bool swap_rb = RTEST_DEFAULT(HASH_LOOKUP(options, "swap_rb"), true); - bool crop = RTEST_DEFAULT(HASH_LOOKUP(options, "crop"), true); - VALUE tmp = Qnil; + scale_factor = NUM2DBL_DEFAULT(HASH_LOOKUP(options, "scale_factor"), scale_factor); + swap_rb = RTEST_DEFAULT(HASH_LOOKUP(options, "swap_rb"), (bool)swap_rb); + crop = RTEST_DEFAULT(HASH_LOOKUP(options, "crop"), (bool)crop); + VALUE tmp = Qnil; tmp = HASH_LOOKUP(options, "size"); if (!NIL_P(tmp)) { size = *(Size::obj2size(tmp)); @@ -47,11 +43,9 @@ namespace rubyopencv { if (!NIL_P(tmp)) { mean = *(Scalar::obj2scalar(tmp)); } - - r = cv::dnn::blobFromImage(*m, scale_factor, size, mean, swap_rb, crop); } - b = new cv::Mat(r); + b = new cv::Mat(cv::dnn::blobFromImage(*Mat::obj2mat(image), scale_factor, size, mean, swap_rb, crop)); } catch(cv::Exception& e) { delete b; Error::raise(e); @@ -60,72 +54,16 @@ namespace rubyopencv { return Mat::mat2obj(b); } - // // Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String()); - // VALUE rb_read_net_from_caffe(VALUE self, VALUE prototxt, VALUE caffe_model) { - // cv::dnn::Net *net = NULL; - // - // try { - // net = new cv::dnn::Net(cv::dnn::readNetFromCaffe(StringValueCStr(prototxt), StringValueCStr(caffe_model))); - // } catch(cv::Exception& e) { - // delete net; - // Error::raise(e); - // } - // - // return Dnn::Net::net2obj(net); - // } - // - // // Net readNetFromTorch(const String &model, bool isBinary) - // VALUE rb_read_net_from_tensorflow(VALUE self, VALUE model) { - // cv::dnn::Net *net = NULL; - // - // try { - // net = new cv::dnn::Net(cv::dnn::readNetFromTensorflow(StringValueCStr(model))); - // } catch(cv::Exception& e) { - // delete net; - // Error::raise(e); - // } - // - // return Dnn::Net::net2obj(net); - // } - // - // // Net readNetFromTorch(const String &model, bool isBinary) - // VALUE rb_read_net_from_torch(VALUE self, VALUE model) { - // cv::dnn::Net *net = NULL; - // - // try { - // net = new cv::dnn::Net(cv::dnn::readNetFromTorch(StringValueCStr(model))); - // } catch(cv::Exception& e) { - // delete net; - // Error::raise(e); - // } - // - // return Dnn::Net::net2obj(net); - // } - // - // // Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/) - // VALUE rb_read_net_from_darknet(VALUE self, VALUE cfg_file, VALUE darknet_model) { - // cv::dnn::Net *net = NULL; - // - // try { - // net = new cv::dnn::Net(cv::dnn::readNetFromDarknet(StringValueCStr(cfg_file), StringValueCStr(darknet_model))); - // } catch(cv::Exception& e) { - // delete net; - // Error::raise(e); - // } - // - // return Dnn::Net::net2obj(net); - // } - - void init() { - VALUE opencv = rb_define_module("Cv"); - + void init(VALUE opencv) { rb_module = rb_define_module_under(opencv, "Dnn"); rb_define_singleton_method(rb_module, "blob_from_image", RUBY_METHOD_FUNC(rb_blob_from_image), -1); - // rb_define_singleton_method(rb_module, "read_net_from_caffe", RUBY_METHOD_FUNC(rb_read_net_from_caffe), 2); - // rb_define_singleton_method(rb_module, "read_net_from_tensorflow", RUBY_METHOD_FUNC(rb_read_net_from_tensorflow), 1); - // rb_define_singleton_method(rb_module, "read_net_from_torch", RUBY_METHOD_FUNC(rb_read_net_from_torch), 1); - // rb_define_singleton_method(rb_module, "read_net_from_darknet", RUBY_METHOD_FUNC(rb_read_net_from_darknet), 2); + + rb_define_singleton_method(rb_module, "read_net", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net), -1); + rb_define_singleton_method(rb_module, "read_net_from_caffe", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_caffe), 2); + rb_define_singleton_method(rb_module, "read_net_from_tensorflow", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_tensorflow), 1); + rb_define_singleton_method(rb_module, "read_net_from_torch", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_torch), 1); + rb_define_singleton_method(rb_module, "read_net_from_darknet", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_darknet), 2); Dnn::Net::init(rb_module); Dnn::Layer::init(rb_module); diff --git a/ext/opencv/dnn.hpp b/ext/opencv/dnn.hpp index d01e476..e971574 100644 --- a/ext/opencv/dnn.hpp +++ b/ext/opencv/dnn.hpp @@ -6,7 +6,7 @@ */ namespace rubyopencv { namespace Dnn { - void init(); + void init(VALUE opencv); } } diff --git a/ext/opencv/dnn_net.cpp b/ext/opencv/dnn_net.cpp index 47bb9ae..850784f 100644 --- a/ext/opencv/dnn_net.cpp +++ b/ext/opencv/dnn_net.cpp @@ -37,41 +37,48 @@ namespace rubyopencv { return TypedData_Wrap_Struct(klass, &opencv_net_type, ptr); } + cv::dnn::Net* rb_read_net_internal(VALUE model, VALUE config, VALUE framework) { + cv::dnn::Net* dataptr = NULL; + + try { + cv::dnn::Net net = cv::dnn::readNet(StringValueCStr(model), CSTR_DEFAULT(config, ""), CSTR_DEFAULT(framework, "")); + dataptr = new cv::dnn::Net(net); + } catch(cv::Exception& e) { + delete dataptr; + Error::raise(e); + } + + return dataptr; + } + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { VALUE model, config, framework; rb_scan_args(argc, argv, "03", &model, &config, &framework); - if (!NIL_P(model)) { - cv::dnn::Net* dataptr = NULL; - - try { - cv::dnn::Net net = cv::dnn::readNet(StringValueCStr(model), CSTR_DEFAULT(config, ""), CSTR_DEFAULT(framework, "")); - cv::dnn::Net* dataptr = new cv::dnn::Net(net); - RTYPEDDATA_DATA(self) = dataptr; - } catch(cv::Exception& e) { - delete dataptr; - Error::raise(e); - } + if (argc > 0) { + RTYPEDDATA_DATA(self) = rb_read_net_internal(model, config, framework); } return self; } + VALUE rb_read_net(int argc, VALUE *argv, VALUE self) { + VALUE model, config, framework; + rb_scan_args(argc, argv, "12", &model, &config, &framework); + return net2obj(rb_read_net_internal(model, config, framework)); + } + // void setInput(const Mat &blob, const String& name = "") VALUE rb_set_input(int argc, VALUE *argv, VALUE self) { - VALUE blob, name; - rb_scan_args(argc, argv, "11", &blob, &name); + VALUE blob, name, options; + rb_scan_args(argc, argv, "12", &blob, &name, &options); cv::dnn::Net* selfptr = obj2net(self); cv::Mat *m = Mat::obj2mat(blob); try { - if (NIL_P(name)) { - selfptr->setInput(*m); - } else { - selfptr->setInput(*m, StringValueCStr(name)); - } + selfptr->setInput(*m, CSTR_DEFAULT(name, "")); } catch(cv::Exception& e) { delete m; Error::raise(e); @@ -107,12 +114,12 @@ namespace rubyopencv { VALUE rb_get_layers(VALUE self) { cv::dnn::Net* selfptr = obj2net(self); - std::vector v = selfptr->getLayerNames(); - const long size = v.size(); + std::vector layer_names = selfptr->getLayerNames(); + const long size = layer_names.size(); VALUE layers = rb_ary_new_capa(size); for (long i = 0; i < size; i++) { - VALUE layer = Dnn::Layer::layer2obj(selfptr->getLayer(v[i])); + VALUE layer = Dnn::Layer::layer2obj(selfptr->getLayer(layer_names[i])); rb_ary_store(layers, i, layer); } @@ -137,6 +144,62 @@ namespace rubyopencv { return self; } + // Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String()); + VALUE rb_read_net_from_caffe(VALUE self, VALUE prototxt, VALUE caffe_model) { + cv::dnn::Net *net = NULL; + + try { + net = new cv::dnn::Net(cv::dnn::readNetFromCaffe(StringValueCStr(prototxt), StringValueCStr(caffe_model))); + } catch(cv::Exception& e) { + delete net; + Error::raise(e); + } + + return net2obj(net); + } + + // Net readNetFromTorch(const String &model, bool isBinary) + VALUE rb_read_net_from_tensorflow(VALUE self, VALUE model) { + cv::dnn::Net *net = NULL; + + try { + net = new cv::dnn::Net(cv::dnn::readNetFromTensorflow(StringValueCStr(model))); + } catch(cv::Exception& e) { + delete net; + Error::raise(e); + } + + return net2obj(net); + } + + // Net readNetFromTorch(const String &model, bool isBinary) + VALUE rb_read_net_from_torch(VALUE self, VALUE model) { + cv::dnn::Net *net = NULL; + + try { + net = new cv::dnn::Net(cv::dnn::readNetFromTorch(StringValueCStr(model))); + } catch(cv::Exception& e) { + delete net; + Error::raise(e); + } + + return net2obj(net); + } + + // Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/) + VALUE rb_read_net_from_darknet(VALUE self, VALUE cfg_file, VALUE darknet_model) { + cv::dnn::Net *net = NULL; + + try { + net = new cv::dnn::Net(cv::dnn::readNetFromDarknet(StringValueCStr(cfg_file), StringValueCStr(darknet_model))); + } catch(cv::Exception& e) { + delete net; + Error::raise(e); + } + + return net2obj(net); + } + void init(VALUE rb_module) { rb_klass = rb_define_class_under(rb_module, "Net", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/dnn_net.hpp b/ext/opencv/dnn_net.hpp index f91068c..f5e4d51 100644 --- a/ext/opencv/dnn_net.hpp +++ b/ext/opencv/dnn_net.hpp @@ -9,6 +9,11 @@ namespace rubyopencv { namespace Net { void init(VALUE rb_module); VALUE net2obj(cv::dnn::Net* ptr); + VALUE rb_read_net(int argc, VALUE *argv, VALUE self); + VALUE rb_read_net_from_caffe(VALUE self, VALUE prototxt, VALUE caffe_model); + VALUE rb_read_net_from_tensorflow(VALUE self, VALUE model); + VALUE rb_read_net_from_torch(VALUE self, VALUE model); + VALUE rb_read_net_from_darknet(VALUE self, VALUE cfg_file, VALUE darknet_model); } } } diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index cf7e189..fb3e8a6 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -93,7 +93,7 @@ namespace rubyopencv { Size::init(); Scalar::init(); CascadeClassifier::init(); - Dnn::init(); + Dnn::init(rb_module); VideoCapture::init(); Window::init(); Trackbar::init();