diff --git a/ext/opencv/dnn.cpp b/ext/opencv/dnn.cpp index 005a8f7..59ce63c 100644 --- a/ext/opencv/dnn.cpp +++ b/ext/opencv/dnn.cpp @@ -8,11 +8,26 @@ #include "dnn_layer.hpp" #include "error.hpp" +/* + * Document-class: Cv::Dnn + */ namespace rubyopencv { namespace Dnn { VALUE rb_module = Qnil; - // Mat blobFromImage(const Mat& image, double scalefactor=1.0, const Size& size = Size(), const Scalar& mean = Scalar(), bool swapRB=true) + /* + * Creates 4-dimensional blob from image. Optionally resizes and crops image from center, subtract mean values, scales values by scalefactor, swap Blue and Red channels. + * + * @overload blob_from_image(image, options = {}) + * @param image [Mat] Input image (with 1-, 3- or 4-channels) + * @param options [Hash] Options + * @option options [Number] :scale_factor (1.0) Multiplier for image values + * @option options [Mat] :size Spatial size for output image + * @option options [Scalar] :mean Scalar with mean values which are subtracted from channels – values are intended to be in (mean-R, mean-G, mean-B) order if image has BGR ordering and swap_rb is true + * @option options [Boolean] :swap_rb (true) Indicates that swap first and last channels in 3-channel image is necessary + * @option options [Boolean] :crop (true) Indicates whether image will be cropped after resize or not + * @return [Mat] 4-dimensional Mat with NCHW dimensions order + */ VALUE rb_blob_from_image(int argc, VALUE *argv, VALUE self) { VALUE image, options; rb_scan_args(argc, argv, "11", &image, &options); @@ -54,19 +69,20 @@ namespace rubyopencv { return Mat::mat2obj(b); } - void init(VALUE opencv) { + void init() { + VALUE opencv = rb_define_module("Cv"); 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", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net), -1); // in ext/opencv/dnn_net.cpp rb_define_singleton_method(rb_module, "read_net_from_caffe", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_caffe), 2); // in ext/opencv/dnn_net.cpp - rb_define_singleton_method(rb_module, "read_net_from_tensorflow", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_tensorflow), 1); // in ext/opencv/dnn_net.cpp - rb_define_singleton_method(rb_module, "read_net_from_torch", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_torch), 1); // in ext/opencv/dnn_net.cpp + rb_define_singleton_method(rb_module, "read_net_from_tensorflow", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_tensorflow), 2); // in ext/opencv/dnn_net.cpp + rb_define_singleton_method(rb_module, "read_net_from_torch", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_torch), -1); // in ext/opencv/dnn_net.cpp rb_define_singleton_method(rb_module, "read_net_from_darknet", RUBY_METHOD_FUNC(Dnn::Net::rb_read_net_from_darknet), 2); // in ext/opencv/dnn_net.cpp - Dnn::Net::init(rb_module); - Dnn::Layer::init(rb_module); + Dnn::Net::init(); + Dnn::Layer::init(); } } } diff --git a/ext/opencv/dnn.hpp b/ext/opencv/dnn.hpp index e971574..d01e476 100644 --- a/ext/opencv/dnn.hpp +++ b/ext/opencv/dnn.hpp @@ -6,7 +6,7 @@ */ namespace rubyopencv { namespace Dnn { - void init(VALUE opencv); + void init(); } } diff --git a/ext/opencv/dnn_layer.cpp b/ext/opencv/dnn_layer.cpp index 8a58b81..17ccc61 100644 --- a/ext/opencv/dnn_layer.cpp +++ b/ext/opencv/dnn_layer.cpp @@ -3,6 +3,9 @@ #include "opencv.hpp" #include "error.hpp" +/* + * Document-class: Cv::Dnn::Layer + */ namespace rubyopencv { namespace Dnn { namespace Layer { @@ -39,18 +42,31 @@ namespace rubyopencv { return self; } + /* + * Returns the layer name + * @overload name + * @return [String] Layer name + */ VALUE rb_name(VALUE self) { cv::dnn::Layer* selfptr = obj2layer(self); return rb_str_new_cstr(selfptr->name.c_str()); } + /* + * Returns the layer type + * + * @overload type + * @return [String] Layer type + */ VALUE rb_type(VALUE self) { cv::dnn::Layer* selfptr = obj2layer(self); return rb_str_new_cstr(selfptr->type.c_str()); } - void init(VALUE rb_module) { - rb_klass = rb_define_class_under(rb_module, "Layer", rb_cData); + void init() { + VALUE opencv = rb_define_module("Cv"); + VALUE dnn = rb_define_module_under(opencv, "Dnn"); + rb_klass = rb_define_class_under(dnn, "Layer", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 0); diff --git a/ext/opencv/dnn_layer.hpp b/ext/opencv/dnn_layer.hpp index e2b4295..952a1cf 100644 --- a/ext/opencv/dnn_layer.hpp +++ b/ext/opencv/dnn_layer.hpp @@ -7,7 +7,7 @@ namespace rubyopencv { namespace Dnn { namespace Layer { - void init(VALUE rb_module); + void init(); VALUE layer2obj(cv::dnn::Layer* ptr); } } diff --git a/ext/opencv/dnn_net.cpp b/ext/opencv/dnn_net.cpp index 4a9e43d..fefa2d8 100644 --- a/ext/opencv/dnn_net.cpp +++ b/ext/opencv/dnn_net.cpp @@ -5,6 +5,9 @@ #include "error.hpp" #include "dnn_layer.hpp" +/* + * Document-class: Cv::Dnn::Net + */ namespace rubyopencv { namespace Dnn { namespace Net { @@ -51,6 +54,19 @@ namespace rubyopencv { return dataptr; } + /* + * Creates or reads a deep learning network + * + * @overload new(model = nil, config = nil, framework = nil) + * @param model [String] Binary file contains trained weights + * @param config [String] Text file contains network configuration + * @param framework [String] Explicit framework name tag to determine a format + * @return [Net] Network object + * @opencv_func cv::dnn::Net + * @example + * net1 = Dnn::Net.new + * net2 = Dnn::Net.new("bvlc_googlenet.caffemodel", "bvlc_googlenet.prototxt") + */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { VALUE model, config, framework; rb_scan_args(argc, argv, "03", &model, &config, &framework); @@ -62,13 +78,16 @@ namespace rubyopencv { 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 = "") + /* + * Sets the new input value for the network + * + * @overload input=(blob) + * @param blob [Mat] A blob of CV_32F or CV_8U depth + * @overload input(blob, name = nil) + * @param blob [Mat] A blob of CV_32F or CV_8U depth + * @param name [String] Name of an input layer + * @return [void] + */ VALUE rb_set_input(int argc, VALUE *argv, VALUE self) { VALUE blob, name; rb_scan_args(argc, argv, "11", &blob, &name); @@ -84,7 +103,13 @@ namespace rubyopencv { return Qnil; } - // Mat forward(const String& outputName = String()) + /* + * Runs forward pass + * + * @overload forward(output_name = nil) + * @param output_name [String] Name of the layer for which output is needed + * @return [Mat] Blob for first output + */ VALUE rb_forward(int argc, VALUE *argv, VALUE self) { VALUE output_name; rb_scan_args(argc, argv, "01", &output_name); @@ -102,12 +127,23 @@ namespace rubyopencv { return Mat::rb_clone(Mat::mat2obj(m)); } - // bool empty() const + /* + * Returns whether or not the network is empty + * + * @overload empty? + * @return [Boolean] Whether or not the network is empty + */ VALUE rb_empty(VALUE self) { cv::dnn::Net* selfptr = obj2net(self); return selfptr->empty() ? Qtrue : Qfalse; } + /* + * Returns an array of layers loaded in this model + * + * @overload layers + * @return [Array] Loaded layers + */ VALUE rb_get_layers(VALUE self) { cv::dnn::Net* selfptr = obj2net(self); @@ -123,25 +159,68 @@ namespace rubyopencv { return layers; } + /* + * Enables or disables layer fusion in the network + * + * @overload fusion=(fusion) + * @param fusion [Boolean] Whether or not fusion should be enabled + * @return [Net] The current network + */ VALUE rb_enable_fusion(VALUE self, VALUE fusion) { cv::dnn::Net* selfptr = obj2net(self); selfptr->enableFusion(RTEST(fusion) ? true : false); return self; } + /* + * Ask network to use specific computation backend where it supported + * + * @overload preferable_backend=(backend_id) + * @param backend_id [Integer] The preferable backend identifier + * @return [Net] The current network + */ VALUE rb_set_preferable_backend(VALUE self, VALUE backend_id) { cv::dnn::Net* selfptr = obj2net(self); selfptr->setPreferableBackend(NUM2INT(backend_id)); return self; } + /* + * Ask network to make computations on specific target device + * + * @overload preferable_target=(target_id) + * @param target_id [Integer] The preferable target identifier + * @return [Net] The current network + */ VALUE rb_set_preferable_target(VALUE self, VALUE target_id) { cv::dnn::Net* selfptr = obj2net(self); selfptr->setPreferableTarget(NUM2INT(target_id)); return self; } - // Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String()); + /* + * Read deep learning network represented in one of the supported formats. + * + * @overload read_net(model = nil, config = nil, framework = nil) + * @param model [String] Binary file contains trained weights + * @param config [String] Text file contains network configuration + * @param framework [String] Explicit framework name tag to determine a format + * @return [Net] Network object + */ + 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)); + } + + /* + * Reads a network model stored in Caffe framework's format + * + * @overload read_net_from_caffe(prototxt, caffe_model) + * @param prototxt [String] Path to the .prototxt file with text description of the network architecture + * @param caffe_model [String] Path to the .caffemodel file with learned network + * @return [Net] Network object + */ VALUE rb_read_net_from_caffe(VALUE self, VALUE prototxt, VALUE caffe_model) { cv::dnn::Net *net = NULL; @@ -155,12 +234,19 @@ namespace rubyopencv { return net2obj(net); } - // Net readNetFromTorch(const String &model, bool isBinary) - VALUE rb_read_net_from_tensorflow(VALUE self, VALUE model) { + /* + * Reads a network model stored in TensorFlow framework's format + * + * @overload read_net_from_tensorflow(model, config) + * @param model [String] Path to the .pb file with binary protobuf description of the network architecture + * @param config [String] Path to the .pbtxt file that contains text graph definition in protobuf format + * @return [Net] Network object + */ + VALUE rb_read_net_from_tensorflow(VALUE self, VALUE model, VALUE config) { cv::dnn::Net *net = NULL; try { - net = new cv::dnn::Net(cv::dnn::readNetFromTensorflow(StringValueCStr(model))); + net = new cv::dnn::Net(cv::dnn::readNetFromTensorflow(StringValueCStr(model), StringValueCStr(config))); } catch(cv::Exception& e) { delete net; Error::raise(e); @@ -169,12 +255,21 @@ namespace rubyopencv { return net2obj(net); } - // Net readNetFromTorch(const String &model, bool isBinary) - VALUE rb_read_net_from_torch(VALUE self, VALUE model) { + /* + * Reads a network model stored in Torch7 framework's format + * + * @overload read_net_from_torch(model, binary = true) + * @param model [String] Path to the file, dumped from Torch by using torch.save() function + * @param binary [Boolean] Specifies whether the network was serialized in ascii mode or binary + * @return [Net] Network object + */ + VALUE rb_read_net_from_torch(int argc, VALUE *argv, VALUE self) { + VALUE model, binary; + rb_scan_args(argc, argv, "11", &model, &binary); cv::dnn::Net *net = NULL; try { - net = new cv::dnn::Net(cv::dnn::readNetFromTorch(StringValueCStr(model))); + net = new cv::dnn::Net(cv::dnn::readNetFromTorch(StringValueCStr(model), RTEST_DEFAULT(binary, true))); } catch(cv::Exception& e) { delete net; Error::raise(e); @@ -183,7 +278,14 @@ namespace rubyopencv { return net2obj(net); } - // Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/) + /* + * Reads a network model stored in Darknet model files + * + * @overload read_net_from_darknet(cfg_file, darknet_model) + * @param cfg_file [String] Path to the .cfg file with text description of the network architecture + * @param darknet_model [String] Path to the .weights file with learned network + * @return [Net] Network object + */ VALUE rb_read_net_from_darknet(VALUE self, VALUE cfg_file, VALUE darknet_model) { cv::dnn::Net *net = NULL; @@ -197,11 +299,13 @@ namespace rubyopencv { return net2obj(net); } - void init(VALUE rb_module) { - rb_klass = rb_define_class_under(rb_module, "Net", rb_cData); + void init() { + VALUE opencv = rb_define_module("Cv"); + VALUE dnn = rb_define_module_under(opencv, "Dnn"); + rb_klass = rb_define_class_under(dnn, "Net", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); rb_define_method(rb_klass, "input=", RUBY_METHOD_FUNC(rb_set_input), -1); rb_define_alias(rb_klass, "input", "input="); diff --git a/ext/opencv/dnn_net.hpp b/ext/opencv/dnn_net.hpp index f5e4d51..4c8e4bb 100644 --- a/ext/opencv/dnn_net.hpp +++ b/ext/opencv/dnn_net.hpp @@ -7,11 +7,11 @@ namespace rubyopencv { namespace Dnn { namespace Net { - void init(VALUE rb_module); + void init(); 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_tensorflow(VALUE self, VALUE model, VALUE config); 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/mat.cpp b/ext/opencv/mat.cpp index fdad6ce..0d58487 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -235,7 +235,7 @@ namespace rubyopencv { /* * Loads an image from a file. * - * @overload imread(filename, flags) + * @overload imread(filename, flags = IMREAD_UNCHANGED) * @param filename [String] Name of file to be loaded. * @param flags [Integer] Flags specifying the color type of a loaded image: * - CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index fb3e8a6..cf7e189 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(rb_module); + Dnn::init(); VideoCapture::init(); Window::init(); Trackbar::init();