mirror of
https://github.com/ruby-opencv/ruby-opencv
synced 2023-03-27 23:22:12 -04:00
added CvMat.find_homography
This commit is contained in:
parent
ed69d8cea8
commit
440d27cdcb
5 changed files with 121 additions and 1 deletions
|
@ -320,6 +320,7 @@ void define_ruby_class()
|
|||
rb_define_method(rb_klass, "warp_affine", RUBY_METHOD_FUNC(rb_warp_affine), -1);
|
||||
rb_define_singleton_method(rb_klass, "rotation_matrix2D", RUBY_METHOD_FUNC(rb_rotation_matrix2D), 3);
|
||||
rb_define_method(rb_klass, "warp_perspective", RUBY_METHOD_FUNC(rb_warp_perspective), -1);
|
||||
rb_define_singleton_method(rb_klass, "find_homography", RUBY_METHOD_FUNC(rb_find_homograpy), -1);
|
||||
//rb_define_method(rb_klass, "get_perspective_transform", RUBY_METHOD_FUNC(rb_get_perspective_transform), -1);
|
||||
//rb_define_alias(rb_klass, "warp_perspective_q_matrix", "get_perspective_transform");
|
||||
rb_define_method(rb_klass, "remap", RUBY_METHOD_FUNC(rb_remap), -1);
|
||||
|
@ -3343,6 +3344,46 @@ rb_warp_affine(int argc, VALUE *argv, VALUE self)
|
|||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* CvMat.find_homograpy(<i>src_points, dst_points[,method = :all][,ransac_reproj_threshold = 0][,get_status = nil]</i>) -> cvmat
|
||||
*
|
||||
* Finds the perspective transformation between two planes.
|
||||
* <i>src_points:</i> Coordinates of the points in the original plane, 2xN, Nx2, 3xN or Nx3 1-channel array (the latter two are for representation in homogeneous coordinates), where N is the number of points. 1xN or Nx1 2- or 3-channel array can also be passed.
|
||||
* <i>dst_points:</i> Point coordinates in the destination plane, 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 2- or 3-channel array.
|
||||
* <i>method:</i> The method used to computed homography matrix; one of the following symbols:
|
||||
* :all - a regular method using all the points
|
||||
* :ransac - RANSAC-based robust method
|
||||
* :lmeds - Least-Median robust method
|
||||
* <i>ransac_reproj_threshold:</i> The maximum allowed reprojection error to treat a point pair as an inlier (used in the RANSAC method only). If src_points and dst_points are measured in pixels, it usually makes sense to set this parameter somewhere in the range 1 to 10.
|
||||
* <i>get_status</i> If true, the optional output mask set by a robust method (:ransac or :lmeds) is returned additionally.
|
||||
*/
|
||||
VALUE
|
||||
rb_find_homograpy(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE src_points, dst_points, method, ransac_reproj_threshold, get_status;
|
||||
rb_scan_args(argc, argv, "23", &src_points, &dst_points, &method, &ransac_reproj_threshold, &get_status);
|
||||
|
||||
VALUE homography = new_object(cvSize(3, 3), CV_32FC1);
|
||||
int _method = CVMETHOD("HOMOGRAPHY_CALC_METHOD", method, 0);
|
||||
double _ransac_reproj_threshold = NIL_P(ransac_reproj_threshold) ? 0.0 : NUM2DBL(ransac_reproj_threshold);
|
||||
|
||||
if ((_method != 0) && (!NIL_P(get_status)) && IF_BOOL(get_status, 1, 0, 0)) {
|
||||
CvMat *src = CVMAT(src_points);
|
||||
int num_points = MAX(src->rows, src->cols);
|
||||
VALUE status = new_object(cvSize(num_points, 1), CV_8UC1);
|
||||
cvFindHomography(src, CVMAT(dst_points), CVMAT(homography),
|
||||
_method, _ransac_reproj_threshold, CVMAT(status));
|
||||
return rb_assoc_new(homography, status);
|
||||
}
|
||||
else {
|
||||
cvFindHomography(CVMAT(src_points), CVMAT(dst_points), CVMAT(homography),
|
||||
_method, _ransac_reproj_threshold, NULL);
|
||||
return homography;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* CvMat.rotation_matrix2D(<i>center,angle,scale</i>) -> cvmat
|
||||
|
|
|
@ -181,6 +181,7 @@ VALUE rb_resize(int argc, VALUE *argv, VALUE self);
|
|||
VALUE rb_warp_affine(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_rotation_matrix2D(VALUE self, VALUE center, VALUE angle, VALUE scale);
|
||||
VALUE rb_warp_perspective(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_find_homograpy(int argc, VALUE *argv, VALUE self);
|
||||
//VALUE rb_perspective_transform();
|
||||
VALUE rb_remap(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_log_polar(int argc, VALUE *argv);
|
||||
|
|
|
@ -204,7 +204,14 @@ define_ruby_module()
|
|||
rb_define_const(rb_module, "WARP_FLAG", warp_flag);
|
||||
RESIST_CVMETHOD(warp_flag, "fill_outliers", CV_WARP_FILL_OUTLIERS);
|
||||
RESIST_CVMETHOD(warp_flag, "inverse_map", CV_WARP_INVERSE_MAP);
|
||||
|
||||
|
||||
VALUE homography_calc_method = rb_hash_new();
|
||||
/* {:all, :ransac, :lmeds}: Methods used to computed homography matrix */
|
||||
rb_define_const(rb_module, "HOMOGRAPHY_CALC_METHOD", homography_calc_method);
|
||||
RESIST_CVMETHOD(homography_calc_method, "all", 0);
|
||||
RESIST_CVMETHOD(homography_calc_method, "ransac", CV_RANSAC);
|
||||
RESIST_CVMETHOD(homography_calc_method, "lmeds", CV_LMEDS);
|
||||
|
||||
VALUE depth = rb_hash_new();
|
||||
/* {:cv8u, :cv8s, :cv16u, :cv16s, :cv32s, :cv32f, :cv64f}: Depth of each pixel. */
|
||||
rb_define_const(rb_module, "DEPTH", depth);
|
||||
|
|
|
@ -318,6 +318,72 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
}
|
||||
end
|
||||
|
||||
def test_find_homography
|
||||
# Nx2
|
||||
src = CvMat.new(4, 2, :cv32f, 1)
|
||||
dst = CvMat.new(4, 2, :cv32f, 1)
|
||||
|
||||
# Nx3 (Homogeneous coordinates)
|
||||
src2 = CvMat.new(4, 3, :cv32f, 1)
|
||||
dst2 = CvMat.new(4, 3, :cv32f, 1)
|
||||
|
||||
# Homography
|
||||
# <src> => <dst>
|
||||
# (0, 0) => (50, 0)
|
||||
# (255, 0) => (205, 0)
|
||||
# (255, 255) => (255, 220)
|
||||
# (0, 255) => (0, 275)
|
||||
[[0, 0], [255, 0], [255, 255], [0, 255]].each_with_index { |coord, i|
|
||||
src[i, 0] = coord[0]
|
||||
src[i, 1] = coord[1]
|
||||
|
||||
src2[i, 0] = coord[0] * 2
|
||||
src2[i, 1] = coord[1] * 2
|
||||
src2[i, 2] = 2
|
||||
}
|
||||
[[50, 0], [205, 0], [255, 220], [0, 275]].each_with_index { |coord, i|
|
||||
dst[i, 0] = coord[0]
|
||||
dst[i, 1] = coord[1]
|
||||
|
||||
dst2[i, 0] = coord[0] * 2
|
||||
dst2[i, 1] = coord[1] * 2
|
||||
dst2[i, 2] = 2
|
||||
}
|
||||
|
||||
mat1 = CvMat.find_homography(src, dst)
|
||||
mat2 = CvMat.find_homography(src, dst, :all)
|
||||
mat3 = CvMat.find_homography(src, dst, :ransac)
|
||||
mat4 = CvMat.find_homography(src, dst, :lmeds)
|
||||
mat5, status5 = CvMat.find_homography(src, dst, :ransac, 5, true)
|
||||
mat6, status6 = CvMat.find_homography(src, dst, :ransac, 5, true)
|
||||
mat7 = CvMat.find_homography(src, dst, :ransac, 5, false)
|
||||
mat8 = CvMat.find_homography(src, dst, :ransac, 5, nil)
|
||||
mat9 = CvMat.find_homography(src, dst, :all, 5, true)
|
||||
mat10, status10 = CvMat.find_homography(src2, dst2, :ransac, 5, true)
|
||||
|
||||
[mat1, mat2, mat3, mat4, mat5, mat6, mat7, mat8, mat9, mat10].each { |mat|
|
||||
assert_equal(3, mat.rows)
|
||||
assert_equal(3, mat.cols)
|
||||
assert_equal(:cv32f, mat.depth)
|
||||
assert_equal(1, mat.channel)
|
||||
[0.72430, -0.19608, 50.0,
|
||||
0.0, 0.62489, 0.0,
|
||||
0.00057, -0.00165, 1.0].each_with_index { |x, i|
|
||||
assert_in_delta(x, mat[i][0], 0.0001)
|
||||
}
|
||||
}
|
||||
|
||||
[status5, status6, status10].each { |status|
|
||||
assert_equal(1, status.rows)
|
||||
assert_equal(4, status.cols)
|
||||
assert_equal(:cv8u, status.depth)
|
||||
assert_equal(1, status.channel)
|
||||
4.times { |i|
|
||||
assert_in_delta(1.0, status[i][0], 0.0001)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_remap
|
||||
mat0 = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
||||
matx = CvMat.new(mat0.height, mat0.width, :cv32f, 1).clear
|
||||
|
|
|
@ -57,6 +57,11 @@ class TestOpenCV < OpenCVTestCase
|
|||
assert_equal(8, WARP_FLAG[:fill_outliers])
|
||||
assert_equal(16, WARP_FLAG[:inverse_map])
|
||||
|
||||
# Homography calculation methods
|
||||
assert_equal(0, HOMOGRAPHY_CALC_METHOD[:all])
|
||||
assert_equal(4, HOMOGRAPHY_CALC_METHOD[:lmeds])
|
||||
assert_equal(8, HOMOGRAPHY_CALC_METHOD[:ransac])
|
||||
|
||||
# Anti aliasing flags
|
||||
assert_equal(16, CONNECTIVITY[:aa])
|
||||
assert_equal(16, CONNECTIVITY[:anti_alias])
|
||||
|
|
Loading…
Reference in a new issue