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

Added support for DNN (3.3.0-rc in experimental mode).

This commit is contained in:
Francois Deschenes 2018-07-24 22:37:36 -07:00
parent ca813d4f71
commit a524cda800
6 changed files with 241 additions and 3 deletions

74
ext/opencv/dnn.cpp Normal file
View file

@ -0,0 +1,74 @@
#include "opencv2/dnn.hpp"
#include "opencv.hpp"
#include "mat.hpp"
#include "size.hpp"
#include "scalar.hpp"
#include "dnn_net.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;
// Mat blobFromImage(const Mat& image, double scalefactor=1.0, const Size& size = Size(), const Scalar& mean = Scalar(), bool swapRB=true)
VALUE rb_blob_from_image(int argc, VALUE *argv, VALUE self) {
VALUE image, options;
rb_scan_args(argc, argv, "11", &image, &options);
cv::Mat *b;
cv::Mat *m = Mat::obj2mat(image);
try {
cv::Mat r;
if (NIL_P(options)) {
r = cv::dnn::blobFromImage(*m);
} else {
Check_Type(options, T_HASH);
double scale_factor = NUM2DBL_DEFAULT(HASH_LOOKUP(options, "scale_factor"), 1.0);
cv::Size *s = Size::obj2size(HASH_LOOKUP(options, "size"));
cv::Scalar *sc = Scalar::obj2scalar(HASH_LOOKUP(options, "mean"));;
r = cv::dnn::blobFromImage(*m, scale_factor, *s, *sc);
}
b = new cv::Mat(r);
} catch(cv::Exception& e) {
delete b;
Error::raise(e);
}
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::experimental_dnn_v1::Net *net;
try {
net = new cv::dnn::experimental_dnn_v1::Net(cv::dnn::readNetFromCaffe(StringValueCStr(prototxt), StringValueCStr(caffe_model)));
} catch(cv::Exception& e) {
delete net;
Error::raise(e);
}
return Dnn::Net::net2obj(net);
}
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_from_caffe", RUBY_METHOD_FUNC(rb_read_net_from_caffe), 2);
Dnn::Net::init(rb_module);
}
}
}

13
ext/opencv/dnn.hpp Normal file
View file

@ -0,0 +1,13 @@
#ifndef RUBY_OPENCV_DNN_H
#define RUBY_OPENCV_DNN_H
/*
* Document-class: Cv::Dnn
*/
namespace rubyopencv {
namespace Dnn {
void init();
}
}
#endif // RUBY_OPENCV_DNN_H

133
ext/opencv/dnn_net.cpp Normal file
View file

