diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp
index 8861a4e..aafdcf1 100644
--- a/ext/opencv/cvmat.cpp
+++ b/ext/opencv/cvmat.cpp
@@ -225,8 +225,8 @@ void define_ruby_class()
rb_define_method(rb_klass, "to_CvMat", RUBY_METHOD_FUNC(rb_to_CvMat), 0);
rb_define_method(rb_klass, "sub_rect", RUBY_METHOD_FUNC(rb_sub_rect), -2);
rb_define_alias(rb_klass, "subrect", "sub_rect");
- rb_define_method(rb_klass, "get_rows", RUBY_METHOD_FUNC(rb_get_rows), -2);
- rb_define_method(rb_klass, "get_cols", RUBY_METHOD_FUNC(rb_get_cols), -2);
+ rb_define_method(rb_klass, "get_rows", RUBY_METHOD_FUNC(rb_get_rows), -1);
+ rb_define_method(rb_klass, "get_cols", RUBY_METHOD_FUNC(rb_get_cols), 1);
rb_define_method(rb_klass, "each_row", RUBY_METHOD_FUNC(rb_each_row), 0);
rb_define_method(rb_klass, "each_col", RUBY_METHOD_FUNC(rb_each_col), 0);
rb_define_alias(rb_klass, "each_column", "each_col");
@@ -1058,77 +1058,71 @@ rb_sub_rect(VALUE self, VALUE args)
return DEPEND_OBJECT(rb_klass, mat, self);
}
-/*
- * call-seq:
- * get_rows(n) -> Return row
- * get_rows(n1, n2, ...) -> Return Array of row
- *
- * Return row(or rows) of matrix.
- * argument should be Fixnum or CvSlice compatible object.
- */
-VALUE
-rb_get_rows(VALUE self, VALUE args)
-{
- int len = RARRAY_LEN(args);
- if (len < 1)
- rb_raise(rb_eArgError, "wrong number of argument.(more than 1)");
- VALUE ary = rb_ary_new2(len);
- for (int i = 0; i < len; ++i) {
- VALUE value = rb_ary_entry(args, i);
-
- CvMat* row = NULL;
- try {
- if (FIXNUM_P(value))
- row = cvGetRow(CVARR(self), RB_CVALLOC(CvMat), FIX2INT(value));
- else {
- CvSlice slice = VALUE_TO_CVSLICE(value);
- row = cvGetRows(CVARR(self), RB_CVALLOC(CvMat), slice.start_index, slice.end_index);
- }
+void
+rb_get_range_index(VALUE index, int* start, int *end) {
+ if (rb_obj_is_kind_of(index, rb_cRange)) {
+ *start = NUM2INT(rb_funcall3(index, rb_intern("begin"), 0, NULL));
+ *end = NUM2INT(rb_funcall3(index, rb_intern("end"), 0, NULL));
+ if (rb_funcall3(index, rb_intern("exclude_end?"), 0, NULL) == Qfalse) {
+ (*end)++;
}
- catch (cv::Exception& e) {
- if (row != NULL)
- cvReleaseMat(&row);
- raise_cverror(e);
- }
- rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, row, self));
}
- return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0);
+ else {
+ *start = NUM2INT(index);
+ *end = *start + 1;
+ }
}
/*
* call-seq:
- * get_cols(n) -> Return column
- * get_cols(n1, n2, ...) -> Return Array of columns
+ * get_rows(row, delta_row = 1) -> cvmat
*
- * Return column(or columns) of matrix.
- * argument should be Fixnum or CvSlice compatible object.
+ * Return row(or rows) of matrix.
+ * argument row should be Fixnum or Range object.
*/
VALUE
-rb_get_cols(VALUE self, VALUE args)
+rb_get_rows(int argc, VALUE* argv, VALUE self)
{
- int len = RARRAY_LEN(args);
- if (len < 1)
- rb_raise(rb_eArgError, "wrong number of argument.(more than 1)");
- VALUE ary = rb_ary_new2(len);
- for (int i = 0; i < len; ++i) {
- VALUE value = rb_ary_entry(args, i);
- CvMat* col = NULL;
- try {
- if (FIXNUM_P(value))
- col = cvGetCol(CVARR(self), RB_CVALLOC(CvMat), FIX2INT(value));
- else {
- CvSlice slice = VALUE_TO_CVSLICE(value);
- col = cvGetCols(CVARR(self), RB_CVALLOC(CvMat), slice.start_index, slice.end_index);
- }
- }
- catch (cv::Exception& e) {
- if (col != NULL)
- cvReleaseMat(&col);
- raise_cverror(e);
- }
- rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, col, self));
+ VALUE row_val, delta_val;
+ rb_scan_args(argc, argv, "11", &row_val, &delta_val);
+
+ int start, end;
+ rb_get_range_index(row_val, &start, &end);
+ int delta = NIL_P(delta_val) ? 1 : NUM2INT(delta_val);
+ CvMat* submat = RB_CVALLOC(CvMat);
+ try {
+ cvGetRows(CVARR(self), submat, start, end, delta);
}
- return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0);
+ catch (cv::Exception& e) {
+ cvFree(&submat);
+ raise_cverror(e);
+ }
+
+ return DEPEND_OBJECT(rb_klass, submat, self);
+}
+
+/*
+ * call-seq:
+ * get_cols(col) -> cvmat
+ *
+ * Return column(or columns) of matrix.
+ * argument col should be Fixnum or Range object.
+ */
+VALUE
+rb_get_cols(VALUE self, VALUE col)
+{
+ int start, end;
+ rb_get_range_index(col, &start, &end);
+ CvMat* submat = RB_CVALLOC(CvMat);
+ try {
+ cvGetCols(CVARR(self), submat, start, end);
+ }
+ catch (cv::Exception& e) {
+ cvFree(&submat);
+ raise_cverror(e);
+ }
+
+ return DEPEND_OBJECT(rb_klass, submat, self);
}
/*
diff --git a/ext/opencv/cvmat.h b/ext/opencv/cvmat.h
index 4138454..fae26c6 100644
--- a/ext/opencv/cvmat.h
+++ b/ext/opencv/cvmat.h
@@ -58,8 +58,8 @@ VALUE rb_square_q(VALUE self);
VALUE rb_to_CvMat(VALUE self);
VALUE rb_to_IplImage(VALUE self);
VALUE rb_sub_rect(VALUE self, VALUE args);
-VALUE rb_get_rows(VALUE self, VALUE args);
-VALUE rb_get_cols(VALUE self, VALUE args);
+VALUE rb_get_rows(int argc, VALUE* argv, VALUE self);
+VALUE rb_get_cols(VALUE self, VALUE col);
VALUE rb_each_row(VALUE self);
VALUE rb_each_col(VALUE self);
VALUE rb_diag(int argc, VALUE *argv, VALUE self);
diff --git a/test/test_cvmat.rb b/test/test_cvmat.rb
index 3cf0973..daa19b8 100755
--- a/test/test_cvmat.rb
+++ b/test/test_cvmat.rb
@@ -439,48 +439,77 @@ class TestCvMat < OpenCVTestCase
end
def test_get_rows
- m1 = create_cvmat(10, 20)
+ m1 = create_cvmat(10, 20) { |j, i, c| CvScalar.new(c) }
- m2 = m1.get_rows(2)
- assert_equal(1, m2.height)
- assert_equal(m1.width, m2.width)
- m1.width.times { |i|
- assert_cvscalar_equal(m1[2, i], m2[i])
+ row = 2
+ m2 = m1.get_rows(row)
+ assert_equal(1, m2.rows)
+ assert_equal(m1.cols, m2.cols)
+ m1.cols.times { |i|
+ assert_cvscalar_equal(m1[row, i], m2[i])
}
- m2, m3 = m1.get_rows(1, 2)
- [m2, m3].each { |m|
- assert_equal(1, m.height)
- assert_equal(m1.width, m.width)
+ row1 = 3..7
+ row2 = 2...8
+ [row1, row2].each { |row|
+ m3 = m1.get_rows(row)
+ w = (row.exclude_end?) ? row.last - row.begin : row.last - row.begin + 1
+ assert_equal(w, m3.rows)
+ assert_equal(m1.cols, m3.cols)
+
+ m3.rows.times { |j|
+ m3.cols.times { |i|
+ assert_cvscalar_equal(m1[row.begin + j, i], m3[j, i])
+ }
+ }
}
- m1.width.times { |i|
- assert_cvscalar_equal(m1[1, i], m2[i])
- assert_cvscalar_equal(m1[2, i], m3[i])
+
+ [row1, row2].each { |row|
+ delta = 2
+ m3 = m1.get_rows(row, 2)
+ w = (((row.exclude_end?) ? row.last - row.begin : row.last - row.begin + 1).to_f / delta).ceil
+ assert_equal(w, m3.rows)
+ assert_equal(m1.cols, m3.cols)
+
+ m3.rows.times { |j|
+ m3.cols.times { |i|
+ assert_cvscalar_equal(m1[row.begin + j * delta, i], m3[j, i])
+ }
+ }
}
assert_raise(TypeError) {
m1.get_rows(DUMMY_OBJ)
}
+ assert_raise(TypeError) {
+ m1.get_rows(1, DUMMY_OBJ)
+ }
end
def test_get_cols
- m1 = create_cvmat(10, 20)
+ m1 = create_cvmat(10, 20) { |j, i, c| CvScalar.new(c) }
- m2 = m1.get_cols(2)
- assert_equal(1, m2.width)
- assert_equal(m1.height, m2.height)
+ col = 2
+ m2 = m1.get_cols(col)
+ assert_equal(m1.rows, m2.rows)
+ assert_equal(1, m2.cols)
m1.height.times { |j|
- assert_cvscalar_equal(m1[j, 2], m2[j])
+ assert_cvscalar_equal(m1[j, col], m2[j])
}
- m2, m3 = m1.get_cols(1, 2)
- [m2, m3].each { |m|
- assert_equal(1, m.width)
- assert_equal(m1.height, m.height)
- }
- m1.height.times { |j|
- assert_cvscalar_equal(m1[j, 1], m2[j])
- assert_cvscalar_equal(m1[j, 2], m3[j])
+ col1 = 3..7
+ col2 = 2...8
+ [col1, col2].each { |col|
+ m3 = m1.get_cols(col)
+ w = (col.exclude_end?) ? col.last - col.begin : col.last - col.begin + 1
+ assert_equal(m1.rows, m3.rows)
+ assert_equal(w, m3.cols)
+
+ m3.rows.times { |j|
+ m3.cols.times { |i|
+ assert_cvscalar_equal(m1[j, col.begin + i], m3[j, i])
+ }
+ }
}
assert_raise(TypeError) {