diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index 657cfec..43246e1 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -344,7 +344,7 @@ void define_ruby_class() rb_define_method(rb_klass, "corner_min_eigen_val", RUBY_METHOD_FUNC(rb_corner_min_eigen_val), -1); rb_define_method(rb_klass, "corner_harris", RUBY_METHOD_FUNC(rb_corner_harris), -1); rb_define_method(rb_klass, "find_chessboard_corners", RUBY_METHOD_FUNC(rb_find_chessboard_corners), -1); - rb_define_private_method(rb_klass, "__find_corner_sub_pix", RUBY_METHOD_FUNC(rbi_find_corner_sub_pix), -1); + rb_define_method(rb_klass, "find_corner_sub_pix", RUBY_METHOD_FUNC(rb_find_corner_sub_pix), 4); rb_define_method(rb_klass, "good_features_to_track", RUBY_METHOD_FUNC(rb_good_features_to_track), -1); rb_define_method(rb_klass, "rect_sub_pix", RUBY_METHOD_FUNC(rb_rect_sub_pix), -1); @@ -3744,27 +3744,42 @@ rb_find_chessboard_corners(int argc, VALUE *argv, VALUE self) /* * call-seq: - * find_corner_sub_pix() + * find_corner_sub_pix(corners, win_size, zero_zone, criteria) -> Array * - * Refines corner locations. - * This method iterates to find the sub-pixel accurate location of corners, - * or radial saddle points, as shown in on the picture below. + * Returns refined corner locations. + * + * corners - Initial coordinates of the input corners and refined coordinates provided for output. + * win_size - Half of the side length of the search window. + * zero_zone - Half of the size of the dead region in the middle of the search zone over + * which the summation in the formula below is not done. + * criteria - Criteria for termination of the iterative process of corner refinement. */ VALUE -rbi_find_corner_sub_pix(int argc, VALUE *argv, VALUE self) +rb_find_corner_sub_pix(VALUE self, VALUE corners, VALUE win_size, VALUE zero_zone, VALUE criteria) { - /* - VALUE corners, win, zero_zone, criteria; - rb_scan_args(argc, argv, "13", &corners, &win, &zero_zone, &criteria); - if (!rb_obj_is_kind_of(corners, mPointSet::rb_module())) - rb_raise(rb_eTypeError, "argument 1 (corners) should be %s.", rb_class2name(mPointSet::rb_module())); - int count = CVSEQ(corners)->total; - VALUE storage = cCvMemStorage::new_object(); - CvPoint2D32f *pointset = POINTSET2D32f(corners); - //cvFindCornerSubPix(CVARR(self), pointset, count, VALUE_TO_CVSIZE(win), VALUE_TO_CVSIZE(zero_zone), VALUE_TO_CVTERMCRITERIA(criteria)); - //return cCvSeq::new_sequence(); - */ - return Qnil; + Check_Type(corners, T_ARRAY); + int count = RARRAY_LEN(corners); + CvPoint2D32f* corners_buff = ALLOCA_N(CvPoint2D32f, count); + VALUE* corners_ptr = RARRAY_PTR(corners); + + for (int i = 0; i < count; i++) { + corners_buff[i] = *(CVPOINT2D32F(corners_ptr[i])); + } + + try { + cvFindCornerSubPix(CVARR(self), corners_buff, count, VALUE_TO_CVSIZE(win_size), + VALUE_TO_CVSIZE(zero_zone), VALUE_TO_CVTERMCRITERIA(criteria)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + VALUE refined_corners = rb_ary_new2(count); + for (int i = 0; i < count; i++) { + rb_ary_store(refined_corners, i, cCvPoint2D32f::new_object(corners_buff[i])); + } + + return refined_corners; } /* diff --git a/ext/opencv/cvmat.h b/ext/opencv/cvmat.h index 74ce98c..33615e6 100644 --- a/ext/opencv/cvmat.h +++ b/ext/opencv/cvmat.h @@ -167,7 +167,7 @@ VALUE rb_corner_eigenvv(int argc, VALUE *argv, VALUE self); VALUE rb_corner_min_eigen_val(int argc, VALUE *argv, VALUE self); VALUE rb_corner_harris(int argc, VALUE *argv, VALUE self); VALUE rb_find_chessboard_corners(int argc, VALUE *argv, VALUE self); -VALUE rbi_find_corner_sub_pix(int argc, VALUE *argv, VALUE self); +VALUE rb_find_corner_sub_pix(VALUE self, VALUE corners, VALUE win_size, VALUE zero_zone, VALUE criteria); VALUE rb_good_features_to_track(int argc, VALUE *argv, VALUE self); VALUE rb_rect_sub_pix(int argc, VALUE *argv, VALUE self); diff --git a/test/test_cvmat_imageprocessing.rb b/test/test_cvmat_imageprocessing.rb index 84444da..6923330 100755 --- a/test/test_cvmat_imageprocessing.rb +++ b/test/test_cvmat_imageprocessing.rb @@ -214,7 +214,36 @@ class TestCvMat_imageprocessing < OpenCVTestCase end def test_find_corner_sub_pix - flunk('FIXME: CvMat#find_corner_sub_pix is not implemented yet.') + mat = CvMat.load(FILENAME_CHESSBOARD, CV_LOAD_IMAGE_GRAYSCALE) + pattern_size = CvSize.new(4, 4) + corners = mat.find_chessboard_corners(pattern_size) + expected = [[39, 39], [79, 39], [119, 39], [159, 39], [39, 79], [79, 79], + [119, 79], [159, 78], [38, 119], [79, 119], [119, 119], [158, 118], + [39, 159], [79, 159], [119, 159], [159, 159]] + + refined_corners = mat.find_corner_sub_pix(corners, CvSize.new(3, 3), CvSize.new(-1, -1), + CvTermCriteria.new(20, 0.03)); + assert_equal(expected.size, refined_corners.size) + expected.zip(refined_corners).each { |e, a| + assert_in_delta(e[0], a.x, 3.0) + assert_in_delta(e[1], a.y, 3.0) + } + + assert_raise(TypeError) { + mat.find_corner_sub_pix(DUMMY_OBJ, CvSize.new(3, 3), CvSize.new(-1, -1), + CvTermCriteria.new(20, 0.03)); + } + assert_raise(TypeError) { + mat.find_corner_sub_pix(corners, DUMMY_OBJ, CvSize.new(-1, -1), + CvTermCriteria.new(20, 0.03)); + } + assert_raise(TypeError) { + mat.find_corner_sub_pix(corners, CvSize.new(3, 3), DUMMY_OBJ, + CvTermCriteria.new(20, 0.03)); + } + assert_raise(TypeError) { + mat.find_corner_sub_pix(corners, CvSize.new(3, 3), CvSize.new(-1, -1), DUMMY_OBJ); + } end def test_good_features_to_track