@ -0,0 +1,133 @@
#include "opencv2/dnn.hpp"
#include "opencv.hpp"
#include "mat.hpp"
#include "error.hpp"
namespace rubyopencv {
namespace Dnn {
namespace Net {
VALUE rb_klass = Qnil;
void free_net(void* ptr) {
delete (cv::dnn::experimental_dnn_v1::Net*)ptr;
}
size_t memsize_net(const void* ptr) {
return sizeof(cv::dnn::experimental_dnn_v1::Net);
}
rb_data_type_t opencv_net_type = {
"Dnn::Net", { 0, free_net, memsize_net, }, 0, 0, 0
};
VALUE net2obj(cv::dnn::experimental_dnn_v1::Net* ptr) {
return TypedData_Wrap_Struct(rb_klass, &opencv_net_type, ptr);
}
cv::dnn::experimental_dnn_v1::Net* obj2net(VALUE obj) {
cv::dnn::experimental_dnn_v1::Net* ptr = NULL;
TypedData_Get_Struct(obj, cv::dnn::experimental_dnn_v1::Net, &opencv_net_type, ptr);
return ptr;
}
VALUE rb_allocate(VALUE klass) {
cv::dnn::experimental_dnn_v1::Net* ptr = new cv::dnn::experimental_dnn_v1::Net();
return TypedData_Wrap_Struct(klass, &opencv_net_type, ptr);
}
VALUE rb_initialize(VALUE self) {
return self;
}
// 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);
cv::dnn::experimental_dnn_v1::Net* selfptr = obj2net(self);
cv::Mat *m = Mat::obj2mat(blob);
try {
if (NIL_P(name)) {
selfptr->setInput(*m);
} else {
selfptr->setInput(*m, StringValueCStr(name));
}
} catch(cv::Exception& e) {
delete m;
Error::raise(e);
}
return Qnil;
}
// Mat forward(const String& outputName = String())
VALUE rb_forward(int argc, VALUE *argv, VALUE self) {
VALUE output_name;
rb_scan_args(argc, argv, "01", &output_name);
cv::dnn::experimental_dnn_v1::Net* selfptr = obj2net(self);
cv::Mat* m = NULL;
// cv::Mat m;
try {
cv::Mat r;
if (NIL_P(output_name)) {
r = selfptr->forward();
} else {
r = selfptr->forward(StringValueCStr(output_name));
}
m = new cv::Mat(r.reshape(1, 1));
// m = r;
} catch(cv::Exception& e) {
delete m;
Error::raise(e);
}
// int indxCls[4] = { 0, 0, 401, 1 };
// int cls = m->at<float>(indxCls);
return Mat::mat2obj(m);
// const long size = m->size[2];
// return(ULL2NUM(m.size[2]));
// VALUE detected_objects = rb_ary_new_capa(size);
// for (long i = 0; i < size; i++) {
// int indxCls[4] = { 0, 0, i, 1 };
// int cls = m->at<float>(indxCls);
// rb_ary_store(detected_objects, i, INT2NUM(cls));
// }
//
// return detected_objects;
// cv::Point classIdPoint;
// double confidence;
// cv::minMaxLoc(m.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
// int classId = classIdPoint.x;
// return(INT2NUM(classId));
}
// bool empty() const
VALUE rb_empty(VALUE self) {
cv::dnn::experimental_dnn_v1::Net* selfptr = obj2net(self);
return selfptr->empty() ? Qtrue : Qfalse;
}
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_method(rb_klass, "set_input", RUBY_METHOD_FUNC(rb_set_input), -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);
}
}
}
}

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

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

View file

@ -21,10 +21,10 @@ def cv_version_suffix(incdir)
major + minor + subminor major + minor + subminor
end end
incdir, libdir = dir_config("opencv", "/usr/local/include", "/usr/local/lib") incdir, _ = dir_config("opencv", "/usr/local/include", "/usr/local/lib")
opencv_headers = ["opencv2/core.hpp", "opencv2/highgui.hpp", "opencv2/imgcodecs.hpp", "opencv2/imgproc.hpp", "opencv2/objdetect.hpp", "opencv2/videoio.hpp"] opencv_headers = ["opencv2/core.hpp", "opencv2/highgui.hpp", "opencv2/imgcodecs.hpp", "opencv2/imgproc.hpp", "opencv2/objdetect.hpp", "opencv2/videoio.hpp", "opencv2/dnn.hpp"]
opencv_libraries = ["opencv_core", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc", "opencv_objdetect", "opencv_videoio"] opencv_libraries = ["opencv_core", "opencv_highgui", "opencv_imgcodecs", "opencv_imgproc", "opencv_objdetect", "opencv_videoio", "opencv_dnn"]
puts ">> Check the required libraries..." puts ">> Check the required libraries..."
if $mswin or $mingw if $mswin or $mingw

View file

@ -12,6 +12,7 @@
#include "scalar.hpp" #include "scalar.hpp"
#include "cascadeclassifier.hpp" #include "cascadeclassifier.hpp"
#include "dnn.hpp"
#include "videocapture.hpp" #include "videocapture.hpp"
#include "error.hpp" #include "error.hpp"
@ -92,6 +93,7 @@ namespace rubyopencv {
Size::init(); Size::init();
Scalar::init(); Scalar::init();
CascadeClassifier::init(); CascadeClassifier::init();
Dnn::init();
VideoCapture::init(); VideoCapture::init();
Window::init(); Window::init();
Trackbar::init(); Trackbar::init();