1
0
Fork 0
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:
ser1zw 2011-01-21 03:20:10 +09:00
parent ed69d8cea8
commit 440d27cdcb
5 changed files with 121 additions and 1 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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])