From 9e79d09e74e72c6c57f150e6cf3f3a908995aeda Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 6 Mar 2011 03:45:45 +0900 Subject: [PATCH] implemented accessors of CvMoments, tested CvMoments --- ext/cvmoments.cpp | 70 +++++++++++++--- ext/cvmoments.h | 19 +++++ test/test_cvmoments.rb | 176 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 11 deletions(-) create mode 100755 test/test_cvmoments.rb diff --git a/ext/cvmoments.cpp b/ext/cvmoments.cpp index ae47dcf..49ee93e 100644 --- a/ext/cvmoments.cpp +++ b/ext/cvmoments.cpp @@ -16,6 +16,12 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVMOMENTS +#define DEFINE_CVMOMENTS_ACCESSOR(elem) \ + rb_define_method(rb_klass, #elem, RUBY_METHOD_FUNC(rb_##elem), 0) + +#define CVMOMENTS_ACCESSOR(elem) \ + VALUE rb_##elem(VALUE self) { return DBL2NUM(CVMOMENTS(self)->elem); } + VALUE rb_klass; VALUE @@ -44,8 +50,28 @@ define_ruby_class() rb_define_method(rb_klass, "normalized_central", RUBY_METHOD_FUNC(rb_normalized_central), 2); rb_define_method(rb_klass, "hu", RUBY_METHOD_FUNC(rb_hu), 0); rb_define_method(rb_klass, "gravity_center", RUBY_METHOD_FUNC(rb_gravity_center), 0); - rb_define_alias(rb_klass, "center", "gravity_center"); rb_define_method(rb_klass, "angle", RUBY_METHOD_FUNC(rb_angle), 0); + + DEFINE_CVMOMENTS_ACCESSOR(m00); + DEFINE_CVMOMENTS_ACCESSOR(m10); + DEFINE_CVMOMENTS_ACCESSOR(m01); + DEFINE_CVMOMENTS_ACCESSOR(m20); + DEFINE_CVMOMENTS_ACCESSOR(m11); + DEFINE_CVMOMENTS_ACCESSOR(m02); + DEFINE_CVMOMENTS_ACCESSOR(m30); + DEFINE_CVMOMENTS_ACCESSOR(m21); + DEFINE_CVMOMENTS_ACCESSOR(m12); + DEFINE_CVMOMENTS_ACCESSOR(m03); + + DEFINE_CVMOMENTS_ACCESSOR(mu20); + DEFINE_CVMOMENTS_ACCESSOR(mu11); + DEFINE_CVMOMENTS_ACCESSOR(mu02); + DEFINE_CVMOMENTS_ACCESSOR(mu30); + DEFINE_CVMOMENTS_ACCESSOR(mu21); + DEFINE_CVMOMENTS_ACCESSOR(mu12); + DEFINE_CVMOMENTS_ACCESSOR(mu03); + + DEFINE_CVMOMENTS_ACCESSOR(inv_sqrt_m00); } VALUE @@ -68,15 +94,37 @@ rb_initialize(int argc, VALUE *argv, VALUE self) { VALUE src, is_binary; rb_scan_args(argc, argv, "02", &src, &is_binary); - if (NIL_P(src)) - ; - else if (rb_obj_is_kind_of(src, cCvMat::rb_class()) || rb_obj_is_kind_of(src, cCvSeq::rb_class())) - cvMoments(CVARR(src), CVMOMENTS(self), TRUE_OR_FALSE(is_binary, 0)); - else - rb_raise(rb_eTypeError, "argument 1 (src) should be %s or %s.", rb_class2name(cCvMat::rb_class()), rb_class2name(cCvSeq::rb_class())); + if (!NIL_P(src)) { + if (rb_obj_is_kind_of(src, cCvMat::rb_class()) || rb_obj_is_kind_of(src, cCvSeq::rb_class())) + cvMoments(CVARR(src), CVMOMENTS(self), TRUE_OR_FALSE(is_binary, 0)); + else + rb_raise(rb_eTypeError, "argument 1 (src) should be %s or %s.", + rb_class2name(cCvMat::rb_class()), rb_class2name(cCvSeq::rb_class())); + } return self; } +CVMOMENTS_ACCESSOR(m00); +CVMOMENTS_ACCESSOR(m10); +CVMOMENTS_ACCESSOR(m01); +CVMOMENTS_ACCESSOR(m20); +CVMOMENTS_ACCESSOR(m11); +CVMOMENTS_ACCESSOR(m02); +CVMOMENTS_ACCESSOR(m30); +CVMOMENTS_ACCESSOR(m21); +CVMOMENTS_ACCESSOR(m12); +CVMOMENTS_ACCESSOR(m03); + +CVMOMENTS_ACCESSOR(mu20); +CVMOMENTS_ACCESSOR(mu11); +CVMOMENTS_ACCESSOR(mu02); +CVMOMENTS_ACCESSOR(mu30); +CVMOMENTS_ACCESSOR(mu21); +CVMOMENTS_ACCESSOR(mu12); +CVMOMENTS_ACCESSOR(mu03); + +CVMOMENTS_ACCESSOR(inv_sqrt_m00); + /* * call-seq: * spatial -> float @@ -186,17 +234,17 @@ rb_angle(VALUE self) m20 = cvGetCentralMoment(moments, 2, 0), m02 = cvGetCentralMoment(moments, 0, 2), mangle = 0.5 * atan(2 * m11 / (m20 - m02)); - if(!cvIsNaN(mangle) && !cvIsInf(mangle)) - return rb_float_new(mangle); - else + if(cvIsNaN(mangle) || cvIsInf(mangle)) return Qnil; + else + return rb_float_new(mangle); } VALUE new_object(CvArr *arr, int is_binary = 0) { VALUE object = rb_allocate(rb_class()); - cvMoments(arr, CVMOMENTS(object), TRUE_OR_FALSE(is_binary, 0)); + cvMoments(arr, CVMOMENTS(object), is_binary); return object; } diff --git a/ext/cvmoments.h b/ext/cvmoments.h index 9eda002..95d8fa9 100644 --- a/ext/cvmoments.h +++ b/ext/cvmoments.h @@ -31,6 +31,25 @@ VALUE rb_hu(VALUE self); VALUE rb_gravity_center(VALUE self); VALUE rb_angle(VALUE self); +VALUE rb_m00(VALUE self); +VALUE rb_m10(VALUE self); +VALUE rb_m01(VALUE self); +VALUE rb_m20(VALUE self); +VALUE rb_m11(VALUE self); +VALUE rb_m02(VALUE self); +VALUE rb_m30(VALUE self); +VALUE rb_m21(VALUE self); +VALUE rb_m12(VALUE self); +VALUE rb_m03(VALUE self); +VALUE rb_mu20(VALUE self); +VALUE rb_mu11(VALUE self); +VALUE rb_mu02(VALUE self); +VALUE rb_mu30(VALUE self); +VALUE rb_mu21(VALUE self); +VALUE rb_mu12(VALUE self); +VALUE rb_mu03(VALUE self); +VALUE rb_inv_sqrt_m00(VALUE self); + VALUE new_object(CvArr *arr, int is_binary); __NAMESPACE_END_CVMOMENTS diff --git a/test/test_cvmoments.rb b/test/test_cvmoments.rb new file mode 100755 index 0000000..3cdc052 --- /dev/null +++ b/test/test_cvmoments.rb @@ -0,0 +1,176 @@ +#!/usr/bin/env ruby +# -*- mode: ruby; coding: utf-8-unix -*- +require 'test/unit' +require 'opencv' +require File.expand_path(File.dirname(__FILE__)) + '/helper' + +include OpenCV + +# Tests for OpenCV::CvMoment +class TestCvMoments < OpenCVTestCase + def setup + @mat = create_cvmat(128, 128, :cv8u, 1) { |j, i| + if j >= 32 and j < 96 and i >= 16 and i < 112 + CvScalar.new(0) + elsif j >= 16 and j < 112 and i >= 16 and i < 112 + CvScalar.new(128) + else + CvScalar.new(255) + end + } + @moment1 = CvMoments.new + @moment2 = CvMoments.new(nil, true) + @moment3 = CvMoments.new(@mat) + @moment4 = CvMoments.new(@mat, true) + end + + def test_initialize + [@moment1, @moment2, @moment3, @moment4].each { |m| + assert_not_nil(m) + assert_equal(CvMoments, m.class) + } + + assert_raise(TypeError) { + CvMoments.new('foo') + } + end + + def test_spatial + assert_in_delta(0, @moment1.spatial(0, 0), 0.1) + assert_in_delta(0, @moment2.spatial(0, 0), 0.1) + assert_in_delta(2221056, @moment3.spatial(0, 0), 0.1) + assert_in_delta(10240, @moment4.spatial(0, 0), 0.1) + end + + def test_central + assert_in_delta(0, @moment1.central(0, 0), 0.1) + assert_in_delta(0, @moment2.central(0, 0), 0.1) + assert_in_delta(2221056, @moment3.central(0, 0), 0.1) + assert_in_delta(10240, @moment4.central(0, 0), 0.1) + end + + def test_normalized_central + assert_in_delta(0, @moment1.normalized_central(0, 0), 0.1) + assert_in_delta(0, @moment2.normalized_central(0, 0), 0.1) + assert_in_delta(1, @moment3.normalized_central(0, 0), 0.1) + assert_in_delta(1, @moment4.normalized_central(0, 0), 0.1) + end + + def test_hu + hu_moments = @moment1.hu + hu_moments.each { |hu| + assert_in_delta(0.0, hu, 0.000001) + } + + hu_moments = @moment2.hu + hu_moments.each { |hu| + assert_in_delta(0.0, hu, 0.000001) + } + + hu_moments = @moment3.hu + assert_in_delta(0.001771, hu_moments[0], 0.000001) + hu_moments[1..7].each { |hu| + assert_in_delta(0.0, hu, 0.000001) + } + + hu_moments = @moment4.hu + assert_in_delta(0.361650, hu_moments[0], 0.000001) + assert_in_delta(0.000625, hu_moments[1], 0.000001) + hu_moments[2..7].each { |hu| + assert_in_delta(0.0, hu, 0.000001) + } + end + + def test_gravity_center + center = @moment1.gravity_center + assert_equal(CvPoint2D32f, center.class) + assert(center.x.nan?) + assert(center.y.nan?) + + center = @moment2.gravity_center + assert_equal(CvPoint2D32f, center.class) + assert(center.x.nan?) + assert(center.y.nan?) + + center = @moment3.gravity_center + assert_equal(CvPoint2D32f, center.class) + assert_in_delta(63.5, center.x, 0.001) + assert_in_delta(63.5, center.y, 0.001) + + center = @moment4.gravity_center + assert_equal(CvPoint2D32f, center.class) + assert_in_delta(63.5, center.x, 0.001) + assert_in_delta(63.5, center.y, 0.001) + end + + def test_angle + [@moment1, @moment2].each { |m| + assert_nil(m.angle) + } + [@moment3, @moment4].each { |m| + assert_in_delta(0, m.angle, 0.001) + } + end + + def test_mXX + [@moment1, @moment2].each { |m| + assert_in_delta(0, m.m00, 0.001) + assert_in_delta(0, m.m10, 0.001) + assert_in_delta(0, m.m01, 0.001) + assert_in_delta(0, m.m20, 0.001) + assert_in_delta(0, m.m11, 0.001) + assert_in_delta(0, m.m02, 0.001) + assert_in_delta(0, m.m30, 0.001) + assert_in_delta(0, m.m21, 0.001) + assert_in_delta(0, m.m12, 0.001) + assert_in_delta(0, m.m03, 0.001) + assert_in_delta(0, m.mu20, 0.001) + assert_in_delta(0, m.mu11, 0.001) + assert_in_delta(0, m.mu02, 0.001) + assert_in_delta(0, m.mu30, 0.001) + assert_in_delta(0, m.mu21, 0.001) + assert_in_delta(0, m.mu12, 0.001) + assert_in_delta(0, m.mu03, 0.001) + assert_in_delta(0, m.inv_sqrt_m00, 0.001) + } + + assert_in_delta(2221056, @moment3.m00, 0.001) + assert_in_delta(141037056, @moment3.m10, 0.001) + assert_in_delta(141037056, @moment3.m01, 0.001) + assert_in_delta(13157049856, @moment3.m20, 0.001) + assert_in_delta(8955853056, @moment3.m11, 0.001) + assert_in_delta(13492594176, @moment3.m02, 0.001) + assert_in_delta(1369024659456, @moment3.m30, 0.001) + assert_in_delta(835472665856, @moment3.m21, 0.001) + assert_in_delta(856779730176, @moment3.m12, 0.001) + assert_in_delta(1432945852416, @moment3.m03, 0.001) + assert_in_delta(4201196800, @moment3.mu20, 0.001) + assert_in_delta(0, @moment3.mu11, 0.001) + assert_in_delta(4536741120, @moment3.mu02, 0.001) + assert_in_delta(0, @moment3.mu30, 0.001) + assert_in_delta(0, @moment3.mu21, 0.001) + assert_in_delta(0, @moment3.mu12, 0.001) + assert_in_delta(0, @moment3.mu03, 0.001) + assert_in_delta(0.000671, @moment3.inv_sqrt_m00, 0.000001) + + assert_in_delta(10240, @moment4.m00, 0.001) + assert_in_delta(650240, @moment4.m10, 0.001) + assert_in_delta(650240, @moment4.m01, 0.001) + assert_in_delta(58940416, @moment4.m20, 0.001) + assert_in_delta(41290240, @moment4.m11, 0.001) + assert_in_delta(61561856, @moment4.m02, 0.001) + assert_in_delta(5984288768, @moment4.m30, 0.001) + assert_in_delta(3742716416, @moment4.m21, 0.001) + assert_in_delta(3909177856, @moment4.m12, 0.001) + assert_in_delta(6483673088, @moment4.m03, 0.001) + assert_in_delta(17650176, @moment4.mu20, 0.001) + assert_in_delta(0, @moment4.mu11, 0.001) + assert_in_delta(20271616, @moment4.mu02, 0.001) + assert_in_delta(0, @moment4.mu30, 0.001) + assert_in_delta(0, @moment4.mu21, 0.001) + assert_in_delta(0, @moment4.mu12, 0.001) + assert_in_delta(0, @moment4.mu03, 0.001) + assert_in_delta(0.009882, @moment4.inv_sqrt_m00, 0.000001) + end +end +