From 85e744c07da246c3694de8c8f5fa7955627b5237 Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 30 Apr 2017 04:37:45 +0900 Subject: [PATCH] add Mat#threshold! --- ext/opencv/mat.cpp | 1 + ext/opencv/mat_imgproc.cpp | 45 +++++++++++++++++++-------- ext/opencv/mat_imgproc.hpp | 1 + test/test_mat_imgproc.rb | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 12 deletions(-) diff --git a/ext/opencv/mat.cpp b/ext/opencv/mat.cpp index 13e704c..e17455e 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -1258,6 +1258,7 @@ namespace rubyopencv { 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, "median_blur!", RUBY_METHOD_FUNC(rb_median_blur_bang), 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, "threshold!", RUBY_METHOD_FUNC(rb_threshold_bang), 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 9b62b6c..48e86cf 100644 --- a/ext/opencv/mat_imgproc.cpp +++ b/ext/opencv/mat_imgproc.cpp @@ -452,6 +452,22 @@ namespace rubyopencv { return self; } + VALUE rb_threshold_internal(VALUE self, VALUE threshold, VALUE max_value, VALUE threshold_type, VALUE dest) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* destptr = obj2mat(dest); + int threshold_type_value = NUM2INT(threshold_type); + double optimal_threshold = cv::threshold(*selfptr, *destptr, NUM2DBL(threshold), NUM2DBL(max_value), threshold_type_value); + + VALUE ret = Qnil; + if ((threshold_type_value & cv::THRESH_OTSU) || (threshold_type_value & cv::THRESH_TRIANGLE)) { + ret = rb_assoc_new(dest, DBL2NUM(optimal_threshold)); + } + else { + ret = dest; + } + return ret; + } + /* * Applies a fixed-level threshold to each array element. * @@ -474,27 +490,32 @@ namespace rubyopencv { * @opencv_func cv::threshold */ VALUE rb_threshold(VALUE self, VALUE threshold, VALUE max_value, VALUE threshold_type) { - cv::Mat* selfptr = obj2mat(self); - cv::Mat* dstptr = NULL; - double optimal_threshold = 0.0; - int threshold_type_value = NUM2INT(threshold_type); + cv::Mat* destptr = new cv::Mat(); + VALUE dest = mat2obj(destptr); + VALUE ret = Qnil; try { - dstptr = new cv::Mat(); - optimal_threshold = cv::threshold(*selfptr, *dstptr, NUM2DBL(threshold), NUM2DBL(max_value), threshold_type_value); + ret = rb_threshold_internal(self, threshold, max_value, threshold_type, dest); } catch (cv::Exception& e) { - delete dstptr; Error::raise(e); } + return ret; + } + + /* + * @overload threshold!(threshold, max_value, type) + * @see #threshold + */ + VALUE rb_threshold_bang(VALUE self, VALUE threshold, VALUE max_value, VALUE threshold_type) { VALUE ret = Qnil; - VALUE dst = mat2obj(dstptr, CLASS_OF(self)); - if ((threshold_type_value & cv::THRESH_OTSU) || (threshold_type_value & cv::THRESH_TRIANGLE)) { - ret = rb_assoc_new(dst, DBL2NUM(optimal_threshold)); + try { + ret = rb_threshold_internal(self, threshold, max_value, threshold_type, self); } - else { - ret = dst; + catch (cv::Exception& e) { + Error::raise(e); } + return ret; } diff --git a/ext/opencv/mat_imgproc.hpp b/ext/opencv/mat_imgproc.hpp index 95a34d1..50577b8 100644 --- a/ext/opencv/mat_imgproc.hpp +++ b/ext/opencv/mat_imgproc.hpp @@ -23,6 +23,7 @@ namespace rubyopencv { VALUE rb_median_blur(VALUE self, VALUE ksize); VALUE rb_median_blur_bang(VALUE self, VALUE ksize); VALUE rb_threshold(VALUE self, VALUE threshold, VALUE max_value, VALUE threshold_type); + VALUE rb_threshold_bang(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/test/test_mat_imgproc.rb b/test/test_mat_imgproc.rb index c9ebfe0..6b008fa 100755 --- a/test/test_mat_imgproc.rb +++ b/test/test_mat_imgproc.rb @@ -605,6 +605,68 @@ class TestCvMat < OpenCVTestCase # Cv::wait_key end + def test_threshold_bang + m0 = Cv::Mat.zeros(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) + + m = m0.clone + m.threshold!(25, 255, Cv::THRESH_BINARY) + expected = "" + assert_equal(expected, m.to_s) + + m = m0.clone + m.threshold!(25, 255, Cv::THRESH_BINARY_INV) + expected = "" + assert_equal(expected, m.to_s) + + m = m0.clone + m.threshold!(25, 255, Cv::THRESH_TRUNC) + expected = "" + assert_equal(expected, m.to_s) + + m = m0.clone + m.threshold!(25, 255, Cv::THRESH_TOZERO) + expected = "" + assert_equal(expected, m.to_s) + + m = m0.clone + m.threshold!(25, 255, Cv::THRESH_TOZERO_INV) + expected = "" + assert_equal(expected, m.to_s) + + m = m0.clone + _, optimal_threshold = m.threshold!(25, 255, Cv::THRESH_BINARY | Cv::THRESH_OTSU) + expected = "" + assert_equal(expected, m.to_s) + assert_in_delta(20, optimal_threshold, 0.1) + + m = m0.clone + _, optimal_threshold = m.threshold!(25, 255, Cv::THRESH_BINARY | Cv::THRESH_TRIANGLE) + expected = "" + assert_equal(expected, m.to_s) + assert_in_delta(12, optimal_threshold, 0.1) + + assert_raise(TypeError) { + m0.threshold!(DUMMY_OBJ, 255, Cv::THRESH_BINARY) + } + assert_raise(TypeError) { + m0.threshold!(25, DUMMY_OBJ, Cv::THRESH_BINARY) + } + assert_raise(TypeError) { + m0.threshold!(25, 255, DUMMY_OBJ) + } + + # m0 = Cv::imread(FILENAME_LENA256x256, 0) + # m = m0.clone + # m.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)