diff --git a/ext/opencv/mat.cpp b/ext/opencv/mat.cpp index 22a0136..da0da4b 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -1234,6 +1234,7 @@ namespace rubyopencv { rb_define_method(rb_klass, "sobel", RUBY_METHOD_FUNC(rb_sobel), -1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "sobel!", RUBY_METHOD_FUNC(rb_sobel_bang), -1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "canny", RUBY_METHOD_FUNC(rb_canny), -1); // in ext/opencv/mat_imgproc.cpp + rb_define_method(rb_klass, "canny!", RUBY_METHOD_FUNC(rb_canny_bang), -1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "laplacian", RUBY_METHOD_FUNC(rb_laplacian), -1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "line", RUBY_METHOD_FUNC(rb_line), -1); // in ext/opencv/mat_drawing.cpp diff --git a/ext/opencv/mat_imgproc.cpp b/ext/opencv/mat_imgproc.cpp index 6411562..249561b 100644 --- a/ext/opencv/mat_imgproc.cpp +++ b/ext/opencv/mat_imgproc.cpp @@ -67,19 +67,7 @@ namespace rubyopencv { return self; } - /** - * Finds edges in an image using the [Canny86] algorithm. - * - * @overload canny(threshold1, threshold2, aperture_size = 3, l2gradient = false) - * @param threshold1 [Number] First threshold for the hysteresis procedure. - * @param threshold2 [Number] Second threshold for the hysteresis procedure. - * @param aperture_size [Integer] Aperture size for the Sobel operator. - * @param l2gradient [Boolean] a flag, indicating whether a more accurate L_2 =\sqrt{ (dI/dx)^2 + (dI/dy)^2 } norm - * should be used to calculate the image gradient magnitude (l2gradient=true), - * or whether the default L_1 norm =|dI/dx|+|dI/dy| is enough (l2gradient=false). - * @opencv_func cv::Canny - */ - VALUE rb_canny(int argc, VALUE *argv, VALUE self) { + cv::Mat* rb_canny_internal(int argc, VALUE *argv, VALUE self, cv::Mat* destptr) { VALUE threshold1, threshold2, aperture_size, l2gradient; rb_scan_args(argc, argv, "22", &threshold1, &threshold2, &aperture_size, &l2gradient); @@ -87,10 +75,29 @@ namespace rubyopencv { bool l2gradient_value = RTEST(l2gradient) ? true : false; cv::Mat* selfptr = obj2mat(self); + cv::Canny(*selfptr, *destptr, NUM2DBL(threshold1), NUM2DBL(threshold2), + aperture_size_value, l2gradient_value); + + return destptr; + } + + /** + * Finds edges in an image using the [Canny86] algorithm. + * + * @overload canny(threshold1, threshold2, aperture_size = 3, l2gradient = false) + * @param threshold1 [Number] First threshold for the hysteresis procedure. + * @param threshold2 [Number] Second threshold for the hysteresis procedure. + * @param aperture_size [Integer] Aperture size for the Sobel operator. + * @param l2gradient [Boolean] a flag, indicating whether a more accurate L_2 = \sqrt{ (dI/dx)^2 + (dI/dy)^2 } norm + * should be used to calculate the image gradient magnitude (l2gradient=true), + * or whether the default L_1 norm = |dI/dx|+|dI/dy| is enough (l2gradient=false). + * @return [Mat] Output image + * @opencv_func cv::Canny + */ + VALUE rb_canny(int argc, VALUE *argv, VALUE self) { cv::Mat* destptr = new cv::Mat(); try { - cv::Canny(*selfptr, *destptr, NUM2DBL(threshold1), NUM2DBL(threshold2), - aperture_size_value, l2gradient_value); + rb_canny_internal(argc, argv, self, destptr); } catch (cv::Exception& e) { delete destptr; @@ -100,6 +107,22 @@ namespace rubyopencv { return mat2obj(destptr, CLASS_OF(self)); } + /** + * @overload canny!(threshold1, threshold2, aperture_size = 3, l2gradient = false) + * @see #canny + */ + VALUE rb_canny_bang(int argc, VALUE *argv, VALUE self) { + cv::Mat* destptr = obj2mat(self); + try { + rb_canny_internal(argc, argv, self, destptr); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + /* * Calculates the Laplacian of an image. * diff --git a/ext/opencv/mat_imgproc.hpp b/ext/opencv/mat_imgproc.hpp index 3861c73..5583f97 100644 --- a/ext/opencv/mat_imgproc.hpp +++ b/ext/opencv/mat_imgproc.hpp @@ -9,6 +9,7 @@ namespace rubyopencv { VALUE rb_sobel(int argc, VALUE *argv, VALUE self); VALUE rb_sobel_bang(int argc, VALUE *argv, VALUE self); VALUE rb_canny(int argc, VALUE *argv, VALUE self); + VALUE rb_canny_bang(int argc, VALUE *argv, VALUE self); VALUE rb_laplacian(int argc, VALUE *argv, VALUE self); VALUE rb_cvt_color(int argc, VALUE *argv, VALUE self); VALUE rb_resize(int argc, VALUE *argv, VALUE self); diff --git a/test/test_mat_imgproc.rb b/test/test_mat_imgproc.rb index 310a562..644b6cb 100755 --- a/test/test_mat_imgproc.rb +++ b/test/test_mat_imgproc.rb @@ -123,6 +123,41 @@ class TestCvMat < OpenCVTestCase # Cv::wait_key end + def test_canny_bang + m0 = Cv::imread(FILENAME_LENA256x256, 0) + m1 = m0.clone + m0.canny!(50, 200) + m1.canny!(50, 200, 5, true) + + canny = [m0, m1] + canny.each { |m| + assert_equal(m0.rows, m.rows) + assert_equal(m0.cols, m.cols) + assert_equal(m0.depth, m.depth) + assert_equal(m0.dims, m.dims) + assert_equal(m0.channels, m.channels) + } + + assert_raise(TypeError) { + m0.canny!(DUMMY_OBJ, 200, 5, true) + } + assert_raise(TypeError) { + m0.canny!(50, DUMMY_OBJ, 5, true) + } + assert_raise(TypeError) { + m0.canny!(50, 200, DUMMY_OBJ, true) + } + assert_nothing_raised { + m0.canny!(50, 200, 5, DUMMY_OBJ) + } + + # w = Window.new('Canny') + # m0 = Cv::imread(FILENAME_LENA256x256, 0) + # m0.canny!(50, 200) + # w.show(m0) + # Cv::wait_key + end + def test_laplacian m0 = Cv::imread(FILENAME_LENA256x256, 0)