From 5dda055611ba88c08931484e60d947b2dd82c5d1 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Tue, 1 May 2012 05:41:06 +0900 Subject: [PATCH] add CvContour#approx_poly --- ext/opencv/cvcontour.cpp | 26 +++++++++++------------ test/test_cvcontour.rb | 45 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/ext/opencv/cvcontour.cpp b/ext/opencv/cvcontour.cpp index 0b21c36..5ea31d7 100644 --- a/ext/opencv/cvcontour.cpp +++ b/ext/opencv/cvcontour.cpp @@ -19,8 +19,8 @@ __NAMESPACE_BEGIN_CVCONTOUR #define APPROX_POLY_OPTION(op) rb_get_option_table(rb_klass, "APPROX_OPTION", op) #define APPROX_POLY_METHOD(op) CVMETHOD("APPROX_POLY_METHOD", LOOKUP_CVMETHOD(op, "method"), CV_POLY_APPROX_DP) -#define APPROX_POLY_ACCURACY(op) NUM2DBL(LOOKUP_CVMETHOD(op, "accuracy")) -#define APPROX_POLY_RECURSIVE(op) TRUE_OR_FALSE(LOOKUP_CVMETHOD(op, "recursive")) +#define APPROX_POLY_PARAMETER(op) NUM2DBL(LOOKUP_CVMETHOD(op, "parameter")) +#define APPROX_POLY_PARAMETER2(op) TRUE_OR_FALSE(LOOKUP_CVMETHOD(op, "parameter2")) VALUE rb_allocate(VALUE klass); void cvcontour_free(void *ptr); @@ -60,8 +60,8 @@ define_ruby_class() VALUE approx_option = rb_hash_new(); rb_define_const(rb_klass, "APPROX_OPTION", approx_option); rb_hash_aset(approx_option, ID2SYM(rb_intern("method")), INT2FIX(CV_POLY_APPROX_DP)); - rb_hash_aset(approx_option, ID2SYM(rb_intern("accuracy")), rb_float_new(1.0)); - rb_hash_aset(approx_option, ID2SYM(rb_intern("recursive")), Qfalse); + rb_hash_aset(approx_option, ID2SYM(rb_intern("parameter")), rb_float_new(1.0)); + rb_hash_aset(approx_option, ID2SYM(rb_intern("parameter2")), Qfalse); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); rb_define_method(rb_klass, "rect", RUBY_METHOD_FUNC(rb_rect), 0); @@ -149,21 +149,21 @@ rb_reserved(VALUE self) * If not nil or false, the function approximates all chains that access can be obtained to * from self by h_next or v_next links. If 0, approximated this one. */ - VALUE rb_approx_poly(int argc, VALUE *argv, VALUE self) { - VALUE approx_poly_option, storage; + VALUE approx_poly_option; rb_scan_args(argc, argv, "01", &approx_poly_option); approx_poly_option = APPROX_POLY_OPTION(approx_poly_option); - storage = cCvMemStorage::new_object(); - /* - CvSeq *contour = cvApproxPoly(CVCONTOUR(self), sizeof(CvContour), CVMEMSTORAGE(storage), - APPROX_POLY_METHOD(approx_poly_option), - APPROX_POLY_ACCURACY(approx_poly_option), - APPROX_POLY_RECURSIVE(approx_poly_option)); + VALUE storage = cCvMemStorage::new_object(); + CvSeq *contour = cvApproxPoly(CVCONTOUR(self), sizeof(CvContour), CVMEMSTORAGE(storage), + APPROX_POLY_METHOD(approx_poly_option), + APPROX_POLY_PARAMETER(approx_poly_option), + APPROX_POLY_PARAMETER2(approx_poly_option)); + + if (contour && contour->total > 0) { return cCvSeq::new_sequence(cCvContour::rb_class(), contour, cCvPoint::rb_class(), storage); - */ + } return Qnil; } diff --git a/test/test_cvcontour.rb b/test/test_cvcontour.rb index 57dd53b..6758f7c 100755 --- a/test/test_cvcontour.rb +++ b/test/test_cvcontour.rb @@ -10,8 +10,8 @@ include OpenCV class TestCvContour < OpenCVTestCase def test_APPROX_OPTION assert_equal(0, CvContour::APPROX_OPTION[:method]) - assert_equal(1.0, CvContour::APPROX_OPTION[:accuracy]) - assert_false(CvContour::APPROX_OPTION[:recursive]) + assert_equal(1.0, CvContour::APPROX_OPTION[:parameter]) + assert_false(CvContour::APPROX_OPTION[:parameter2]) end def test_initialize @@ -41,7 +41,46 @@ class TestCvContour < OpenCVTestCase end def test_approx_poly - flunk('FIXME: CvContour#approx_poly is not implemented yet.') + mat0 = create_cvmat(128, 128, :cv8u, 1) { |j, i| + (j - 64) ** 2 + (i - 64) ** 2 <= (32 ** 2) ? CvColor::White : CvColor::Black + } + contours = mat0.find_contours(:mode => CV_RETR_EXTERNAL) + + poly = contours.approx_poly + assert_equal(CvContour, poly.class) + assert(poly.size > 0) + assert(poly.all? { |c| c.class == CvPoint }) + + poly = contours.approx_poly(:method => :dp) + assert_equal(CvContour, poly.class) + assert(poly.size > 0) + assert(poly.all? { |c| c.class == CvPoint }) + + poly = contours.approx_poly(:parameter => 2.0) + assert_equal(CvContour, poly.class) + assert(poly.size > 0) + assert(poly.all? { |c| c.class == CvPoint }) + + [true, false, 1, 0].each { |recursive| + poly = contours.approx_poly(:recursive => recursive) + assert_equal(CvContour, poly.class) + assert(poly.size > 0) + assert(poly.all? { |c| c.class == CvPoint }) + } + + poly = contours.approx_poly(:method => :dp, :parameter => 2.0, :parameter2 => false) + assert_equal(CvContour, poly.class) + assert(poly.size > 0) + assert(poly.all? { |c| c.class == CvPoint }) + + # Uncomment the following lines to show the result + # poly = contours.approx_poly(:parameter => 3.0) + # dst = mat0.clone.zero + # begin + # dst.draw_contours!(poly, CvColor::White, CvColor::Black, 2, + # :thickness => 1, :line_type => :aa) + # end while (poly = poly.h_next) + # snap dst end def test_bounding_rect