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