diff --git a/ext/opencv/mat.cpp b/ext/opencv/mat.cpp index d27054f..0631622 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -815,7 +815,38 @@ namespace rubyopencv { return mat2obj(dstptr, CLASS_OF(self)); } - + + /* + * Converts an array to another data type with optional scaling. + * + * @overload convert_to(rtype, alpha = 1, beta = 0) + * @param rtype [Integer] Desired output matrix type or, rather, the depth + * since the number of channels are the same as the input has; + * if rtype is negative, the output matrix will have the same type as the input. + * @param alpha [Number] Optional scale factor. + * @param beta [Number] Optional delta added to the scaled values. + * @return [Mat] +self+ + * @opencv_func cv::convertTo + */ + VALUE rb_convert_to(int argc, VALUE *argv, VALUE self) { + VALUE rtype, alpha, beta; + rb_scan_args(argc, argv, "12", &rtype, &alpha, &beta); + double alpha_value = NIL_P(alpha) ? 1.0 : NUM2DBL(alpha); + double beta_value = NIL_P(beta) ? 0 : NUM2DBL(beta); + + cv::Mat* selfptr = obj2mat(self); + cv::Mat* dstptr = empty_mat(); + try { + selfptr->convertTo(*dstptr, NUM2INT(rtype), alpha_value, beta_value); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, CLASS_OF(self)); + } + void init() { VALUE opencv = rb_define_module("Cv"); @@ -870,6 +901,7 @@ namespace rubyopencv { rb_define_singleton_method(rb_klass, "imdecode_as", RUBY_METHOD_FUNC(rb_imdecode_as), 3); rb_define_method(rb_klass, "convert_scale_abs", RUBY_METHOD_FUNC(rb_convert_scale_abs), -1); + rb_define_method(rb_klass, "convert_to", RUBY_METHOD_FUNC(rb_convert_to), -1); } } } diff --git a/test/test_mat.rb b/test/test_mat.rb index 47dc064..db5f2b3 100755 --- a/test/test_mat.rb +++ b/test/test_mat.rb @@ -363,6 +363,40 @@ class TestMat < OpenCVTestCase } end + def test_convert_to + m0 = Mat.ones(3, 3, CV_32F) * 1.1 + DEPTH.each { |depth| + m = m0.convert_to(depth) + assert_equal(m0.rows, m.rows) + assert_equal(m0.cols, m.cols) + assert_equal(m0.channels, m.channels) + assert_equal(depth, m.depth) + assert_equal(m0[0, 0][0].to_i, m[0, 0][0].to_i) + } + + alpha = 3.0 + beta = 1.0 + m1 = (Mat.ones(3, 3, CV_32F) * alpha) + beta + DEPTH.each { |depth| + m = m0.convert_to(depth, alpha, beta) + assert_equal(m1.rows, m.rows) + assert_equal(m1.cols, m.cols) + assert_equal(m1.channels, m.channels) + assert_equal(depth, m.depth) + assert_equal(m1[0, 0][0].to_i, m[0, 0][0].to_i) + } + + assert_raise(TypeError) { + m0.convert_to(DUMMY_OBJ) + } + assert_raise(TypeError) { + m0.convert_to(CV_8U, DUMMY_OBJ) + } + assert_raise(TypeError) { + m0.convert_to(CV_8U, 0.1, DUMMY_OBJ) + } + end + def test_imencode m = Cv::imread(FILENAME_LENA32x32, -1)