1
0
Fork 0
mirror of https://github.com/ruby-opencv/ruby-opencv synced 2023-03-27 23:22:12 -04:00

implemented CvMat.find_fundamental_mat

This commit is contained in:
ser1zw 2011-04-17 04:32:43 +09:00
parent d5e7d1acea
commit b447c9d5c3
5 changed files with 262 additions and 1 deletions

View file

@ -402,6 +402,8 @@ void define_ruby_class()
RUBY_METHOD_FUNC(rb_find_fundamental_mat_ransac), -1); RUBY_METHOD_FUNC(rb_find_fundamental_mat_ransac), -1);
rb_define_singleton_method(rb_klass, "find_fundamental_mat_lmeds", rb_define_singleton_method(rb_klass, "find_fundamental_mat_lmeds",
RUBY_METHOD_FUNC(rb_find_fundamental_mat_lmeds), -1); RUBY_METHOD_FUNC(rb_find_fundamental_mat_lmeds), -1);
rb_define_singleton_method(rb_klass, "find_fundamental_mat",
RUBY_METHOD_FUNC(rb_find_fundamental_mat), -1);
rb_define_singleton_method(rb_klass, "compute_correspond_epilines", rb_define_singleton_method(rb_klass, "compute_correspond_epilines",
RUBY_METHOD_FUNC(rb_compute_correspond_epilines), 3); RUBY_METHOD_FUNC(rb_compute_correspond_epilines), 3);
@ -5111,6 +5113,58 @@ rb_find_fundamental_mat_lmeds(int argc, VALUE *argv, VALUE klass)
} }
} }
/*
* call-seq:
* CvMat.find_fundamental_mat(<i>points1, points2[,options = {}]</i>) -> fundamental_matrix(cvmat) or nil
*
* Calculates fundamental matrix from corresponding points.
* Size of the output fundamental matrix is 3x3 or 9x3 (7-point method may return up to 3 matrices)
*
* <i>points1</i> and <i>points2</i> should be 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 multi-channel matrix.
* <i>method<i> is method for computing the fundamental matrix
* - CV_FM_7POINT for a 7-point algorithm. (N = 7)
* - CV_FM_8POINT for an 8-point algorithm. (N >= 8)
* - CV_FM_RANSAC for the RANSAC algorithm. (N >= 8)
* - CV_FM_LMEDS for the LMedS algorithm. (N >= 8)
* <i>option</i> 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 parameter is used for RANSAC. It is 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. It can be set to something like 1-3, depending on the accuracy of the point localization, image resolution and the image noise.
* :desirable_level
* The optional output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in RANSAC and LMedS methods. For other methods it is set to all 1's.
*
* note: <i>option</i>'s default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION.
*/
VALUE
rb_find_fundamental_mat(int argc, VALUE *argv, VALUE klass)
{
VALUE points1, points2, method, option, fundamental_matrix, status;
int num = 0;
rb_scan_args(argc, argv, "31", &points1, &points2, &method, &option);
option = FIND_FUNDAMENTAL_MAT_OPTION(option);
int fm_method = FIX2INT(method);
if (fm_method == CV_FM_7POINT)
fundamental_matrix = cCvMat::new_object(9, 3, CVMAT(points1)->type);
else
fundamental_matrix = cCvMat::new_object(3, 3, CVMAT(points1)->type);
if (FFM_WITH_STATUS(option)) {
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), fm_method,
FFM_MAXIMUM_DISTANCE(option), 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), fm_method,
FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL);
return num == 0 ? Qnil : fundamental_matrix;
}
}
/* /*
* call-seq: * call-seq:
* CvMat.compute_correspond_epilines(<i>points, which_image, fundamental_matrix</i>) -> correspondent_lines(cvmat) * CvMat.compute_correspond_epilines(<i>points, which_image, fundamental_matrix</i>) -> correspondent_lines(cvmat)

View file

@ -263,6 +263,7 @@ VALUE rb_find_fundamental_mat_7point(VALUE klass, VALUE points1, VALUE points2);
VALUE rb_find_fundamental_mat_8point(VALUE klass, VALUE points1, VALUE points2); VALUE rb_find_fundamental_mat_8point(VALUE klass, VALUE points1, VALUE points2);
VALUE rb_find_fundamental_mat_ransac(int argc, VALUE *argv, VALUE klass); VALUE rb_find_fundamental_mat_ransac(int argc, VALUE *argv, VALUE klass);
VALUE rb_find_fundamental_mat_lmeds(int argc, VALUE *argv, VALUE klass); VALUE rb_find_fundamental_mat_lmeds(int argc, VALUE *argv, VALUE klass);
VALUE rb_find_fundamental_mat(int argc, VALUE *argv, VALUE klass);
VALUE rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_image, VALUE fundamental_matrix); VALUE rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_image, VALUE fundamental_matrix);
// HighGUI function // HighGUI function

View file

@ -256,6 +256,12 @@ define_ruby_module()
rb_define_const(rb_module, "CV_CONTOURS_MATCH_I1", INT2FIX(CV_CONTOURS_MATCH_I1)); rb_define_const(rb_module, "CV_CONTOURS_MATCH_I1", INT2FIX(CV_CONTOURS_MATCH_I1));
rb_define_const(rb_module, "CV_CONTOURS_MATCH_I2", INT2FIX(CV_CONTOURS_MATCH_I2)); rb_define_const(rb_module, "CV_CONTOURS_MATCH_I2", INT2FIX(CV_CONTOURS_MATCH_I2));
rb_define_const(rb_module, "CV_CONTOURS_MATCH_I3", INT2FIX(CV_CONTOURS_MATCH_I3)); rb_define_const(rb_module, "CV_CONTOURS_MATCH_I3", INT2FIX(CV_CONTOURS_MATCH_I3));
/* Fundamental matrix computing methods */
rb_define_const(rb_module, "CV_FM_7POINT", INT2FIX(CV_FM_7POINT));
rb_define_const(rb_module, "CV_FM_8POINT", INT2FIX(CV_FM_8POINT));
rb_define_const(rb_module, "CV_FM_RANSAC", INT2FIX(CV_FM_RANSAC));
rb_define_const(rb_module, "CV_FM_LMEDS", INT2FIX(CV_FM_LMEDS));
VALUE inversion_method = rb_hash_new(); VALUE inversion_method = rb_hash_new();
/* {:lu, :svd, :svd_sym(:svd_symmetric)}: Inversion method */ /* {:lu, :svd, :svd_sym(:svd_symmetric)}: Inversion method */

View file

@ -2087,6 +2087,200 @@ class TestCvMat < OpenCVTestCase
assert_in_delta(val, status[i][0], 1.0e-5) assert_in_delta(val, status[i][0], 1.0e-5)
} }
end end
def test_find_fundamental_mat
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],
[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],
[475.84, 94.6777],
[421.16, 90.3223],
[368.5, 87.5]]
# 7 point
num_points = 7
mat1 = CvMat.new(num_points, 2, :cv64f, 1)
mat2 = CvMat.new(num_points, 2, :cv64f, 1)
points1[0...num_points].each_with_index { |pt, i|
mat1[i, 0] = CvScalar.new(pt[0])
mat1[i, 1] = CvScalar.new(pt[1])
}
points2[0...num_points].each_with_index { |pt, i|
mat2[i, 0] = CvScalar.new(pt[0])
mat2[i, 1] = CvScalar.new(pt[1])
}
f_mat1 = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_7POINT)
f_mat2, status = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_7POINT, :with_status => true)
expected = [0.000009, 0.000029, -0.010343,
-0.000033, 0.000000, 0.014590,
0.004415, -0.013420, 1.000000,
0.000000, 0.000001, -0.000223,
-0.000001, 0.000036, -0.005309,
-0.000097, -0.006463, 1.000000,
0.000002, 0.000005, -0.001621,
-0.000005, 0.000031, -0.002559,
0.000527, -0.007424, 1.000000]
[f_mat1, f_mat2].each { |f_mat|
assert_equal(9, f_mat.rows)
assert_equal(3, f_mat.cols)
expected.each_with_index { |val, i|
assert_in_delta(val, f_mat[i][0], 1.0e-5)
}
}
assert_equal(num_points, status.cols)
num_points.times { |i|
assert_in_delta(1, status[i][0], 1.0e-5)
}
# 8 point
num_points = 8
mat1 = CvMat.new(num_points, 2, :cv64f, 1)
mat2 = CvMat.new(num_points, 2, :cv64f, 1)
points1[0...num_points].each_with_index { |pt, i|
mat1[i, 0] = CvScalar.new(pt[0])
mat1[i, 1] = CvScalar.new(pt[1])
}
points2[0...num_points].each_with_index { |pt, i|
mat2[i, 0] = CvScalar.new(pt[0])
mat2[i, 1] = CvScalar.new(pt[1])
}
f_mat1 = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_8POINT)
f_mat2, status = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_8POINT, :with_status => true)
expected = [0.000001, 0.000004, -0.001127,
-0.000005, 0.000038, -0.003778,
0.000819, -0.008325, 1.000000]
[f_mat1, f_mat2].each { |f_mat|
assert_equal(3, f_mat.rows)
assert_equal(3, f_mat.cols)
expected.each_with_index { |val, i|
assert_in_delta(val, f_mat[i][0], 1.0e-5)
}
}
assert_equal(num_points, status.cols)
num_points.times { |i|
assert_in_delta(1, status[i][0], 1.0e-5)
}
# RANSAC default
num_points = points1.size
mat1 = CvMat.new(num_points, 2, :cv64f, 1)
mat2 = CvMat.new(num_points, 2, :cv64f, 1)
points1[0...num_points].each_with_index { |pt, i|
mat1[i, 0] = CvScalar.new(pt[0])
mat1[i, 1] = CvScalar.new(pt[1])
}
points2[0...num_points].each_with_index { |pt, i|
mat2[i, 0] = CvScalar.new(pt[0])
mat2[i, 1] = CvScalar.new(pt[1])
}
[CvMat.find_fundamental_mat(mat1, mat2, CV_FM_RANSAC, :with_status => false,
:maximum_distance => 1.0, :desirable_level => 0.99),
CvMat.find_fundamental_mat(mat1, mat2, CV_FM_RANSAC)].each { |f_mat|
assert_equal(3, f_mat.rows)
assert_equal(3, f_mat.cols)
expected = [0.000010, 0.000039, -0.011141,
-0.000045, -0.000001, 0.019631,
0.004873, -0.017604, 1.000000]
expected.each_with_index { |val, i|
assert_in_delta(val, f_mat[i][0], 1.0e-5)
}
}
# RANSAC with options
f_mat, status = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_RANSAC, :with_status => true,
:maximum_distance => 2.0, :desirable_level => 0.8)
assert_equal(3, f_mat.rows)
assert_equal(3, f_mat.cols)
assert_equal(1, status.rows)
assert_equal(num_points, status.cols)
expected_f_mat = [0.000009, 0.000030, -0.010692,
-0.000039, 0.000000, 0.020567,
0.004779, -0.018064, 1.000000]
expected_f_mat.each_with_index { |val, i|
assert_in_delta(val, f_mat[i][0], 1.0e-5)
}
expected_status = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
expected_status.each_with_index { |val, i|
assert_in_delta(val, status[i][0], 1.0e-5)
}
# LMedS default
num_points = 12
mat1 = CvMat.new(num_points, 2, :cv64f, 1)
mat2 = CvMat.new(num_points, 2, :cv64f, 1)
points1[0...num_points].each_with_index { |pt, i|
mat1[i, 0] = CvScalar.new(pt[0])
mat1[i, 1] = CvScalar.new(pt[1])
}
points2[0...num_points].each_with_index { |pt, i|
mat2[i, 0] = CvScalar.new(pt[0])
mat2[i, 1] = CvScalar.new(pt[1])
}
[CvMat.find_fundamental_mat(mat1, mat2, CV_FM_LMEDS, :with_status => false,
:maximum_distance => 1.0, :desirable_level => 0.99),
CvMat.find_fundamental_mat(mat1, mat2, CV_FM_LMEDS)].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)
}
}
# LMedS with options
f_mat, status = CvMat.find_fundamental_mat(mat1, mat2, CV_FM_LMEDS, :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(num_points, 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 end

View file

@ -93,6 +93,12 @@ class TestOpenCV < OpenCVTestCase
assert_equal(1, CV_CONTOURS_MATCH_I1) assert_equal(1, CV_CONTOURS_MATCH_I1)
assert_equal(2, CV_CONTOURS_MATCH_I2) assert_equal(2, CV_CONTOURS_MATCH_I2)
assert_equal(3, CV_CONTOURS_MATCH_I3) assert_equal(3, CV_CONTOURS_MATCH_I3)
# Fundamental matrix computing methods
assert_equal(1, CV_FM_7POINT)
assert_equal(2, CV_FM_8POINT)
assert_equal(8, CV_FM_RANSAC)
assert_equal(4, CV_FM_LMEDS)
end end
def test_symbols def test_symbols