From 197d5b92fd41cb523b14092f466210cf7e8c6eb4 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Fri, 2 Jan 2015 03:12:52 +0900 Subject: [PATCH] add CvMat#norm --- ext/opencv/cvmat.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ ext/opencv/cvmat.h | 2 +- test/test_cvmat.rb | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index e1cbfdf..8129dbe 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -2276,6 +2276,47 @@ rb_min_max_loc(int argc, VALUE *argv, VALUE self) return rb_ary_new3(4, rb_float_new(min_val), rb_float_new(max_val), min_loc, max_loc); } +/* + * Calculates an absolute array norm, an absolute difference norm, or a relative difference norm. + * + * @overload norm(src1, src2=nil, norm_type=NORM_L2, mask=nil) + * @param src1 [CvMat] First input array. + * @param src2 [CvMat] Second input array of the same size and the same type as src1. + * @param norm_type [Integer] Type of the norm. + * @param mask [CvMat] Optional operation mask; it must have the same size as src1 and CV_8UC1 type. + * @return [Number] The norm of two arrays. + * @opencv_func cvNorm + * @scope class + */ +VALUE +rb_norm(int argc, VALUE *argv, VALUE self) +{ + VALUE src1, src2, norm_type_val, mask_val; + rb_scan_args(argc, argv, "13", &src1, &src2, &norm_type_val, &mask_val); + + CvMat *src1_ptr = NULL; + CvMat *src2_ptr = NULL; + int norm_type = NIL_P(norm_type_val) ? cv::NORM_L2 : NUM2INT(norm_type_val); + CvMat *mask = NULL; + double norm = 0.0; + + try { + src1_ptr = CVMAT_WITH_CHECK(src1); + if (!NIL_P(src2)) { + src2_ptr = CVMAT_WITH_CHECK(src2); + } + if (!NIL_P(mask_val)) { + mask = CVMAT_WITH_CHECK(mask_val); + } + norm = cvNorm(src1_ptr, src2_ptr, norm_type, mask); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return DBL2NUM(norm); +} + /* * Calculates the dot product of two arrays in Euclidean metrics. * @@ -5913,6 +5954,7 @@ init_ruby_class() rb_define_method(rb_klass, "avg_sdv", RUBY_METHOD_FUNC(rb_avg_sdv), -1); rb_define_method(rb_klass, "sdv", RUBY_METHOD_FUNC(rb_sdv), -1); rb_define_method(rb_klass, "min_max_loc", RUBY_METHOD_FUNC(rb_min_max_loc), -1); + rb_define_singleton_method(rb_klass, "norm", RUBY_METHOD_FUNC(rb_norm), -1); rb_define_method(rb_klass, "dot_product", RUBY_METHOD_FUNC(rb_dot_product), 1); rb_define_method(rb_klass, "cross_product", RUBY_METHOD_FUNC(rb_cross_product), 1); rb_define_method(rb_klass, "transform", RUBY_METHOD_FUNC(rb_transform), -1); diff --git a/ext/opencv/cvmat.h b/ext/opencv/cvmat.h index 2046040..168c280 100644 --- a/ext/opencv/cvmat.h +++ b/ext/opencv/cvmat.h @@ -119,7 +119,7 @@ VALUE rb_avg_sdv(int argc, VALUE *argv, VALUE self); VALUE rb_sdv(int argc, VALUE *argv, VALUE self); VALUE rb_min_max_loc(int argc, VALUE *argv, VALUE self); -//VALUE rb_norm(); +VALUE rb_norm(int argc, VALUE *argv, VALUE self); VALUE rb_dot_product(VALUE self, VALUE mat); VALUE rb_cross_product(VALUE self, VALUE mat); // VALUE rb_gemm(); diff --git a/test/test_cvmat.rb b/test/test_cvmat.rb index 9d1274d..0187551 100755 --- a/test/test_cvmat.rb +++ b/test/test_cvmat.rb @@ -2161,6 +2161,39 @@ class TestCvMat < OpenCVTestCase } end + def test_norm + src1 = CvMat.new(3, 3, :cv32f, 1).set_data([1, 2, 3, 4, 5, 6, 7, 8, 9]) + src2 = CvMat.new(3, 3, :cv32f, 1).set_data([2, 3, 4, 5, 6, 7, 8, 9, 1]) + mask = CvMat.new(3, 3, :cv8u, 1).set_data([1, 1, 0, 1, 1, 0, 0, 0, 0]) + + assert_in_delta(CvMat.norm(src1), 16.88, 0.01) + + assert_in_delta(CvMat.norm(src1, nil, CV_NORM_L1), 45.0, 0.01) + assert_in_delta(CvMat.norm(src1, nil, CV_NORM_L2), 16.88, 0.01) + assert_in_delta(CvMat.norm(src1, nil, CV_NORM_INF), 9.0, 0.01) + + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_L1), 16.0, 0.01) + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_L2), 8.49, 0.01) + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_INF), 8.0, 0.01) + + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_L1, mask), 4.0, 0.01) + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_L2, mask), 2.0, 0.01) + assert_in_delta(CvMat.norm(src1, src2, CV_NORM_INF, mask), 1.0, 0.01) + + assert_raise(TypeError) { + CvMat.norm(DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.norm(src1, DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.norm(src1, src2, DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.norm(src1, src2, CV_NORM_L1, DUMMY_OBJ) + } + end + def test_dot_product m1 = create_cvmat(2, 2, :cv32f, 1) { |j, i, c| CvScalar.new(c * 0.5)