From 2e63bbd856b445ba1f92a189dba1c1197853aa33 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 7 Jul 2013 06:06:13 +0900 Subject: [PATCH] add Algorithm class and modify FaceRecognizer to inherit it --- ext/opencv/algorithm.cpp | 286 ++++++++++++++++++++++++++++++++++ ext/opencv/algorithm.h | 38 +++++ ext/opencv/facerecognizer.cpp | 2 +- ext/opencv/opencv.cpp | 1 + ext/opencv/opencv.h | 1 + test/test_eigenfaces.rb | 18 +++ 6 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 ext/opencv/algorithm.cpp create mode 100644 ext/opencv/algorithm.h diff --git a/ext/opencv/algorithm.cpp b/ext/opencv/algorithm.cpp new file mode 100644 index 0000000..a406366 --- /dev/null +++ b/ext/opencv/algorithm.cpp @@ -0,0 +1,286 @@ +/************************************************************ + + algorithm.cpp - + + $Author: ser1zw $ + + Copyright (C) 2013 ser1zw + +************************************************************/ +#include +#include "algorithm.h" +/* + * Document-class: OpenCV::Algorithm + * + */ +__NAMESPACE_BEGIN_OPENCV +__NAMESPACE_BEGIN_ALGORITHM + +VALUE rb_klass; + +VALUE +rb_class() +{ + return rb_klass; +} + +VALUE +rb_set_int(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + try { + ALGORITHM(self)->setInt(StringValueCStr(parameter), NUM2INT(value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_double(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + try { + ALGORITHM(self)->setDouble(StringValueCStr(parameter), NUM2DBL(value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_bool(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + try { + bool val = TRUE_OR_FALSE(value) ? true : false; + ALGORITHM(self)->setBool(StringValueCStr(parameter), val); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_string(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + Check_Type(T_STRING, value); + try { + ALGORITHM(self)->setString(StringValueCStr(parameter), StringValueCStr(value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_mat(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + try { + CvMat* val = CVMAT_WITH_CHECK(value); + cv::Mat mat(val); + ALGORITHM(self)->setMat(StringValueCStr(parameter), mat); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_matvector(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + Check_Type(T_ARRAY, value); + try { + long len = RARRAY_LEN(value); + VALUE* value_ptr = RARRAY_PTR(value); + std::vector mat_vector; + for (int i = 0; i < len; i++) { + CvMat* val = CVMAT_WITH_CHECK(value_ptr[i]); + cv::Mat mat(val); + mat_vector.push_back(mat); + } + ALGORITHM(self)->setMatVector(StringValueCStr(parameter), mat_vector); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + +VALUE +rb_set_algorithm(VALUE self, VALUE parameter, VALUE value) +{ + Check_Type(T_STRING, parameter); + try { + ALGORITHM(self)->setAlgorithm(StringValueCStr(parameter), ALGORITHM(value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return Qnil; +} + + +VALUE +rb_get_int(VALUE self, VALUE parameter) +{ + Check_Type(T_STRING, parameter); + int value = 0; + try { + value = ALGORITHM(self)->getInt(StringValueCStr(parameter)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return INT2NUM(value); +} + +VALUE +rb_get_double(VALUE self, VALUE parameter) +{ + Check_Type(T_STRING, parameter); + double value = 0.0; + try { + value = ALGORITHM(self)->getDouble(StringValueCStr(parameter)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return NUM2DBL(value); +} + +VALUE +rb_get_bool(VALUE self, VALUE parameter) +{ + Check_Type(T_STRING, parameter); + bool value = false; + try { + value = ALGORITHM(self)->getBool(StringValueCStr(parameter)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return value ? Qtrue : Qfalse; +} + +VALUE +rb_get_string(VALUE self, VALUE parameter) +{ + Check_Type(T_STRING, parameter); + std::string value = ""; + try { + value = ALGORITHM(self)->getString(StringValueCStr(parameter)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return rb_str_new_cstr(value.c_str()); +} + +VALUE +rb_get_mat(VALUE self, VALUE parameter) +{ + Check_Type(parameter, T_STRING); + VALUE mat = Qnil; + try { + cv::Mat value = ALGORITHM(self)->getMat(StringValueCStr(parameter)); + cv::Size size = value.size(); + mat = cCvMat::new_object(size.height, size.width, value.type()); + cv::Mat dst(CVMAT(mat)); + value.copyTo(dst); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return mat; +} + +VALUE +rb_get_matvector(VALUE self, VALUE parameter) +{ + Check_Type(T_STRING, parameter); + VALUE array = Qnil; + try { + std::vector value = ALGORITHM(self)->getMatVector(StringValueCStr(parameter)); + int len = value.size(); + array = rb_ary_new2(len); + for (int i = 0; i < len; i++) { + cv::Mat m = value[i]; + cv::Size size = m.size(); + VALUE mat = cCvMat::new_object(size.height, size.width, m.type()); + cv::Mat dst(CVMAT(mat)); + m.copyTo(dst); + rb_ary_store(array, i, mat); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return array; +} + +VALUE +rb_name(VALUE self) +{ + VALUE name = Qnil; + try { + name = rb_str_new_cstr(ALGORITHM(self)->name().c_str()); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return name; +} + +void +define_ruby_class() +{ + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "Algorithm", rb_cObject); + rb_define_method(rb_klass, "set_int", RUBY_METHOD_FUNC(rb_set_int), 2); + rb_define_method(rb_klass, "set_double", RUBY_METHOD_FUNC(rb_set_double), 2); + rb_define_method(rb_klass, "set_bool", RUBY_METHOD_FUNC(rb_set_bool), 2); + rb_define_method(rb_klass, "set_string", RUBY_METHOD_FUNC(rb_set_string), 2); + rb_define_method(rb_klass, "set_mat", RUBY_METHOD_FUNC(rb_set_mat), 2); + rb_define_method(rb_klass, "set_matvector", RUBY_METHOD_FUNC(rb_set_matvector), 2); + rb_define_method(rb_klass, "set_algorithm", RUBY_METHOD_FUNC(rb_set_algorithm), 2); + + rb_define_method(rb_klass, "get_int", RUBY_METHOD_FUNC(rb_get_int), 1); + rb_define_method(rb_klass, "get_double", RUBY_METHOD_FUNC(rb_get_double), 1); + rb_define_method(rb_klass, "get_bool", RUBY_METHOD_FUNC(rb_get_bool), 1); + rb_define_method(rb_klass, "get_string", RUBY_METHOD_FUNC(rb_get_string), 1); + rb_define_method(rb_klass, "get_mat", RUBY_METHOD_FUNC(rb_get_mat), 1); + rb_define_method(rb_klass, "get_matvector", RUBY_METHOD_FUNC(rb_get_matvector), 1); + + rb_define_method(rb_klass, "name", RUBY_METHOD_FUNC(rb_name), 0); +} + +__NAMESPACE_END_ALGORITM +__NAMESPACE_END_OPENCV + diff --git a/ext/opencv/algorithm.h b/ext/opencv/algorithm.h new file mode 100644 index 0000000..d8d922e --- /dev/null +++ b/ext/opencv/algorithm.h @@ -0,0 +1,38 @@ +/************************************************************ + + algorithm.h + + $Author: ser1zw $ + + Copyright (C) 2013 ser1zw + +************************************************************/ +#ifndef RUBY_OPENCV_ALGORITHM_H +#define RUBY_OPENCV_ALGORITHM_H + +#include "opencv.h" + +#define __NAMESPACE_BEGIN_ALGORITHM namespace cAlgorithm { +#define __NAMESPACE_END_ALGORITM } + +__NAMESPACE_BEGIN_OPENCV +__NAMESPACE_BEGIN_ALGORITHM + +VALUE rb_class(); + +void define_ruby_class(); + +__NAMESPACE_END_ALGORITM + +inline cv::Algorithm* +ALGORITHM(VALUE object) +{ + cv::Algorithm *ptr; + Data_Get_Struct(object, cv::Algorithm, ptr); + return ptr; +} + +__NAMESPACE_END_OPENCV + +#endif // RUBY_OPENCV_ALGORITHM_H + diff --git a/ext/opencv/facerecognizer.cpp b/ext/opencv/facerecognizer.cpp index 69b10b0..3fd73b0 100644 --- a/ext/opencv/facerecognizer.cpp +++ b/ext/opencv/facerecognizer.cpp @@ -138,7 +138,7 @@ define_ruby_class() * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "FaceRecognizer", rb_cObject); + rb_klass = rb_define_class_under(opencv, "FaceRecognizer", cAlgorithm::rb_class()); rb_define_method(rb_klass, "train", RUBY_METHOD_FUNC(rb_train), 2); rb_define_method(rb_klass, "predict", RUBY_METHOD_FUNC(rb_predict), 1); rb_define_method(rb_klass, "save", RUBY_METHOD_FUNC(rb_save), 1); diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index 9787d80..6ca14ea 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -707,6 +707,7 @@ extern "C" { mOpenCV::cCvAvgComp::define_ruby_class(); mOpenCV::cCvHaarClassifierCascade::define_ruby_class(); + mOpenCV::cAlgorithm::define_ruby_class(); mOpenCV::cFaceRecognizer::define_ruby_class(); mOpenCV::cEigenFaces::define_ruby_class(); diff --git a/ext/opencv/opencv.h b/ext/opencv/opencv.h index 2fd9881..0d39aa1 100644 --- a/ext/opencv/opencv.h +++ b/ext/opencv/opencv.h @@ -130,6 +130,7 @@ extern "C" { #include "cvfeaturetree.h" +#include "algorithm.h" #include "facerecognizer.h" #include "eigenfaces.h" diff --git a/test/test_eigenfaces.rb b/test/test_eigenfaces.rb index 4f7df07..4e3453e 100755 --- a/test/test_eigenfaces.rb +++ b/test/test_eigenfaces.rb @@ -11,6 +11,10 @@ include OpenCV class TestEigenFaces < OpenCVTestCase def setup @eigenfaces = EigenFaces.new + + @eigenfaces_trained = EigenFaces.new + img = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE) + @eigenfaces_trained.train([img], [1]) end def test_initialize @@ -75,5 +79,19 @@ class TestEigenFaces < OpenCVTestCase @eigenfaces.load(DUMMY_OBJ) } end + + def test_name + assert_equal('FaceRecognizer.Eigenfaces', @eigenfaces.name) + end + + def test_get_mat + mat = @eigenfaces_trained.get_mat('eigenvalues') + assert_not_nil(mat) + assert_equal(CvMat, mat.class) + + assert_raise(TypeError) { + @eigenfaces_trained.get_mat(DUMMY_OBJ) + } + end end