add CvMat#snake_image (only for OpenCV 2)
This commit is contained in:
parent
65999bf534
commit
33e96195e2
|
@ -14,6 +14,7 @@
|
|||
|
||||
#ifdef IS_OPENCV2
|
||||
# include "opencv2/contrib/contrib.hpp"
|
||||
# include "opencv2/legacy/legacy.hpp"
|
||||
#else
|
||||
# include "opencv2/video/tracking_c.h"
|
||||
# include "opencv2/calib3d/calib3d_c.h"
|
||||
|
@ -5606,6 +5607,95 @@ namespace mOpenCV {
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* snake_image(points, alpha, beta, gamma, window, criteria[, calc_gradient = true]) -> array(pointset)
|
||||
*
|
||||
* Updates snake in order to minimize its total energy that is a sum of internal energy
|
||||
* that depends on contour shape (the smoother contour is, the smaller internal energy is)
|
||||
* and external energy that depends on the energy field and reaches minimum at the local energy
|
||||
* extremums that correspond to the image edges in case of image gradient.
|
||||
|
||||
* The parameter criteria.epsilon is used to define the minimal number of points that must be moved
|
||||
* during any iteration to keep the iteration process running.
|
||||
*
|
||||
* If at some iteration the number of moved points is less than criteria.epsilon or
|
||||
* the function performed criteria.max_iter iterations, the function terminates.
|
||||
*
|
||||
* points
|
||||
* Contour points (snake).
|
||||
* alpha
|
||||
* Weight[s] of continuity energy, single float or array of length floats, one per each contour point.
|
||||
* beta
|
||||
* Weight[s] of curvature energy, similar to alpha.
|
||||
* gamma
|
||||
* Weight[s] of image energy, similar to alpha.
|
||||
* window
|
||||
* Size of neighborhood of every point used to search the minimum, both win.width and win.height must be odd.
|
||||
* criteria
|
||||
* Termination criteria.
|
||||
* calc_gradient
|
||||
* Gradient flag. If not 0, the function calculates gradient magnitude for every image pixel and consideres
|
||||
* it as the energy field, otherwise the input image itself is considered.
|
||||
*/
|
||||
VALUE
|
||||
rb_snake_image(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
#ifdef IS_OPENCV2
|
||||
VALUE points, alpha, beta, gamma, window, criteria, calc_gradient;
|
||||
rb_scan_args(argc, argv, "61", &points, &alpha, &beta, &gamma, &window, &criteria, &calc_gradient);
|
||||
CvPoint *pointset = 0;
|
||||
int length = CVPOINTS_FROM_POINT_SET(points, &pointset);
|
||||
int coeff = (TYPE(alpha) == T_ARRAY && TYPE(beta) == T_ARRAY && TYPE(gamma) == T_ARRAY) ? CV_ARRAY : CV_VALUE;
|
||||
float *a = 0, *b = 0, *c = 0;
|
||||
IplImage stub;
|
||||
int i;
|
||||
if (coeff == CV_VALUE) {
|
||||
float buff_a, buff_b, buff_c;
|
||||
buff_a = (float)NUM2DBL(alpha);
|
||||
buff_b = (float)NUM2DBL(beta);
|
||||
buff_c = (float)NUM2DBL(gamma);
|
||||
a = &buff_a;
|
||||
b = &buff_b;
|
||||
c = &buff_c;
|
||||
}
|
||||
else { // CV_ARRAY
|
||||
if ((RARRAY_LEN(alpha) != length) ||
|
||||
(RARRAY_LEN(beta) != length) ||
|
||||
(RARRAY_LEN(gamma) != length))
|
||||
rb_raise(rb_eArgError, "alpha, beta, gamma should be same size of points");
|
||||
a = ALLOCA_N(float, length);
|
||||
b = ALLOCA_N(float, length);
|
||||
c = ALLOCA_N(float, length);
|
||||
for (i = 0; i < length; ++i) {
|
||||
a[i] = (float)NUM2DBL(RARRAY_PTR(alpha)[i]);
|
||||
b[i] = (float)NUM2DBL(RARRAY_PTR(beta)[i]);
|
||||
c[i] = (float)NUM2DBL(RARRAY_PTR(gamma)[i]);
|
||||
}
|
||||
}
|
||||
CvSize win = VALUE_TO_CVSIZE(window);
|
||||
CvTermCriteria tc = VALUE_TO_CVTERMCRITERIA(criteria);
|
||||
try {
|
||||
cvSnakeImage(cvGetImage(CVARR(self), &stub), pointset, length,
|
||||
a, b, c, coeff, win, tc, IF_BOOL(calc_gradient, 1, 0, 1));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
if (pointset != NULL)
|
||||
cvFree(&pointset);
|
||||
raise_cverror(e);
|
||||
}
|
||||
VALUE result = rb_ary_new2(length);
|
||||
for (i = 0; i < length; ++i)
|
||||
rb_ary_push(result, cCvPoint::new_object(pointset[i]));
|
||||
cvFree(&pointset);
|
||||
|
||||
return result;
|
||||
#else
|
||||
raise_opencv3_unsupported();
|
||||
return Qnil;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_ruby_class()
|
||||
{
|
||||
|
@ -5862,6 +5952,7 @@ namespace mOpenCV {
|
|||
|
||||
rb_define_method(rb_klass, "mean_shift", RUBY_METHOD_FUNC(rb_mean_shift), 2);
|
||||
rb_define_method(rb_klass, "cam_shift", RUBY_METHOD_FUNC(rb_cam_shift), 2);
|
||||
rb_define_method(rb_klass, "snake_image", RUBY_METHOD_FUNC(rb_snake_image), -1);
|
||||
|
||||
rb_define_singleton_method(rb_klass, "find_fundamental_mat",
|
||||
RUBY_METHOD_FUNC(rb_find_fundamental_mat), -1);
|
||||
|
|
|
@ -225,7 +225,7 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
[39, 159], [79, 159], [119, 159], [159, 159]]
|
||||
|
||||
refined_corners = mat.find_corner_sub_pix(corners, CvSize.new(3, 3), CvSize.new(-1, -1),
|
||||
CvTermCriteria.new(20, 0.03));
|
||||
CvTermCriteria.new(20, 0.03));
|
||||
assert_equal(expected.size, refined_corners.size)
|
||||
assert(found)
|
||||
expected.zip(refined_corners).each { |e, a|
|
||||
|
@ -440,10 +440,10 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
|
||||
def test_get_perspective_transform
|
||||
from = [
|
||||
OpenCV::CvPoint2D32f.new(540, 382),
|
||||
OpenCV::CvPoint2D32f.new(802, 400),
|
||||
OpenCV::CvPoint2D32f.new(850, 731),
|
||||
OpenCV::CvPoint2D32f.new(540, 731),
|
||||
OpenCV::CvPoint2D32f.new(540, 382),
|
||||
OpenCV::CvPoint2D32f.new(802, 400),
|
||||
OpenCV::CvPoint2D32f.new(850, 731),
|
||||
OpenCV::CvPoint2D32f.new(540, 731),
|
||||
]
|
||||
to = [
|
||||
OpenCV::CvPoint2D32f.new(0, 0),
|
||||
|
@ -1741,4 +1741,99 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
assert_in_delta(0.0033327, mat_cv.match_shapes(mat_ov, method), 0.00001)
|
||||
}
|
||||
end
|
||||
|
||||
def test_snake_image
|
||||
omit_unless(IS_OPENCV2, 'CvMat#snake_image is not supported in OpenCV 3 or later')
|
||||
radius = 40
|
||||
center = CvPoint.new(128, 128)
|
||||
mat = CvMat.new(center.y * 2, center.x * 2, :cv8u, 1).zero!
|
||||
mat.circle!(center, radius, :color => CvColor::White, :thickness => -1)
|
||||
|
||||
num_points = 10
|
||||
alpha = 0.05
|
||||
beta = 0.05
|
||||
gamma = 0.9
|
||||
|
||||
arr_alpha = [alpha] * num_points
|
||||
arr_beta = [beta] * num_points
|
||||
arr_gamma = [gamma] * num_points
|
||||
size = CvSize.new(3, 3)
|
||||
term_criteria = CvTermCriteria.new(100, num_points / 2)
|
||||
|
||||
# initialize contours
|
||||
points = []
|
||||
num_points.times { |i|
|
||||
x = center.x * Math.cos(2 * Math::PI * i / num_points) + center.x
|
||||
y = center.y * Math.sin(2 * Math::PI * i / num_points) + center.y
|
||||
points << CvPoint.new(x, y)
|
||||
}
|
||||
|
||||
acceptable_error = 50
|
||||
|
||||
# test snake_image
|
||||
# calc_gradient = true
|
||||
[mat.snake_image(points, alpha, beta, gamma, size, term_criteria),
|
||||
mat.snake_image(points, alpha, beta, gamma, size, term_criteria, true),
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, size, term_criteria),
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, size, term_criteria, true)].each { |result|
|
||||
assert_equal(num_points, result.size)
|
||||
result.each { |pt|
|
||||
x = pt.x - center.x
|
||||
y = pt.y - center.y
|
||||
error = Math.sqrt((x * x + y * y - radius * radius).abs)
|
||||
assert(error < acceptable_error)
|
||||
}
|
||||
}
|
||||
|
||||
# calc_gradient = false
|
||||
[mat.snake_image(points, alpha, beta, gamma, size, term_criteria, false),
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, size, term_criteria, false)].each { |result|
|
||||
expected_points = [[149, 102], [139, 144], [95, 144], [56, 124], [17, 105],
|
||||
[25, 61], [63, 39], [101, 17], [145, 17], [158, 59]]
|
||||
assert_equal(num_points, result.size)
|
||||
result.each { |pt|
|
||||
x = pt.x - center.x
|
||||
y = pt.y - center.y
|
||||
error = Math.sqrt((x * x + y * y - radius * radius).abs)
|
||||
assert(error < acceptable_error)
|
||||
}
|
||||
}
|
||||
|
||||
# raise error
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(DUMMY_OBJ, arr_alpha, arr_beta, arr_gamma, size, term_criteria)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(points, DUMMY_OBJ, arr_beta, arr_gamma, size, term_criteria)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(points, arr_alpha, DUMMY_OBJ, arr_gamma, size, term_criteria)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(points, arr_alpha, arr_beta, DUMMY_OBJ, size, term_criteria)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, DUMMY_OBJ, term_criteria)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, size, DUMMY_OBJ)
|
||||
}
|
||||
mat.snake_image(points, arr_alpha, arr_beta, arr_gamma, size, term_criteria, DUMMY_OBJ)
|
||||
|
||||
assert_raise(ArgumentError) {
|
||||
mat.snake_image(points, arr_alpha[0 .. num_points / 2], arr_beta, arr_gamma, size, term_criteria)
|
||||
}
|
||||
assert_raise(CvBadNumChannels) {
|
||||
CvMat.new(10, 10, :cv8u, 3).snake_image(points, alpha, beta, gamma, size, term_criteria)
|
||||
}
|
||||
|
||||
# Uncomment the following lines to show the result
|
||||
# result = mat.clone.GRAY2BGR
|
||||
# pts = mat.snake_image(points, alpha, beta, gamma, size, term_criteria)
|
||||
# w = GUI::Window.new('HoughCircle')
|
||||
# result.poly_line!([pts], :color => CvColor::Red, :is_closed => true, :thickness => 2)
|
||||
# result.poly_line!([points], :color => CvColor::Yellow, :is_closed => true, :thickness => 2)
|
||||
# w.show result
|
||||
# GUI::wait_key
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue