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:
parent
d5e7d1acea
commit
b447c9d5c3
5 changed files with 262 additions and 1 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue