1
0
Fork 0
mirror of https://github.com/ruby-opencv/ruby-opencv synced 2023-03-27 23:22:12 -04:00

Added Dnn::Layer, more Ruby-ish code, etc.

This commit is contained in:
Francois Deschenes 2018-07-26 15:28:00 -07:00
parent 46c5a08025
commit 801d1e8694
9 changed files with 218 additions and 90 deletions

View file

@ -5,6 +5,7 @@
#include "size.hpp"
#include "scalar.hpp"
#include "dnn_net.hpp"
#include "dnn_layer.hpp"
#include "error.hpp"
// https://docs.opencv.org/trunk/d6/d0f/group__dnn.html#ga29d0ea5e52b1d1a6c2681e3f7d68473a
@ -59,61 +60,61 @@ 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);
}
// // 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");
@ -121,12 +122,13 @@ namespace rubyopencv {
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_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);
Dnn::Net::init(rb_module);
Dnn::Layer::init(rb_module);
}
}
}

63
ext/opencv/dnn_layer.cpp Normal file
View file

@ -0,0 +1,63 @@
#include "opencv2/dnn.hpp"
#include "opencv.hpp"
#include "error.hpp"
namespace rubyopencv {
namespace Dnn {
namespace Layer {
VALUE rb_klass = Qnil;
void free_layer(void* ptr) {
delete (cv::dnn::Layer*)ptr;
}
size_t memsize_layer(const void* ptr) {
return sizeof(cv::dnn::Layer);
}
rb_data_type_t opencv_layer_type = {
"Dnn::Layer", { 0, free_layer, memsize_layer, }, 0, 0, 0
};
VALUE layer2obj(cv::dnn::Layer* ptr) {
return TypedData_Wrap_Struct(rb_klass, &opencv_layer_type, ptr);
}
cv::dnn::Layer* obj2layer(VALUE obj) {
cv::dnn::Layer* ptr = NULL;
TypedData_Get_Struct(obj, cv::dnn::Layer, &opencv_layer_type, ptr);
return ptr;
}
VALUE rb_allocate(VALUE klass) {
cv::dnn::Layer* ptr = NULL;
return TypedData_Wrap_Struct(klass, &opencv_layer_type, ptr);
}
VALUE rb_initialize(VALUE self) {
return self;
}
VALUE rb_name(VALUE self) {
cv::dnn::Layer* selfptr = obj2layer(self);
return rb_str_new_cstr(selfptr->name.c_str());
}
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);
rb_define_alloc_func(rb_klass, rb_allocate);
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 0);
rb_define_method(rb_klass, "name", RUBY_METHOD_FUNC(rb_name), 0);
rb_define_method(rb_klass, "type", RUBY_METHOD_FUNC(rb_type), 0);
}
}
}
}

16
ext/opencv/dnn_layer.hpp Normal file
View file

@ -0,0 +1,16 @@
#ifndef RUBY_OPENCV_DNN_LAYER_H
#define RUBY_OPENCV_DNN_LAYER_H
/*
* Document-class: Cv::Dnn::Layer
*/
namespace rubyopencv {
namespace Dnn {
namespace Layer {
void init(VALUE rb_module);
VALUE layer2obj(cv::dnn::Layer* ptr);
}
}
}
#endif // RUBY_OPENCV_DNN_LAYER_H

View file

