From d5e7d1acea09b5bac3bc88a899625d142fd05757 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 17 Apr 2011 03:42:19 +0900 Subject: [PATCH] tested CvMat.find_fundamental_mat_lmeds --- ext/opencv/cvmat.cpp | 17 ++++++----- test/test_cvmat.rb | 73 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index 344551f..db40c16 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -5079,14 +5079,11 @@ rb_find_fundamental_mat_ransac(int argc, VALUE *argv, VALUE klass) * CvMat.find_fundamental_mat_lmeds(points1, points2[,options = {}]) -> fundamental_matrix(cvmat) or nil * * Calculates fundamental matrix from corresponding points, use for LMedS algorism. - * points1 and points2 should be 2x7 or 3x7 single-channel, or 1x7 multi-channel matrix. + * points1 and points2 should be 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 multi-channel matrix (N >= 8). * option should be Hash include these keys. * :with_status (true or false) * If set true, return fundamental_matrix and status. [fundamental_matrix, status] * Otherwise return fundamental matrix only(default). - * :maximum_distance - * The maximum distance from point to epipolar line in pixels, beyond which the point is considered an outlier - * and is not used for computing the final fundamental matrix. Usually it is set to 0.5 or 1.0. * :desirable_level * It denotes the desirable level of confidence that the matrix is correct. * @@ -5099,13 +5096,17 @@ rb_find_fundamental_mat_lmeds(int argc, VALUE *argv, VALUE klass) int num = 0; rb_scan_args(argc, argv, "21", &points1, &points2, &option); option = FIND_FUNDAMENTAL_MAT_OPTION(option); - fundamental_matrix = cCvMat::new_object(3, 3, CV_32FC1); + fundamental_matrix = cCvMat::new_object(3, 3, CVMAT(points1)->type); if(FFM_WITH_STATUS(option)){ - status = cCvMat::new_object(cvGetSize(CVARR(points1)), CV_8UC1); - num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), CVMAT(status)); + CvMat *points1_ptr = CVMAT(points1); + int status_len = (points1_ptr->rows > points1_ptr->cols) ? points1_ptr->rows : points1_ptr->cols; + status = cCvMat::new_object(1, status_len, CV_8UC1); + num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, + 0, FFM_DESIRABLE_LEVEL(option), CVMAT(status)); return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status); }else{ - num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL); + num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, + 0, FFM_DESIRABLE_LEVEL(option), NULL); return num == 0 ? Qnil : fundamental_matrix; } } diff --git a/test/test_cvmat.rb b/test/test_cvmat.rb index 9fcba43..6aad3d4 100755 --- a/test/test_cvmat.rb +++ b/test/test_cvmat.rb @@ -2014,6 +2014,79 @@ class TestCvMat < OpenCVTestCase assert_in_delta(val, status[i][0], 1.0e-5) } end + + def test_find_fundamental_mat_lmeds + points1 = [[488.362, 169.911], + [449.488, 174.44], + [408.565, 179.669], + [364.512, 184.56], + [491.483, 122.366], + [451.512, 126.56], + [409.502, 130.342], + [365.5, 134.0], + [494.335, 74.544], + [453.5, 76.5], + [411.646, 79.5901], + [366.498, 81.6577]] + points2 = [[526.605, 213.332], + [470.485, 207.632], + [417.5, 201.0], + [367.485, 195.632], + [530.673, 156.417], + [473.749, 151.39], + [419.503, 146.656], + [368.669, 142.565], + [534.632, 97.5152], + [475.84, 94.6777], + [421.16, 90.3223], + [368.5, 87.5]] + + mat1 = CvMat.new(points1.size, 2, :cv64f, 1) + mat2 = CvMat.new(points2.size, 2, :cv64f, 1) + + points1.each_with_index { |pt, i| + mat1[i, 0] = CvScalar.new(pt[0]) + mat1[i, 1] = CvScalar.new(pt[1]) + } + points2.each_with_index { |pt, i| + mat2[i, 0] = CvScalar.new(pt[0]) + mat2[i, 1] = CvScalar.new(pt[1]) + } + + # default + [CvMat.find_fundamental_mat_lmeds(mat1, mat2, :with_status => false, + :maximum_distance => 1.0, :desirable_level => 0.99), + CvMat.find_fundamental_mat_lmeds(mat1, mat2)].each { |f_mat| + assert_equal(3, f_mat.rows) + assert_equal(3, f_mat.cols) + expected = [0.000009, -0.000129, -0.008502, + 0.000183, -0.000004, -0.106088, + 0.002575, 0.090291, 1.000000] + expected.each_with_index { |val, i| + assert_in_delta(val, f_mat[i][0], 1.0e-5) + } + } + + # with options + f_mat, status = CvMat.find_fundamental_mat_lmeds(mat1, mat2, :with_status => true, + :desirable_level => 0.8) + assert_equal(3, f_mat.rows) + assert_equal(3, f_mat.cols) + assert_equal(1, status.rows) + assert_equal(points1.size, status.cols) + + expected_f_mat = [0.000009, -0.000129, -0.008502, + 0.000183, -0.000004, -0.106088, + 0.002575, 0.090291, 1.000000] + expected_f_mat.each_with_index { |val, i| + assert_in_delta(val, f_mat[i][0], 1.0e-5) + } + expected_status = [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1] + + expected_status.each_with_index { |val, i| + assert_in_delta(val, status[i][0], 1.0e-5) + } + end end