diff --git a/ext/opencv/mat.cpp b/ext/opencv/mat.cpp index 9fbbb28..45e6077 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -1247,6 +1247,7 @@ namespace rubyopencv { rb_define_method(rb_klass, "gaussian_blur", RUBY_METHOD_FUNC(rb_gaussian_blur), -1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "median_blur", RUBY_METHOD_FUNC(rb_median_blur), 1); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "threshold", RUBY_METHOD_FUNC(rb_threshold), 3); // in ext/opencv/mat_imgproc.cpp + rb_define_method(rb_klass, "adaptive_threshold", RUBY_METHOD_FUNC(rb_adaptive_threshold), 5); // in ext/opencv/mat_imgproc.cpp rb_define_method(rb_klass, "save", RUBY_METHOD_FUNC(rb_save), -1); diff --git a/ext/opencv/mat_imgproc.cpp b/ext/opencv/mat_imgproc.cpp index 07adf5f..56ff53d 100644 --- a/ext/opencv/mat_imgproc.cpp +++ b/ext/opencv/mat_imgproc.cpp @@ -311,5 +311,37 @@ namespace rubyopencv { } return ret; } + + /* + * Applies an adaptive threshold to an array. + * + * @overload adaptive_threshold(max_value, adaptive_method, threshold_type, block_size, delta) + * @param max_value [Number] Non-zero value assigned to the pixels for which the condition is satisfied. + * @param adaptive_method [Integer] Adaptive thresholding algorithm to use. + * @param threshold_type [Integer] Thresholding type that must be either THRESH_BINARY + * or THRESH_BINARY_INV. + * @param block_size [Integer] Size of a pixel neighborhood that is used to calculate a threshold value + * for the pixel: 3, 5, 7, and so on. + * @param delta [Number] Constant subtracted from the mean or weighted mean. + * Normally, it is positive but may be zero or negative as well. + * @return [Mat] Destination image of the same size and the same type as self. + * @opencv_func cv::adaptiveThreshold + */ + VALUE rb_adaptive_threshold(VALUE self, VALUE max_value, VALUE adaptive_method, VALUE threshold_type, + VALUE block_size, VALUE delta) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* dstptr = NULL; + try { + dstptr = new cv::Mat(); + cv::adaptiveThreshold(*selfptr, *dstptr, NUM2DBL(max_value), NUM2INT(adaptive_method), + NUM2INT(threshold_type), NUM2INT(block_size), NUM2DBL(delta)); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, CLASS_OF(self)); + } } } diff --git a/ext/opencv/mat_imgproc.hpp b/ext/opencv/mat_imgproc.hpp index d2e4514..10ef711 100644 --- a/ext/opencv/mat_imgproc.hpp +++ b/ext/opencv/mat_imgproc.hpp @@ -15,6 +15,8 @@ namespace rubyopencv { VALUE rb_gaussian_blur(int argc, VALUE *argv, VALUE self); VALUE rb_median_blur(VALUE self, VALUE ksize); VALUE rb_threshold(VALUE self, VALUE threshold, VALUE max_value, VALUE threshold_type); + VALUE rb_adaptive_threshold(VALUE self, VALUE max_value, VALUE adaptive_method, + VALUE threshold_type, VALUE block_size, VALUE delta); } } diff --git a/ext/opencv/opencv_const.cpp b/ext/opencv/opencv_const.cpp index 21c7c81..cc771c1 100644 --- a/ext/opencv/opencv_const.cpp +++ b/ext/opencv/opencv_const.cpp @@ -386,5 +386,8 @@ namespace rubyopencv { rb_define_const(rb_module, "THRESH_MASK", INT2FIX(cv::THRESH_MASK)); rb_define_const(rb_module, "THRESH_OTSU", INT2FIX(cv::THRESH_OTSU)); rb_define_const(rb_module, "THRESH_TRIANGLE", INT2FIX(cv::THRESH_TRIANGLE)); + + rb_define_const(rb_module, "ADAPTIVE_THRESH_MEAN_C", INT2FIX(cv::ADAPTIVE_THRESH_MEAN_C)); + rb_define_const(rb_module, "ADAPTIVE_THRESH_GAUSSIAN_C", INT2FIX(cv::ADAPTIVE_THRESH_GAUSSIAN_C)); } } diff --git a/test/test_mat_imgproc.rb b/test/test_mat_imgproc.rb index 229d463..3700320 100755 --- a/test/test_mat_imgproc.rb +++ b/test/test_mat_imgproc.rb @@ -284,10 +284,48 @@ class TestCvMat < OpenCVTestCase assert_raise(TypeError) { m0.threshold(25, 255, DUMMY_OBJ) } + # m0 = Cv::imread(FILENAME_LENA256x256, 0) # m = m0.threshold(127, 255, Cv::THRESH_BINARY) # w = Window.new('Original | Binary') # w.show(Cv::hconcat([m0, m])) # Cv::wait_key end + + def test_adaptive_threshold + m0 = Cv::Mat.new(2, 2, Cv::CV_8U) + m0[0, 0] = Cv::Scalar.new(10) + m0[0, 1] = Cv::Scalar.new(20) + m0[1, 0] = Cv::Scalar.new(30) + m0[1, 1] = Cv::Scalar.new(40) + + expected = "" + m = m0.adaptive_threshold(255, Cv::ADAPTIVE_THRESH_MEAN_C, Cv::THRESH_BINARY, 3, 0) + assert_equal(expected, m.to_s) + + m = m0.adaptive_threshold(255, Cv::ADAPTIVE_THRESH_GAUSSIAN_C, Cv::THRESH_BINARY, 3, 0) + assert_equal(expected, m.to_s) + + assert_raise(TypeError) { + m0.adaptive_threshold(DUMMY_OBJ, Cv::ADAPTIVE_THRESH_MEAN_C, Cv::THRESH_BINARY, 3, 0) + } + assert_raise(TypeError) { + m0.adaptive_threshold(255, DUMMY_OBJ, Cv::THRESH_BINARY, 3, 0) + } + assert_raise(TypeError) { + m0.adaptive_threshold(255, Cv::ADAPTIVE_THRESH_MEAN_C, DUMMY_OBJ, 3, 0) + } + assert_raise(TypeError) { + m0.adaptive_threshold(DUMMY_OBJ, Cv::ADAPTIVE_THRESH_MEAN_C, Cv::THRESH_BINARY, DUMMY_OBJ, 0) + } + assert_raise(TypeError) { + m0.adaptive_threshold(DUMMY_OBJ, Cv::ADAPTIVE_THRESH_MEAN_C, Cv::THRESH_BINARY, 3, DUMMY_OBJ) + } + + # m0 = Cv::imread(FILENAME_LENA256x256, 0) + # m = m0.adaptive_threshold(255, Cv::ADAPTIVE_THRESH_MEAN_C, Cv::THRESH_BINARY, 25, 0) + # w = Window.new('Original | Binary') + # w.show(Cv::hconcat([m0, m])) + # Cv::wait_key + end end