@ -3,6 +3,7 @@
#include "opencv.hpp"
#include "mat.hpp"
#include "error.hpp"
#include "dnn_layer.hpp"
namespace rubyopencv {
namespace Dnn {
@ -36,7 +37,23 @@ namespace rubyopencv {
return TypedData_Wrap_Struct(klass, &opencv_net_type, ptr);
}
VALUE rb_initialize(VALUE self) {
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);
}
}
return self;
}
@ -69,25 +86,16 @@ namespace rubyopencv {
rb_scan_args(argc, argv, "01", &output_name);
cv::dnn::Net* selfptr = obj2net(self);
cv::Mat* m = NULL;
try {
cv::Mat r;
if (NIL_P(output_name)) {
r = selfptr->forward();
} else {
r = selfptr->forward(StringValueCStr(output_name));
}
m = new cv::Mat(r);
m = new cv::Mat(selfptr->forward(CSTR_DEFAULT(output_name, "")));
} catch(cv::Exception& e) {
delete m;
Error::raise(e);
}
return Mat::mat2obj(m);
return Mat::rb_clone(Mat::mat2obj(m));
}
// bool empty() const
@ -96,34 +104,54 @@ namespace rubyopencv {
return selfptr->empty() ? Qtrue : Qfalse;
}
VALUE rb_get_layer_names(VALUE self) {
VALUE rb_get_layers(VALUE self) {
cv::dnn::Net* selfptr = obj2net(self);
std::vector<cv::String> v = selfptr->getLayerNames();
const long size = v.size();
VALUE layer_names = rb_ary_new_capa(size);
VALUE layers = rb_ary_new_capa(size);
for (long i = 0; i < size; i++) {
VALUE layer_name = rb_str_new_cstr(v[i].c_str());
rb_ary_store(layer_names, i, layer_name);
VALUE layer = Dnn::Layer::layer2obj(selfptr->getLayer(v[i]));
rb_ary_store(layers, i, layer);
}
return layer_names;
return layers;
}
VALUE rb_enable_fusion(VALUE self, VALUE fusion) {
cv::dnn::Net* selfptr = obj2net(self);
selfptr->enableFusion(RTEST(fusion) ? true : false);
return self;
}
VALUE rb_set_preferable_backend(VALUE self, VALUE backend_id) {
cv::dnn::Net* selfptr = obj2net(self);
selfptr->setPreferableBackend(NUM2INT(backend_id));
return self;
}
VALUE rb_set_preferable_target(VALUE self, VALUE target_id) {
cv::dnn::Net* selfptr = obj2net(self);
selfptr->setPreferableTarget(NUM2INT(target_id));
return self;
}
void init(VALUE rb_module) {
rb_klass = rb_define_class_under(rb_module, "Net", rb_cData);
rb_define_alloc_func(rb_klass, rb_allocate);
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 0);
rb_define_private_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, "set_input", "input=");
rb_define_alias(rb_klass, "input", "input=");
rb_define_method(rb_klass, "fusion=", RUBY_METHOD_FUNC(rb_enable_fusion), 1);
rb_define_method(rb_klass, "preferable_backend=", RUBY_METHOD_FUNC(rb_set_preferable_backend), 1);
rb_define_method(rb_klass, "preferable_target=", RUBY_METHOD_FUNC(rb_set_preferable_target), 1);
rb_define_method(rb_klass, "forward", RUBY_METHOD_FUNC(rb_forward), -1);
rb_define_method(rb_klass, "empty?", RUBY_METHOD_FUNC(rb_empty), 0);
rb_define_method(rb_klass, "get_layer_names", RUBY_METHOD_FUNC(rb_get_layer_names), 0);
rb_define_method(rb_klass, "layers", RUBY_METHOD_FUNC(rb_get_layers), 0);
}
}
}

View file

