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

add Cv::Mat#split and Cv::merge

This commit is contained in:
ser1zw 2016-04-30 19:26:26 +09:00
parent 7b34f21e4f
commit 54ab023195
4 changed files with 105 additions and 0 deletions

View file

@ -956,6 +956,67 @@ namespace rubyopencv {
return self;
}
/*
* Divides a multi-channel array into several single-channel arrays.
* The functions split split a multi-channel array into separate single-channel arrays.
*
* @overload split
* @return [Array<Mat>] Output array; the number of arrays must match self.channels
* @opencv_func cv::split
*/
VALUE rb_split(VALUE self) {
cv::Mat* selfptr = obj2mat(self);
std::vector<cv::Mat> splitted;
try {
cv::split(*selfptr, splitted);
}
catch (cv::Exception& e) {
Error::raise(e);
}
const int size = selfptr->channels();
VALUE result = rb_ary_new2(size);
for (int i = 0; i < size; i++) {
cv::Mat* tmp = new cv::Mat(splitted[i]);
rb_ary_store(result, i, mat2obj(tmp));
}
return result;
}
/*
* Creates one multi-channel array out of several single-channel ones.
* The function merge merges several arrays to make a single multi-channel array.
*
* @overload merge(mv)
* @param mv [Array<Mat>] Input array of matrices to be merged; all the matrices in mv must have the same size and the same depth.
* @return [Mat] Output array of the same size and the same depth as mv[0]; The number of channels will be equal to the parameter count.
* @!scope class
* @opencv_func cv::merge
*/
VALUE rb_merge(VALUE self, VALUE mv) {
Check_Type(mv, T_ARRAY);
const long size = RARRAY_LEN(mv);
std::vector<cv::Mat> matrixes;
for (long i = 0; i < size; i++) {
VALUE elt = RARRAY_AREF(mv, i);
cv::Mat* tmp = obj2mat(elt);
matrixes.push_back(*tmp);
}
cv::Mat* dstptr = NULL;
try {
dstptr = new cv::Mat();
cv::merge(matrixes, *dstptr);
}
catch (cv::Exception& e) {
delete dstptr;
Error::raise(e);
}
return mat2obj(dstptr);
}
void init() {
VALUE opencv = rb_define_module("Cv");
@ -1017,6 +1078,7 @@ namespace rubyopencv {
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);
rb_define_method(rb_klass, "set_identity", RUBY_METHOD_FUNC(rb_set_identity), -1);
rb_define_method(rb_klass, "split", RUBY_METHOD_FUNC(rb_split), 0);
}
}
}

View file

@ -14,6 +14,8 @@ namespace rubyopencv {
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);
VALUE rb_merge(VALUE self, VALUE mv);
cv::Mat* obj2mat(VALUE obj);
VALUE mat2obj(cv::Mat* ptr);
VALUE mat2obj(cv::Mat* ptr, VALUE klass);

View file

@ -105,6 +105,7 @@ namespace rubyopencv {
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
rb_define_singleton_method(rb_module, "merge", RUBY_METHOD_FUNC(Mat::rb_merge), 1); // in ext/opencv/mat.cpp
rb_define_singleton_method(rb_module, "CV_MAKETYPE", RUBY_METHOD_FUNC(rb_maketype), 2);

View file

@ -579,4 +579,44 @@ class TestMat < OpenCVTestCase
m.set_identity(DUMMY_OBJ)
}
end
def test_split
m = Mat::zeros(1, 1, CV_8UC3)
m[0, 0] = Scalar.new(1, 2, 3)
a = m.split
assert_equal(3, a.size)
a.each_with_index { |x, i|
assert_equal(m.class, x.class)
assert_equal(m.rows, x.rows)
assert_equal(m.cols, x.cols)
assert_equal(m.depth, x.depth)
assert_equal(1, x.channels)
assert_equal(m[0, 0][i], x[0, 0][0])
}
end
def test_merge
m = Mat::zeros(1, 1, CV_8U)
b = m + 1
g = m + 2
r = m + 3
a = Cv::merge([b, g, r])
assert_equal(b.class, a.class)
assert_equal(b.rows, a.rows)
assert_equal(b.cols, a.cols)
assert_equal(b.depth, a.depth)
assert_equal(3, a.channels)
assert_equal(b[0, 0][0], a[0, 0][0])
assert_equal(g[0, 0][0], a[0, 0][1])
assert_equal(r[0, 0][0], a[0, 0][2])
assert_raise(TypeError) {
Cv::merge(DUMMY_OBJ)
}
assert_raise(TypeError) {
Cv::merge([DUMMY_OBJ])
}
end
end