@ -2,6 +2,7 @@
#include <sstream>
#include "opencv2/highgui.hpp"
#include "opencv.hpp"
#include "mat.hpp"
#include "mat_imgproc.hpp"
#include "mat_drawing.hpp"
@ -246,8 +247,10 @@ namespace rubyopencv {
* @return [Mat] Loaded image
* @opencv_func cv::imread
*/
VALUE rb_imread(VALUE self, VALUE filename, VALUE flags) {
return rb_imread_internal(self, filename, flags, rb_klass);
VALUE rb_imread(int argc, VALUE *argv, VALUE self) {
VALUE filename, flags;
rb_scan_args(argc, argv, "11", &filename, &flags);
return rb_imread_internal(self, filename, NUM2INT_DEFAULT(flags, cv::IMREAD_UNCHANGED), rb_klass);
}
VALUE rb_imread_as(VALUE self, VALUE filename, VALUE flags, VALUE klass) {
@ -366,8 +369,10 @@ namespace rubyopencv {
* @return [CvMat] Loaded matrix
* @opencv_func cv::imdecode
*/
VALUE rb_imdecode(VALUE self, VALUE buf, VALUE flags) {
return rb_imdecode_internal(self, buf, flags, rb_klass);
VALUE rb_imdecode(int argc, VALUE *argv, VALUE self) {
VALUE buf, flags;
rb_scan_args(argc, argv, "11", &buf, &flags);
return rb_imdecode_internal(self, buf, NUM2INT_DEFAULT(flags, cv::IMREAD_UNCHANGED), rb_klass);
}
VALUE rb_imdecode_as(VALUE self, VALUE buf, VALUE flags, VALUE klass) {

View file

@ -9,8 +9,8 @@
namespace rubyopencv {
namespace Mat {
void init();
VALUE rb_imread(VALUE self, VALUE filename, VALUE flags);
VALUE rb_imdecode(VALUE self, VALUE buf, VALUE flags);
VALUE rb_imread(int argc, VALUE *argv, VALUE self);
VALUE rb_imdecode(int argc, VALUE *argv, VALUE self);
VALUE rb_imwrite_internal(VALUE filename, VALUE img, VALUE params);
VALUE rb_clone(VALUE self);
VALUE rb_add_weighted(int argc, VALUE *argv, VALUE self);
@ -21,7 +21,7 @@ namespace rubyopencv {
cv::Mat* obj2mat(VALUE obj);
VALUE mat2obj(cv::Mat* ptr);
VALUE mat2obj(cv::Mat* ptr, VALUE klass);
class RubyMatAllocator: public cv::MatAllocator {
public:
RubyMatAllocator() {}

View file

@ -101,9 +101,9 @@ namespace rubyopencv {
rb_define_module_function(rb_module, "build_information", RUBY_METHOD_FUNC(rb_build_information), 0);
rb_define_singleton_method(rb_module, "imread", RUBY_METHOD_FUNC(Mat::rb_imread), 2); // in ext/opencv/mat.cpp
rb_define_singleton_method(rb_module, "imread", RUBY_METHOD_FUNC(Mat::rb_imread), -1); // in ext/opencv/mat.cpp
rb_define_singleton_method(rb_module, "imwrite", RUBY_METHOD_FUNC(rb_imwrite), -1);
rb_define_singleton_method(rb_module, "imdecode", RUBY_METHOD_FUNC(Mat::rb_imdecode), 2); // in ext/opencv/mat.cpp
rb_define_singleton_method(rb_module, "imdecode", RUBY_METHOD_FUNC(Mat::rb_imdecode), -1); // in ext/opencv/mat.cpp
rb_define_singleton_method(rb_module, "wait_key", RUBY_METHOD_FUNC(Window::rb_wait_key), -1); // in ext/opencv/window.cpp
rb_define_singleton_method(rb_module, "add_weighted", RUBY_METHOD_FUNC(Mat::rb_add_weighted), -1); // in ext/opencv/mat.cpp

View file

@ -15,6 +15,10 @@ namespace rubyopencv {
return NIL_P(value) ? (default_value) : NUM2DBL(value);
}
inline std::string CSTR_DEFAULT(VALUE value, std::string default_value) {
return NIL_P(value) ? (default_value) : StringValueCStr(value);
}
inline double RTEST_DEFAULT(VALUE value, bool default_value) {
return NIL_P(value) ? (default_value) : (RTEST(value) ? true : false);
}

View file

@ -1,6 +1,7 @@
// -*- mode: c++; coding: utf-8 -*-
#include "ruby.h"
#include "opencv2/core.hpp"
#include "opencv2/dnn.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
@ -318,7 +319,7 @@ namespace rubyopencv {
rb_define_const(rb_module, "BORDER_REFLECT101", INT2FIX(cv::BORDER_REFLECT101));
rb_define_const(rb_module, "BORDER_DEFAULT", INT2FIX(cv::BORDER_DEFAULT));
rb_define_const(rb_module, "BORDER_ISOLATED", INT2FIX(cv::BORDER_ISOLATED));
rb_define_const(rb_module, "EVENT_MOUSEMOVE", INT2FIX(cv::EVENT_MOUSEMOVE));
rb_define_const(rb_module, "EVENT_LBUTTONDOWN", INT2FIX(cv::EVENT_LBUTTONDOWN));
rb_define_const(rb_module, "EVENT_RBUTTONDOWN", INT2FIX(cv::EVENT_RBUTTONDOWN));
@ -387,6 +388,15 @@ namespace rubyopencv {
rb_define_const(rb_module, "THRESH_OTSU", INT2FIX(cv::THRESH_OTSU));
rb_define_const(rb_module, "THRESH_TRIANGLE", INT2FIX(cv::THRESH_TRIANGLE));
rb_define_const(rb_module, "DNN_BACKEND_DEFAULT", INT2FIX(cv::dnn::DNN_BACKEND_DEFAULT));
rb_define_const(rb_module, "DNN_BACKEND_INFERENCE_ENGINE", INT2FIX(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE));
rb_define_const(rb_module, "DNN_BACKEND_OPENCV", INT2FIX(cv::dnn::DNN_BACKEND_OPENCV));
rb_define_const(rb_module, "DNN_BACKEND_HALIDE", INT2FIX(cv::dnn::DNN_BACKEND_HALIDE));
rb_define_const(rb_module, "DNN_TARGET_CPU", INT2FIX(cv::dnn::DNN_TARGET_CPU));
rb_define_const(rb_module, "DNN_TARGET_OPENCL", INT2FIX(cv::dnn::DNN_TARGET_OPENCL));
rb_define_const(rb_module, "DNN_TARGET_OPENCL_FP16", INT2FIX(cv::dnn::DNN_TARGET_OPENCL_FP16));
rb_define_const(rb_module, "ADAPTIVE_THRESH_MEAN_C", INT2FIX(cv::ADAPTIVE_THRESH_MEAN_C));
rb_define_const(rb_module, "ADAPTIVE_THRESH_GAUSSIAN_C", INT2FIX(cv::ADAPTIVE_THRESH_GAUSSIAN_C));
}