diff --git a/.gitignore b/.gitignore index 3f097f2..b1580e9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ log.txt videowriter_result.avi examples/contours/rotated-boxes-with-detected-bounding-rectangles.jpg Gemfile.lock +.yardoc .RUBYLIBDIR.* .RUBYARCHDIR.* +.bundle diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..5c78b63 --- /dev/null +++ b/.yardopts @@ -0,0 +1,3 @@ +--load yard_extension.rb +ext/opencv/*.cpp + diff --git a/Gemfile b/Gemfile index 1c6b08d..0cb99e2 100644 --- a/Gemfile +++ b/Gemfile @@ -4,5 +4,6 @@ group :development do gem "hoe" gem "hoe-gemspec" gem "rake-compiler" + gem "yard" end diff --git a/Manifest.txt b/Manifest.txt index 503c58e..c48551b 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,4 +1,5 @@ .gitignore +.yardopts DEVELOPERS_NOTE.md Gemfile History.txt @@ -34,12 +35,6 @@ examples/images/tiffany.jpg examples/inpaint.rb examples/match_kdtree.rb examples/match_template.rb -examples/matching_to_many_images/matching_to_many_images.rb -examples/matching_to_many_images/query.png -examples/matching_to_many_images/train/1.png -examples/matching_to_many_images/train/2.png -examples/matching_to_many_images/train/3.png -examples/matching_to_many_images/train/trainImages.txt examples/paint.rb examples/snake.rb ext/opencv/algorithm.cpp @@ -56,8 +51,6 @@ ext/opencv/cvchain.cpp ext/opencv/cvchain.h ext/opencv/cvcircle32f.cpp ext/opencv/cvcircle32f.h -ext/opencv/cvcondensation.cpp -ext/opencv/cvcondensation.h ext/opencv/cvconnectedcomp.cpp ext/opencv/cvconnectedcomp.h ext/opencv/cvcontour.cpp @@ -82,8 +75,6 @@ ext/opencv/cvline.cpp ext/opencv/cvline.h ext/opencv/cvmat.cpp ext/opencv/cvmat.h -ext/opencv/cvmatnd.cpp -ext/opencv/cvmatnd.h ext/opencv/cvmemstorage.cpp ext/opencv/cvmemstorage.h ext/opencv/cvmoments.cpp @@ -106,8 +97,6 @@ ext/opencv/cvsize2d32f.cpp ext/opencv/cvsize2d32f.h ext/opencv/cvslice.cpp ext/opencv/cvslice.h -ext/opencv/cvsparsemat.cpp -ext/opencv/cvsparsemat.h ext/opencv/cvsurfparams.cpp ext/opencv/cvsurfparams.h ext/opencv/cvsurfpoint.cpp @@ -148,7 +137,6 @@ ext/opencv/window.h images/CvMat_sobel.png images/CvMat_sub_rect.png images/CvSeq_relationmap.png -images/face_detect_from_lena.jpg lib/opencv.rb lib/opencv/psyched_yaml.rb lib/opencv/version.rb @@ -222,7 +210,6 @@ test/test_cvmat.rb test/test_cvmat_drawing.rb test/test_cvmat_dxt.rb test/test_cvmat_imageprocessing.rb -test/test_cvmat_matching.rb test/test_cvmoments.rb test/test_cvpoint.rb test/test_cvpoint2d32f.rb @@ -249,3 +236,4 @@ test/test_pointset.rb test/test_preliminary.rb test/test_trackbar.rb test/test_window.rb +yard_extension.rb diff --git a/README.md b/README.md index 11fcac9..69897c1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ An OpenCV wrapper for Ruby. * Web site: -* Ruby 1.9.3, 2.0.0 and OpenCV 2.4.7 are supported. +* Ruby 1.9.3, 2.0.0, 2.1.0 and OpenCV 2.4.8 are supported. ## Requirement diff --git a/Rakefile b/Rakefile index 7f059d7..03d2e7a 100644 --- a/Rakefile +++ b/Rakefile @@ -6,6 +6,9 @@ require 'hoe' require 'rake/extensiontask' require 'fileutils' require './lib/opencv/psyched_yaml' +require 'yard' +require 'yard/rake/yardoc_task' +require './yard_extension' SO_FILE = 'opencv.so' @@ -27,7 +30,7 @@ hoespec = Hoe.spec 'ruby-opencv' do |s| s.test_globs = ['test/test_*.rb'] s.urls = ['https://github.com/ruby-opencv/ruby-opencv/'] - s.extra_dev_deps << ['rake-compiler', '>= 0'] << ['hoe-gemspec'] + s.extra_dev_deps << ['rake-compiler', '~> 0'] << ['hoe-gemspec', '~> 0'] Rake::ExtensionTask.new('opencv', spec) do |ext| ext.lib_dir = 'lib' @@ -87,4 +90,10 @@ task 'gem:precompile' => ['gem'] do FileUtils.rm_rf tmp_dir end +# yard +YARD::Rake::YardocTask.new do |t| + t.files = ['lib/**/*.rb', 'ext/**/*.cpp'] +end + # vim: syntax=ruby + diff --git a/examples/facerec/facerec_lbph.rb b/examples/facerec/facerec_lbph.rb index 4fee5d5..ba3e8a8 100755 --- a/examples/facerec/facerec_lbph.rb +++ b/examples/facerec/facerec_lbph.rb @@ -97,7 +97,7 @@ model.set_double('threshold', 0.0); # Now the threshold of this model is set to 0.0. A prediction # now returns -1, as it's impossible to have a distance below it -predicted_label = model.predict(test_sample) +predicted_label, predicted_confidence = model.predict(test_sample) puts "Predicted class = #{predicted_label}" # Show some informations about the model, as there's no cool diff --git a/examples/matching_to_many_images/matching_to_many_images.rb b/examples/matching_to_many_images/matching_to_many_images.rb deleted file mode 100644 index 72d0a1c..0000000 --- a/examples/matching_to_many_images/matching_to_many_images.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'opencv' -require 'benchmark' -include OpenCV - -data = File.dirname(__FILE__) - -query = CvMat.load File.join(data, 'query.png'), CV_LOAD_IMAGE_GRAYSCALE -image_files = ['1.png', '2.png', '3.png'].map{|f| File.join(data, 'train', f)} -images = image_files.map{|f| CvMat.load f, CV_LOAD_IMAGE_GRAYSCALE} - - -matchs = query.match_descriptors(images) - -match_index, count = matchs.max_by {|image_index, count| count} - -puts "max match: #{image_files[match_index]}" diff --git a/examples/matching_to_many_images/query.png b/examples/matching_to_many_images/query.png deleted file mode 100755 index 9aa1199..0000000 Binary files a/examples/matching_to_many_images/query.png and /dev/null differ diff --git a/examples/matching_to_many_images/train/1.png b/examples/matching_to_many_images/train/1.png deleted file mode 100755 index c52e19e..0000000 Binary files a/examples/matching_to_many_images/train/1.png and /dev/null differ diff --git a/examples/matching_to_many_images/train/2.png b/examples/matching_to_many_images/train/2.png deleted file mode 100755 index 7b1189c..0000000 Binary files a/examples/matching_to_many_images/train/2.png and /dev/null differ diff --git a/examples/matching_to_many_images/train/3.png b/examples/matching_to_many_images/train/3.png deleted file mode 100755 index dc2389a..0000000 Binary files a/examples/matching_to_many_images/train/3.png and /dev/null differ diff --git a/examples/matching_to_many_images/train/trainImages.txt b/examples/matching_to_many_images/train/trainImages.txt deleted file mode 100755 index b376639..0000000 --- a/examples/matching_to_many_images/train/trainImages.txt +++ /dev/null @@ -1,3 +0,0 @@ -1.png -2.png -3.png diff --git a/ext/opencv/algorithm.cpp b/ext/opencv/algorithm.cpp index 837a1da..d702b42 100644 --- a/ext/opencv/algorithm.cpp +++ b/ext/opencv/algorithm.cpp @@ -252,8 +252,13 @@ rb_name(VALUE self) } void -define_ruby_class() +init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + if (rb_klass) return; /* diff --git a/ext/opencv/algorithm.h b/ext/opencv/algorithm.h index d8d922e..945ee69 100644 --- a/ext/opencv/algorithm.h +++ b/ext/opencv/algorithm.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_ALGORITHM VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); __NAMESPACE_END_ALGORITM diff --git a/ext/opencv/curve.cpp b/ext/opencv/curve.cpp index 0c87c13..1aa0c82 100644 --- a/ext/opencv/curve.cpp +++ b/ext/opencv/curve.cpp @@ -11,7 +11,7 @@ /* * Document-class: OpenCV::Curve * - * Curve sequence. + * Curve sequence */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CURVE @@ -24,27 +24,11 @@ rb_module() return module; } -void -define_ruby_module() -{ - if (module) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - module = rb_define_module_under(opencv, "Curve"); - rb_define_method(module, "closed?", RUBY_METHOD_FUNC(rb_closed_q), 0); - rb_define_method(module, "convex?", RUBY_METHOD_FUNC(rb_convex_q), 0); - rb_define_method(module, "hole?", RUBY_METHOD_FUNC(rb_hole_q), 0); - rb_define_method(module, "simple?", RUBY_METHOD_FUNC(rb_simple_q), 0); - rb_define_method(module, "arc_length", RUBY_METHOD_FUNC(rb_arc_length), -1); -} - /* - * If curve is closed, return true. Otherwise return false. + * If the curve is closed, return true. Otherwise return false. + * @overload closed? + * @return [Boolean] Closed or not + * @opencv_func CV_IS_SEQ_CLOSED */ VALUE rb_closed_q(VALUE self) @@ -53,7 +37,10 @@ rb_closed_q(VALUE self) } /* - * If curve is convex, return true. Otherwise return false. + * If the curve is convex, return true. Otherwise return false. + * @overload convex? + * @return [Boolean] Convex or not + * @opencv_func CV_IS_SEQ_CONVEX */ VALUE rb_convex_q(VALUE self) @@ -62,7 +49,10 @@ rb_convex_q(VALUE self) } /* - * If curve is hole(inner contour), return true. Otherwise return false. + * If the curve is hole(inner contour), return true. Otherwise return false. + * @overload hole? + * @return [Boolean] Hole or not + * @opencv_func CV_IS_SEQ_HOLE */ VALUE rb_hole_q(VALUE self) @@ -71,7 +61,10 @@ rb_hole_q(VALUE self) } /* - * no idia. + * If the curve is simple, return true. Otherwise return false. + * @overload simple? + * @return [Boolean] Simple or not + * @opencv_func CV_IS_SEQ_SIMPLE */ VALUE rb_simple_q(VALUE self) @@ -80,15 +73,17 @@ rb_simple_q(VALUE self) } /* - * call-seq: - * arc_length([slice = nil][,is_closed = nil]) -> float - * - * Calculates contour perimeter or curve length. - * slice is starting and ending points of the curve. - * is_closed is indicates whether the curve is closed or not. There are 3 cases: - * * is_closed = true - the curve is assumed to be unclosed. - * * is_closed = false - the curve is assumed to be closed. - * * is_closed = nil (default) use self#close? + * Calculates length of a curve + * @overload arc_length(slice = nil, is_closed = nil) + * @param slice [Range,CvSlice,nil] Starting and ending points of the curve. + * By default, the whole curve length is calculated. + * @param is_closed [Boolean,nil] Indicates whether the curve is closed or not. + * There are 3 cases: + * * is_closed = true - the curve is assumed to be unclosed. + * * is_closed = false - the curve is assumed to be closed. + * * is_closed = nil (default) use self#closed? + * @return [Number] Length of the curve + * @opencv_func cvArcLength */ VALUE rb_arc_length(int argc, VALUE *argv, VALUE self) @@ -107,6 +102,26 @@ rb_arc_length(int argc, VALUE *argv, VALUE self) return rb_float_new(length); } +void +init_ruby_module() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (module) + return; + + VALUE opencv = rb_module_opencv(); + module = rb_define_module_under(opencv, "Curve"); + rb_define_method(module, "closed?", RUBY_METHOD_FUNC(rb_closed_q), 0); + rb_define_method(module, "convex?", RUBY_METHOD_FUNC(rb_convex_q), 0); + rb_define_method(module, "hole?", RUBY_METHOD_FUNC(rb_hole_q), 0); + rb_define_method(module, "simple?", RUBY_METHOD_FUNC(rb_simple_q), 0); + rb_define_method(module, "arc_length", RUBY_METHOD_FUNC(rb_arc_length), -1); +} + __NAMESPACE_END_CURVE __NAMESPACE_END_OPENCV diff --git a/ext/opencv/curve.h b/ext/opencv/curve.h index 182ad5a..28ec556 100644 --- a/ext/opencv/curve.h +++ b/ext/opencv/curve.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CURVE VALUE rb_module(); -void define_ruby_module(); +void init_ruby_module(); VALUE rb_closed_q(VALUE self); VALUE rb_convex_q(VALUE self); diff --git a/ext/opencv/cvavgcomp.cpp b/ext/opencv/cvavgcomp.cpp index cf95069..ec64648 100644 --- a/ext/opencv/cvavgcomp.cpp +++ b/ext/opencv/cvavgcomp.cpp @@ -11,13 +11,7 @@ /* * Document-class: OpenCV::CvAvgComp * - * CvRect with parameter "neighbors". - * CvHaarClassifierCascade#detect_object. - * - * typedef struct CvAvgComp { - * CvRect rect; - * int neighbors; - * } + * CvRect with parameter "neighbors" */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_AVGCOMP @@ -30,23 +24,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvrect = rb_define_class_under(opencv, "CvRect", rb_cObject); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(), cvrect = cCvRect::rb_class(); - rb_klass = rb_define_class_under(opencv, "CvAvgComp", cvrect); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_method(rb_klass, "neighbors", RUBY_METHOD_FUNC(rb_neighbors), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -55,7 +32,9 @@ rb_allocate(VALUE klass) } /* - * Return neighbors. + * Return neighbors + * @overload neighbors + * @return [Integer] neighbors */ VALUE rb_neighbors(VALUE self) @@ -63,5 +42,23 @@ rb_neighbors(VALUE self) return INT2NUM(CVAVGCOMP(self)->neighbors); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvrect = rb_define_class_under(opencv, "CvRect", rb_cObject); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(), cvrect = cCvRect::rb_class(); + rb_klass = rb_define_class_under(opencv, "CvAvgComp", cvrect); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "neighbors", RUBY_METHOD_FUNC(rb_neighbors), 0); +} + __NAMESPACE_END_AVGCOMP __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvavgcomp.h b/ext/opencv/cvavgcomp.h index cce6df7..a29d7d0 100644 --- a/ext/opencv/cvavgcomp.h +++ b/ext/opencv/cvavgcomp.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_AVGCOMP VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_neighbors(VALUE self); diff --git a/ext/opencv/cvbox2d.cpp b/ext/opencv/cvbox2d.cpp index c0ffbc1..bf39e04 100644 --- a/ext/opencv/cvbox2d.cpp +++ b/ext/opencv/cvbox2d.cpp @@ -11,12 +11,7 @@ /* * Document-class: OpenCV::CvBox2D * - * C structure is here. - * typdef struct CvBox2D { - * CvPoint2D32f center; // center of the box. - * CvSize2D32f size; // box width and length - * float angle; // angle between the horizonal axis and the first side (i.e length) in radians - * } CvBox2D; + * Stores coordinates of a rotated rectangle. */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVBOX2D @@ -29,29 +24,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvBox2D", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); - rb_define_method(rb_klass, "center=", RUBY_METHOD_FUNC(rb_set_center), 1); - rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_size), 0); - rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); - rb_define_method(rb_klass, "angle", RUBY_METHOD_FUNC(rb_angle), 0); - rb_define_method(rb_klass, "angle=", RUBY_METHOD_FUNC(rb_set_angle), 1); - rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -59,11 +31,13 @@ rb_allocate(VALUE klass) return Data_Make_Struct(klass, CvBox2D, 0, -1, ptr); } -/* - * call-seq: - * CvBox2D.new([center][, size][, angle]) -> cvbox2d - * +/* * Create a box + * @overload new(center=nil, size=nil, angle=nil) + * @param center [CvPoint2D32f,nil] Center of the box + * @param size [CvSize,nil] Size of the box + * @param angle [Number,nil] Angle between the horizontal axis and the first side in degrees + * @return [CvBox2D] New box */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) @@ -84,9 +58,9 @@ rb_initialize(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * center -> cvpoint2d32f - * Return center point of box as CvPoint2D32f. + * Returns center point of the box + * @overload center + * @return [CvPoint2D32f] Center of the box */ VALUE rb_center(VALUE self) @@ -95,10 +69,10 @@ rb_center(VALUE self) } /* - * call-seq: - * center = value - * - * Set center to value + * Set center point of the box + * @overload center=value + * @param value [CvPoint2D32f] Center of the box + * @return [CvBox2D] self */ VALUE rb_set_center(VALUE self, VALUE value) @@ -108,9 +82,9 @@ rb_set_center(VALUE self, VALUE value) } /* - * call-seq: - * size -> cvsize2d32f - * Return size of box as CvSize2D32f. + * Returns size of the box + * @overload size + * @return [CvSize2D32f] Size of the box */ VALUE rb_size(VALUE self) @@ -119,10 +93,10 @@ rb_size(VALUE self) } /* - * call-seq: - * size = value - * - * Set size to value + * Set size of the box + * @overload size=value + * @param value [CvSize2D32f] Size of the box + * @return [CvBox2D] self */ VALUE rb_set_size(VALUE self, VALUE value) @@ -132,10 +106,9 @@ rb_set_size(VALUE self, VALUE value) } /* - * call-seq: - * angle -> float - * - * Return angle of box as Float. + * Returns angle of the box + * @overload angle + * @return [Float] Angle of the box */ VALUE rb_angle(VALUE self) @@ -144,10 +117,10 @@ rb_angle(VALUE self) } /* - * call-seq: - * angle = value - * - * Set angle to value + * Set angle of the box + * @overload angle=value + * @param value [Number] Angle of the box + * @return [CvBox2D] self */ VALUE rb_set_angle(VALUE self, VALUE value) @@ -157,9 +130,10 @@ rb_set_angle(VALUE self, VALUE value) } /* - * call-seq: - * points -> array(include cvpoint2d32f) - * Find box vertices. Return Array contain 4 CvPoint2D32f. + * Find box vertices + * @overload points + * @return [Array] Vertices of the box + * @opencv_func cvBoxPoints */ VALUE rb_points(VALUE self) @@ -193,5 +167,29 @@ new_object(CvBox2D box) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvBox2D", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); + rb_define_method(rb_klass, "center=", RUBY_METHOD_FUNC(rb_set_center), 1); + rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_size), 0); + rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); + rb_define_method(rb_klass, "angle", RUBY_METHOD_FUNC(rb_angle), 0); + rb_define_method(rb_klass, "angle=", RUBY_METHOD_FUNC(rb_set_angle), 1); + rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); +} + __NAMESPACE_END_CVBOX2D __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvbox2d.h b/ext/opencv/cvbox2d.h index 38da887..fa1432a 100644 --- a/ext/opencv/cvbox2d.h +++ b/ext/opencv/cvbox2d.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVBOX2D VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvcapture.cpp b/ext/opencv/cvcapture.cpp index 42224e5..3675c4a 100644 --- a/ext/opencv/cvcapture.cpp +++ b/ext/opencv/cvcapture.cpp @@ -11,8 +11,7 @@ /* * Document-class: OpenCV::CvCapture * - * Capture image from video stream. - * + * Class for video capturing from video files or cameras */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCAPTURE @@ -25,75 +24,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvCapture", rb_cData); - - VALUE video_interface = rb_hash_new(); - /* {:any, :mil, :vfw, :v4l, :v4l2, :fireware, :ieee1394, :dc1394, :cmu1394, :stereo, - :tyzx, :tyzx_left, :tyzx_right, :tyzx_color, :tyzx_z, :qt, :qtuicktime}: video source */ - rb_define_const(rb_klass, "INTERFACE", video_interface); - rb_hash_aset(video_interface, ID2SYM(rb_intern("any")), INT2FIX(CV_CAP_ANY)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("mil")), INT2FIX(CV_CAP_MIL)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("vfw")), INT2FIX(CV_CAP_VFW)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("v4l")), INT2FIX(CV_CAP_V4L)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("v4l2")), INT2FIX(CV_CAP_V4L2)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("fireware")), INT2FIX(CV_CAP_FIREWARE)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("ieee1394")), INT2FIX(CV_CAP_IEEE1394)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("dc1394")), INT2FIX(CV_CAP_DC1394)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("cmu1394")), INT2FIX(CV_CAP_CMU1394)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("stereo")), INT2FIX(CV_CAP_STEREO)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx")), INT2FIX(CV_CAP_TYZX)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_left")), INT2FIX(CV_TYZX_LEFT)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_right")), INT2FIX(CV_TYZX_RIGHT)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_color")), INT2FIX(CV_TYZX_COLOR)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_z")), INT2FIX(CV_TYZX_Z)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("qt")), INT2FIX(CV_CAP_QT)); - rb_hash_aset(video_interface, ID2SYM(rb_intern("quicktime")), INT2FIX(CV_CAP_QT)); - - rb_define_singleton_method(rb_klass, "open", RUBY_METHOD_FUNC(rb_open), -1); - - rb_define_method(rb_klass, "grab", RUBY_METHOD_FUNC(rb_grab), 0); - rb_define_method(rb_klass, "retrieve", RUBY_METHOD_FUNC(rb_retrieve), 0); - rb_define_method(rb_klass, "query", RUBY_METHOD_FUNC(rb_query), 0); - rb_define_method(rb_klass, "millisecond", RUBY_METHOD_FUNC(rb_get_millisecond), 0); - rb_define_method(rb_klass, "millisecond=", RUBY_METHOD_FUNC(rb_set_millisecond), 1); - rb_define_method(rb_klass, "frames", RUBY_METHOD_FUNC(rb_get_frames), 0); - rb_define_method(rb_klass, "frames=", RUBY_METHOD_FUNC(rb_set_frames), 1); - rb_define_method(rb_klass, "avi_ratio", RUBY_METHOD_FUNC(rb_get_avi_ratio), 0); - rb_define_method(rb_klass, "avi_ratio=", RUBY_METHOD_FUNC(rb_set_avi_ratio), 1); - rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_get_size), 0); - rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); - rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_get_width), 0); - rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); - rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_get_height), 0); - rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); - rb_define_method(rb_klass, "fps", RUBY_METHOD_FUNC(rb_get_fps), 0); - rb_define_method(rb_klass, "fps=", RUBY_METHOD_FUNC(rb_set_fps), 1); - rb_define_method(rb_klass, "fourcc", RUBY_METHOD_FUNC(rb_get_fourcc), 0); - rb_define_method(rb_klass, "frame_count", RUBY_METHOD_FUNC(rb_get_frame_count), 0); - rb_define_method(rb_klass, "format", RUBY_METHOD_FUNC(rb_get_format), 0); - rb_define_method(rb_klass, "mode", RUBY_METHOD_FUNC(rb_get_mode), 0); - rb_define_method(rb_klass, "brightness", RUBY_METHOD_FUNC(rb_get_brightness), 0); - rb_define_method(rb_klass, "contrast", RUBY_METHOD_FUNC(rb_get_contrast), 0); - rb_define_method(rb_klass, "saturation", RUBY_METHOD_FUNC(rb_get_saturation), 0); - rb_define_method(rb_klass, "hue", RUBY_METHOD_FUNC(rb_get_hue), 0); - rb_define_method(rb_klass, "gain", RUBY_METHOD_FUNC(rb_get_gain), 0); - rb_define_method(rb_klass, "exposure", RUBY_METHOD_FUNC(rb_get_exposure), 0); - rb_define_method(rb_klass, "convert_rgb", RUBY_METHOD_FUNC(rb_get_convert_rgb), 0); - rb_define_method(rb_klass, "rectification", RUBY_METHOD_FUNC(rb_get_rectification), 0); -} - void cvcapture_free(void *ptr) { @@ -102,20 +32,16 @@ cvcapture_free(void *ptr) } /* - * call-seq: - * CvCapture.open([dev = -1]) - * - * Reading video stream from the specified file or camera device. - * If dev is string (i.e "stream.avi"), reading video stream from file. - * If dev is number or symbol(include CvCapture::INTERFACE), - * reading video stream from camera. - * Currently two camera interfaces can be used on Windows: - * * Video for Windows(VFW) - * * Matrox Imaging Library(MIL) - * and two on Linux - * * V4L - * * FireWire(IEEE1394). - * If there is only one camera or it does not matter what camera to use nil may be passed. + * Open video file or a capturing device for video capturing + * @scope class + * @overload open(dev = nil) + * @param dev [String,Fixnum,Simbol,nil] Video capturing device + * * If dev is a string (i.e "stream.avi"), reads video stream from a file. + * * If dev is a number or symbol (included in CvCapture::INTERFACE), reads video stream from a device. + * * If dev is a nil, same as CvCapture.open(:any) + * @return [CvCapture] Opened CvCapture instance + * @opencv_func cvCaptureFromCAM + * @opencv_func cvCaptureFromFile */ VALUE rb_open(int argc, VALUE *argv, VALUE self) @@ -151,18 +77,11 @@ rb_open(int argc, VALUE *argv, VALUE self) return Data_Wrap_Struct(rb_klass, 0, cvcapture_free, capture); } - /* - * call-seq: - * grab -> true or false - * - * Grabbed frame is stored internally. To grab frame - * fast that is important for syncronization in case of reading from - * several cameras simultaneously. The grabbed frames are not exposed because - * they may be stored in compressed format (as defined by camera/driver). - * To retrieve the grabbed frame, retrieve should be used. - * - * If grabbed frame was success, return true. Otherwise return false. + * Grabs the next frame from video file or capturing device. + * @overload grab + * @return [Boolean] If grabbing a frame successed, returns true, otherwise returns false. + * @opencv_func cvGrabFrame */ VALUE rb_grab(VALUE self) @@ -178,10 +97,11 @@ rb_grab(VALUE self) } /* - * call-seq: - * retrieve -> IplImage or nil - * - * Gets the image grabbed with grab. + * Decodes and returns the grabbed video frame. + * @overload retrieve + * @return [IplImage] Grabbed video frame + * @return [nil] Failed to grabbing a frame + * @opencv_func cvRetrieveFrame */ VALUE rb_retrieve(VALUE self) @@ -209,10 +129,11 @@ rb_retrieve(VALUE self) } /* - * call-seq: - * query -> IplImage or nil - * - * Grabs and returns a frame camera or file. Just a combination of grab and retrieve in one call. + * Grabs, decodes and returns the next video frame. + * @overload query + * @return [IplImage] Next video frame + * @return [nil] Failed to read next video frame + * @opencv_func cvQueryFrame */ VALUE rb_query(VALUE self) @@ -266,30 +187,47 @@ rb_set_capture_property(VALUE self, int id, VALUE value) /* * Get film current position in milliseconds or video capture timestamp. + * @overload millisecond + * @return [Number] Current position of the video file in milliseconds or video capture timestamp + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_POS_MSEC) */ VALUE rb_get_millisecond(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_POS_MSEC); } + /* * Set film current position in milliseconds or video capture timestamp. + * @overload millisecond=value + * @param value [Number] Position in milliseconds or video capture timestamp. + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_POS_MSEC) */ VALUE rb_set_millisecond(VALUE self, VALUE value) { return rb_set_capture_property(self, CV_CAP_PROP_POS_MSEC, value); } + /* * Get 0-based index of the frame to be decoded/captured next + * @overload frames + * @return [Number] 0-based index of the frame to be decoded/captured next + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_POS_FRAMES) */ VALUE rb_get_frames(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_POS_FRAMES); } + /* * Set 0-based index of the frame to be decoded/captured next + * @overload frames=value + * @param value [Number] 0-based index of the frame to be decoded/captured next + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_POS_FRAMES) */ VALUE rb_set_frames(VALUE self, VALUE value) @@ -297,7 +235,10 @@ rb_set_frames(VALUE self, VALUE value) return rb_set_capture_property(self, CV_CAP_PROP_POS_FRAMES, value); } /* - * Get relative position of video file (0 - start of the film, 1 - end of the film) + * Get relative position of video file + * @overload avi_ratio + * @return [Number] Relative position of video file (0: Start of the film, 1: End of the film) + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_POS_AVI_RATIO) */ VALUE rb_get_avi_ratio(VALUE self) @@ -305,15 +246,23 @@ rb_get_avi_ratio(VALUE self) return rb_get_capture_property(self, CV_CAP_PROP_POS_AVI_RATIO); } /* - * Set relative position of video file (0 - start of the film, 1 - end of the film) + * Set relative position of video file + * @overload avi_ratio=value + * @param value [Number] Relative position of video file (0: Start of the film, 1: End of the film) + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_POS_AVI_RATIO) */ VALUE rb_set_avi_ratio(VALUE self, VALUE value) { return rb_set_capture_property(self, CV_CAP_PROP_POS_AVI_RATIO, value); } + /* * Get size of frames in the video stream. + * @overload size + * @return [Size] Size of frames in the video stream. + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FRAME_WIDTH,CV_CAP_PROP_FRAME_HEIGHT) */ VALUE rb_get_size(VALUE self) @@ -329,8 +278,13 @@ rb_get_size(VALUE self) } return cCvSize::new_object(size); } + /* * Set size of frames in the video stream. + * @overload size=value + * @param value [CvSize] Size of frames + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_FRAME_WIDTH,CV_CAP_PROP_FRAME_HEIGHT) */ VALUE rb_set_size(VALUE self, VALUE value) @@ -347,56 +301,87 @@ rb_set_size(VALUE self, VALUE value) } return DBL2NUM(result); } + /* * Get width of frames in the video stream. + * @overload width + * @return [Number] Width of frames in the video stream. + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_FRAME_WIDTH) */ VALUE rb_get_width(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_FRAME_WIDTH); } + /* * Set width of frames in the video stream. + * @overload width=value + * @param value [Number] Width of frames + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_FRAME_WIDTH) */ VALUE rb_set_width(VALUE self, VALUE value) { return rb_set_capture_property(self, CV_CAP_PROP_FRAME_WIDTH, value); } + /* * Get height of frames in the video stream. + * @overload height + * @return [Number] Height of frames in the video stream. + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FRAME_HEIGHT) */ VALUE rb_get_height(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_FRAME_HEIGHT); } + /* * Set height of frames in the video stream. + * @overload height=value + * @param value [Number] Height of frames + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_FRAME_HEIGHT) */ VALUE rb_set_height(VALUE self, VALUE value) { return rb_set_capture_property(self, CV_CAP_PROP_FRAME_HEIGHT, value); } + /* * Get frame rate + * @overload fps + * @return [Number] Frame rate + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FPS) */ VALUE rb_get_fps(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_FPS); } + /* * Set frame rate + * @overload fps=value + * @param value [Number] Frame rate + * @return [Number] + * @opencv_func cvSetCaptureProperty (propId=CV_CAP_PROP_FPS) */ VALUE rb_set_fps(VALUE self, VALUE value) { return rb_set_capture_property(self, CV_CAP_PROP_FPS, value); } + /* - * Get 4character code of codec. see http://www.fourcc.org/ + * Get 4 character code of codec. see http://www.fourcc.org/ + * @overload fourcc + * @return [Number] Codec code + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FOURCC) */ VALUE rb_get_fourcc(VALUE self) @@ -406,48 +391,72 @@ rb_get_fourcc(VALUE self) sprintf(str, "%s", (char*)&fourcc); return rb_str_new2(str); } + /* * Get number of frames in video file. + * @overload frame_count + * @return [Number] Number of frames + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FRAME_COUNT) */ VALUE rb_get_frame_count(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_FRAME_COUNT); } + /* - * Get the format of the Mat objects returned by CvCapture#retrieve + * Get format of images returned by CvCapture#retrieve + * @overload format + * @return [Number] format + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_FORMAT) */ VALUE rb_get_format(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_FORMAT); } + /* * Get a backend-specific value indicating the current capture mode + * @overload mode + * @return [Number] Backend-specific value indicating the current capture mode + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_MODE) */ VALUE rb_get_mode(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_MODE); } + /* * Get brightness of the image (only for cameras) + * @overload brightness + * @return [Number] Brightness + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_BRIGHTNESS) */ VALUE rb_get_brightness(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_BRIGHTNESS); } + /* * Get contrast of the image (only for cameras) + * @overload contrast + * @return [Number] Contrast + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_CONTRAST) */ VALUE rb_get_contrast(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_CONTRAST); } + /* * Get saturation of the image (only for cameras) + * @overload saturation + * @return [Number] Saturation + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_SATURATION) */ VALUE rb_get_saturation(VALUE self) @@ -456,30 +465,45 @@ rb_get_saturation(VALUE self) } /* * Get hue of the image (only for cameras) + * @overload hue + * @return [Number] Hue + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_HUE) */ VALUE rb_get_hue(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_HUE); } + /* * Get gain of the image (only for cameras) + * @overload gain + * @return [Number] Gain + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_GAIN) */ VALUE rb_get_gain(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_GAIN); } + /* * Get exposure (only for cameras) + * @overload exposure + * @return [Number] Exposure + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_EXPOSURE) */ VALUE rb_get_exposure(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_EXPOSURE); } + /* * Get boolean flags indicating whether images should be converted to RGB + * @overload convert_rgb + * @return [Boolean] Whether images should be converted to RGB + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_CONVERT_RGB) */ VALUE rb_get_convert_rgb(VALUE self) @@ -493,14 +517,91 @@ rb_get_convert_rgb(VALUE self) } return flag ? Qtrue : Qfalse; } + /* - * Get TOWRITE (note: only supported by DC1394 v 2.x backend currently) + * Get rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently) + * @overload rectification + * @return [Number] Rectification flag + * @opencv_func cvGetCaptureProperty (propId=CV_CAP_PROP_RECTIFICATION) */ VALUE rb_get_rectification(VALUE self) { return rb_get_capture_property(self, CV_CAP_PROP_RECTIFICATION); } + +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvCapture", rb_cData); + + VALUE video_interface = rb_hash_new(); + /* + * :any, :mil, :vfw, :v4l, :v4l2, :fireware, :ieee1394, :dc1394, :cmu1394, + * :stereo, :tyzx, :tyzx_left, :tyzx_right, :tyzx_color, :tyzx_z, :qt, :qtuicktime + */ + rb_define_const(rb_klass, "INTERFACE", video_interface); + rb_hash_aset(video_interface, ID2SYM(rb_intern("any")), INT2FIX(CV_CAP_ANY)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("mil")), INT2FIX(CV_CAP_MIL)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("vfw")), INT2FIX(CV_CAP_VFW)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("v4l")), INT2FIX(CV_CAP_V4L)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("v4l2")), INT2FIX(CV_CAP_V4L2)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("fireware")), INT2FIX(CV_CAP_FIREWARE)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("ieee1394")), INT2FIX(CV_CAP_IEEE1394)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("dc1394")), INT2FIX(CV_CAP_DC1394)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("cmu1394")), INT2FIX(CV_CAP_CMU1394)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("stereo")), INT2FIX(CV_CAP_STEREO)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx")), INT2FIX(CV_CAP_TYZX)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_left")), INT2FIX(CV_TYZX_LEFT)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_right")), INT2FIX(CV_TYZX_RIGHT)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_color")), INT2FIX(CV_TYZX_COLOR)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("tyzx_z")), INT2FIX(CV_TYZX_Z)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("qt")), INT2FIX(CV_CAP_QT)); + rb_hash_aset(video_interface, ID2SYM(rb_intern("quicktime")), INT2FIX(CV_CAP_QT)); + + rb_define_singleton_method(rb_klass, "open", RUBY_METHOD_FUNC(rb_open), -1); + + rb_define_method(rb_klass, "grab", RUBY_METHOD_FUNC(rb_grab), 0); + rb_define_method(rb_klass, "retrieve", RUBY_METHOD_FUNC(rb_retrieve), 0); + rb_define_method(rb_klass, "query", RUBY_METHOD_FUNC(rb_query), 0); + rb_define_method(rb_klass, "millisecond", RUBY_METHOD_FUNC(rb_get_millisecond), 0); + rb_define_method(rb_klass, "millisecond=", RUBY_METHOD_FUNC(rb_set_millisecond), 1); + rb_define_method(rb_klass, "frames", RUBY_METHOD_FUNC(rb_get_frames), 0); + rb_define_method(rb_klass, "frames=", RUBY_METHOD_FUNC(rb_set_frames), 1); + rb_define_method(rb_klass, "avi_ratio", RUBY_METHOD_FUNC(rb_get_avi_ratio), 0); + rb_define_method(rb_klass, "avi_ratio=", RUBY_METHOD_FUNC(rb_set_avi_ratio), 1); + rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_get_size), 0); + rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); + rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_get_width), 0); + rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); + rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_get_height), 0); + rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); + rb_define_method(rb_klass, "fps", RUBY_METHOD_FUNC(rb_get_fps), 0); + rb_define_method(rb_klass, "fps=", RUBY_METHOD_FUNC(rb_set_fps), 1); + rb_define_method(rb_klass, "fourcc", RUBY_METHOD_FUNC(rb_get_fourcc), 0); + rb_define_method(rb_klass, "frame_count", RUBY_METHOD_FUNC(rb_get_frame_count), 0); + rb_define_method(rb_klass, "format", RUBY_METHOD_FUNC(rb_get_format), 0); + rb_define_method(rb_klass, "mode", RUBY_METHOD_FUNC(rb_get_mode), 0); + rb_define_method(rb_klass, "brightness", RUBY_METHOD_FUNC(rb_get_brightness), 0); + rb_define_method(rb_klass, "contrast", RUBY_METHOD_FUNC(rb_get_contrast), 0); + rb_define_method(rb_klass, "saturation", RUBY_METHOD_FUNC(rb_get_saturation), 0); + rb_define_method(rb_klass, "hue", RUBY_METHOD_FUNC(rb_get_hue), 0); + rb_define_method(rb_klass, "gain", RUBY_METHOD_FUNC(rb_get_gain), 0); + rb_define_method(rb_klass, "exposure", RUBY_METHOD_FUNC(rb_get_exposure), 0); + rb_define_method(rb_klass, "convert_rgb", RUBY_METHOD_FUNC(rb_get_convert_rgb), 0); + rb_define_method(rb_klass, "rectification", RUBY_METHOD_FUNC(rb_get_rectification), 0); +} + __NAMESPACE_END_CVCAPTURE __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvcapture.h b/ext/opencv/cvcapture.h index d8ef16a..70a0575 100644 --- a/ext/opencv/cvcapture.h +++ b/ext/opencv/cvcapture.h @@ -21,7 +21,7 @@ __NAMESPACE_BEGIN_CVCAPTURE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); void cvcapture_free(void *ptr); VALUE rb_open(int argc, VALUE *argv, VALUE klass); diff --git a/ext/opencv/cvchain.cpp b/ext/opencv/cvchain.cpp index 19cb1d2..ccec7d4 100644 --- a/ext/opencv/cvchain.cpp +++ b/ext/opencv/cvchain.cpp @@ -11,8 +11,7 @@ /* * Document-class: OpenCV::CvChain * - * Freeman chain code. - * CvMat#find_contours(:method => :code) + * Freeman chain code */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCHAIN @@ -31,45 +30,19 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvseq = rb_define_class_under(opencv, "CvSeq"); - * curve = rb_define_module_under(opencv, "Curve"); - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - VALUE cvseq = cCvSeq::rb_class(); - VALUE curve = mCurve::rb_module(); - - rb_klass = rb_define_class_under(opencv, "CvChain", cvseq); - rb_include_module(rb_klass, curve); - VALUE approx_chain_option = rb_hash_new(); - rb_define_const(rb_klass, "APPROX_CHAIN_OPTION", approx_chain_option); - rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("method")), ID2SYM(rb_intern("approx_simple"))); - rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("parameter")), rb_float_new(0)); - rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("minimal_perimeter")), INT2FIX(0)); - rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("recursive")), Qfalse); - - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "origin", RUBY_METHOD_FUNC(rb_origin), 0); - rb_define_method(rb_klass, "origin=", RUBY_METHOD_FUNC(rb_set_origin), 1); - rb_define_method(rb_klass, "codes", RUBY_METHOD_FUNC(rb_codes), 0); - rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); - rb_define_method(rb_klass, "approx_chains", RUBY_METHOD_FUNC(rb_approx_chains), -1); - rb_define_alias(rb_klass, "approx", "approx_chains"); -} - VALUE rb_allocate(VALUE klass) { return Data_Wrap_Struct(klass, mark_root_object, unregister_object, NULL); } +/* + * Create a new chain code + * @overload new(storage=nil) + * @param storage [CvMemStorage,nil] Sequence location (If storage is nil, allocates a new storage automatically) + * @return [CvChain] New CvChain instance + * @opencv_func cvCreateSeq (seq_flags=CV_SEQ_ELTYPE_CODE) + */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { @@ -96,10 +69,9 @@ rb_initialize(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * origin -> cvpoint - * - * Return Freeman chain code origin. + * Returns Freeman chain code origin + * @overload origin + * @return [CvPoint] Origin of the chain code */ VALUE rb_origin(VALUE self) @@ -108,10 +80,10 @@ rb_origin(VALUE self) } /* - * call-seq: - * origin = point -> self - * - * Set Freeman chain code origin. + * Set Freeman chain code origin + * @overload origin=value + * @param value [CvPoint] Origin of the chain code + * @return [CvChain] self */ VALUE rb_set_origin(VALUE self, VALUE origin) @@ -121,10 +93,11 @@ rb_set_origin(VALUE self, VALUE origin) } /* - * call-seq: - * codes -> array(contain fixnum) - * - * Return Freeman chain codes. + * Returns the chain codes + * @overload codes + * @return [Array] Chain codes + * @opencv_func cvStartReadChainPoints + * @opencv_func CV_READ_SEQ_ELEM */ VALUE rb_codes(VALUE self) @@ -147,10 +120,11 @@ rb_codes(VALUE self) } /* - * call-seq: - * points -> array(contain cvpoint) - * - * Return points that represent by Freeman chain code. + * Returns the points of the chain codes + * @overload points + * @return [Array] Points of the chain codes + * @opencv_func cvStartReadChainPoints + * @opencv_func CV_READ_CHAIN_POINT */ VALUE rb_points(VALUE self) @@ -174,26 +148,17 @@ rb_points(VALUE self) } /* - * call-seq: - * approx_chains([approx_chain_option]) -> cvcontour - * - * Approximates Freeman chain(s) with polygonal curve. - * approx_chain_option should be Hash include these keys. - * :method - Approximation method. - * :approx_none - translate all the points from the chain code into points; - * :approx_simple(default) - compress horizontal, vertical, and diagonal segments, that is, - * the function leaves only their ending points. - * :approx_tc89_l1 - * :approx_tc89_kcos - apply one of the flavors of Teh-Chin chain approximation algorithm. - * If set the difference between the current pixel and seed pixel is considered, - * otherwise difference between neighbor pixels is considered (the range is floating). - * :parameter - Method parameter (not used now). - * :minimal_perimeter (default 0) - * Approximates only those contours whose perimeters are not less than minimal_perimeter. Other chains are removed from the resulting structure. - * :recursive (default false) - * If not nil or false, the function approximates all chains that access can be obtained to - * from self by h_next or v_next links. If 0, the single chain is approximated. - * + * Approximates Freeman chains with a polygonal curve + * @overload approx_chain(options) + * @param options [Hash] Parameters + * @option options [Symbol] :method Approximation method (see the description of CvMat#find_contours) + * @option options [Number] :minimal_perimeter Approximates only those contours whose perimeters + * are not less than minimal_perimeter. Other chains are removed from the resulting structure. + * @option options [Boolean] :recursive Recursion flag. If it is true, the function approximates + * all chains that can be obtained from chain by using the h_next or v_next links. + * Otherwise, the single input chain is approximated. + * @return [CvSeq] Polygonal curve + * @opencv_func cvApproxChains */ VALUE rb_approx_chains(int argc, VALUE *argv, VALUE self) @@ -229,5 +194,40 @@ new_object() return cCvSeq::new_sequence(cCvChain::rb_class(), seq, T_FIXNUM, storage); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvseq = rb_define_class_under(opencv, "CvSeq"); + VALUE curve = rb_define_module_under(opencv, "Curve"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + VALUE cvseq = cCvSeq::rb_class(); + VALUE curve = mCurve::rb_module(); + + rb_klass = rb_define_class_under(opencv, "CvChain", cvseq); + rb_include_module(rb_klass, curve); + VALUE approx_chain_option = rb_hash_new(); + rb_define_const(rb_klass, "APPROX_CHAIN_OPTION", approx_chain_option); + rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("method")), ID2SYM(rb_intern("approx_simple"))); + rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("parameter")), rb_float_new(0)); + rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("minimal_perimeter")), INT2FIX(0)); + rb_hash_aset(approx_chain_option, ID2SYM(rb_intern("recursive")), Qfalse); + + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "origin", RUBY_METHOD_FUNC(rb_origin), 0); + rb_define_method(rb_klass, "origin=", RUBY_METHOD_FUNC(rb_set_origin), 1); + rb_define_method(rb_klass, "codes", RUBY_METHOD_FUNC(rb_codes), 0); + rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); + rb_define_method(rb_klass, "approx_chains", RUBY_METHOD_FUNC(rb_approx_chains), -1); + rb_define_alias(rb_klass, "approx", "approx_chains"); +} + __NAMESPACE_END_CVCHAIN __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvchain.h b/ext/opencv/cvchain.h index 49ed367..e0bb892 100644 --- a/ext/opencv/cvchain.h +++ b/ext/opencv/cvchain.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_CVCHAIN VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvcircle32f.cpp b/ext/opencv/cvcircle32f.cpp index ed44f09..2e8bbe3 100644 --- a/ext/opencv/cvcircle32f.cpp +++ b/ext/opencv/cvcircle32f.cpp @@ -26,27 +26,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvCircle32f", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); - rb_define_method(rb_klass, "radius", RUBY_METHOD_FUNC(rb_radius), 0); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - VALUE rb_allocate(VALUE klass) { @@ -55,7 +34,9 @@ rb_allocate(VALUE klass) } /* - * Return parameter on center. + * Returns center point of the circle + * @overload center + * @return [CvPoint2D32f] Center point of the circle */ VALUE rb_center(VALUE self) @@ -64,7 +45,9 @@ rb_center(VALUE self) } /* - * Return parameter on radius. + * Returns radius of the circle + * @overload radius + * @return [Number] Radius of the circle */ VALUE rb_radius(VALUE self) @@ -73,10 +56,10 @@ rb_radius(VALUE self) } /* - * call-seq: - * [index] - * - * Return value of index dimension. + * Accesses to parameters of the circle by array-like interface ([X-coordinate, Y-coordinate, radius]) + * @overload [] + * @param index [Integer] Index + * @return [Number] X-coordinate, Y-coordinate or radius of the circle */ VALUE rb_aref(VALUE self, VALUE index) @@ -98,6 +81,11 @@ rb_aref(VALUE self, VALUE index) return Qnil; } +/* + * Returns parameters of the circle as an array which contains [center, radius] + * @overload to_ary + * @return [Array] An array which contains [center, radius] + */ VALUE rb_to_ary(VALUE self) { @@ -112,5 +100,27 @@ new_object(CvCircle32f circle32f) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvCircle32f", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); + rb_define_method(rb_klass, "radius", RUBY_METHOD_FUNC(rb_radius), 0); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVCIRCLE32F __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvcircle32f.h b/ext/opencv/cvcircle32f.h index dbc366e..065c647 100644 --- a/ext/opencv/cvcircle32f.h +++ b/ext/opencv/cvcircle32f.h @@ -26,7 +26,7 @@ __NAMESPACE_BEGIN_CVCIRCLE32F VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvcondensation.cpp b/ext/opencv/cvcondensation.cpp deleted file mode 100644 index 271d9bd..0000000 --- a/ext/opencv/cvcondensation.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/************************************************************ - - cvcondensation.cpp - - - $Author: lsxi $ - - Copyright (C) 2005-2006 Masakazu Yonekura - -************************************************************/ -#include "cvcondensation.h" -/* - * Document-class: OpenCV::CvConDensation - * - */ -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVCONDENSATION - -VALUE rb_klass; - -VALUE -rb_class() -{ - return rb_klass; -} - -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvConDensation", rb_cObject); - rb_define_method(rb_klass, "dp", RUBY_METHOD_FUNC(rb_dp), 0); - rb_define_method(rb_klass, "mp", RUBY_METHOD_FUNC(rb_mp), 0); - rb_define_method(rb_klass, "dynamic_matrix", RUBY_METHOD_FUNC(rb_dynamic_matrix), 0); - rb_define_method(rb_klass, "confidence", RUBY_METHOD_FUNC(rb_confidence), 0); - rb_define_method(rb_klass, "cumulative", RUBY_METHOD_FUNC(rb_cumulative), 0); - rb_define_method(rb_klass, "state", RUBY_METHOD_FUNC(rb_state), 0); - rb_define_method(rb_klass, "samples_num", RUBY_METHOD_FUNC(rb_samples_num), 0); - rb_define_method(rb_klass, "init_sample_set", RUBY_METHOD_FUNC(rb_init_sample_set), 2); - rb_define_method(rb_klass, "update_by_time", RUBY_METHOD_FUNC(rb_update_by_time), 0); - rb_define_alias(rb_klass, "update", "update_by_time"); - rb_define_method(rb_klass, "each_sample", RUBY_METHOD_FUNC(rb_each_sample), 0); - rb_define_method(rb_klass, "calculate_confidence", RUBY_METHOD_FUNC(rb_calculate_confidence), 0); -} - -/* - * call-seq: - * dp -> int - * - * Return dimension of state vector - */ -VALUE -rb_dp(VALUE self) -{ - return INT2NUM(CVCONDENSATION(self)->DP); -} - -/* - * call-seq: - * mp -> int - * - * Return demension of measurement vector. - */ -VALUE -rb_mp(VALUE self) -{ - return INT2NUM(CVCONDENSATION(self)->MP); -} - -/* - * call-seq: - * dynamic_matrix -> mat - * - * Return matrix of the linear Dynamics system. - */ -VALUE -rb_dynamic_matrix(VALUE self) -{ - CvConDensation *cd = CVCONDENSATION(self); - CvMat* mat = NULL; - try { - mat = cvInitMatHeader(ALLOC(CvMat), cd->DP, cd->DP, CV_MAKETYPE(CV_32F, 1), cd->DynamMatr); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(cCvMat::rb_class(), mat, self); -} - -/* - * call-seq: - * confidence -> mat - * - * Return confidence for each sample. - */ -VALUE -rb_confidence(VALUE self) -{ - CvConDensation *cd = CVCONDENSATION(self); - CvMat* mat = NULL; - try { - mat = cvInitMatHeader(ALLOC(CvMat), cd->SamplesNum, 1, CV_MAKETYPE(CV_32F, 1), cd->flConfidence); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(cCvMat::rb_class(), mat, self); -} - -/* - * call-seq: - * cumulative -> mat - * - * Return cumulative confidence. - */ -VALUE -rb_cumulative(VALUE self) -{ - CvConDensation *cd = CVCONDENSATION(self); - CvMat* mat = NULL; - try { - mat = cvInitMatHeader(ALLOC(CvMat), cd->SamplesNum, 1, CV_MAKETYPE(CV_32F, 1), cd->flCumulative); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(cCvMat::rb_class(), mat, self); -} - -/* - * call-seq: - * state -> mat - * - * Return vector of state - */ -VALUE -rb_state(VALUE self) -{ - CvConDensation *cd = CVCONDENSATION(self); - CvMat* mat = NULL; - try { - mat = cvInitMatHeader(ALLOC(CvMat), cd->DP, 1, CV_MAKETYPE(CV_32F, 1), cd->State); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(cCvMat::rb_class(), mat, self); -} - -/* - * call-seq: - * samples_num -> int - * - * Return number of the samples - */ -VALUE -rb_samples_num(VALUE self) -{ - return INT2NUM(CVCONDENSATION(self)->SamplesNum); -} - -/* - * call-seq: - * init_sample_set(upper, lower) - * - * Initializes sample set for ConDensation algorithm. - * Fills the samples with values within specified(lower to upper) ranges. - */ -VALUE -rb_init_sample_set(VALUE self, VALUE lower, VALUE upper) -{ - CvConDensation *cd = CVCONDENSATION(self); - CvMat *lower_bound = CVMAT_WITH_CHECK(lower), *upper_bound = CVMAT_WITH_CHECK(upper), lb_stub, ub_stub; - int lower_type = lower_bound->type, upper_type = lower_bound->type; - try { - if (lower_type != CV_32FC1 || lower_bound->cols != 1) { - if (CV_MAT_DEPTH(lower_type) == CV_32F) { - lower_bound = cvReshape(lower_bound, &lb_stub, 1, lower_bound->rows * lower_bound->cols); - } - else { - lower = cCvMat::new_object(cvSize(lower_bound->rows * lower_bound->cols, 1), CV_MAKETYPE(CV_32S, 1)); - cvConvertScale(lower_bound, CVARR(lower)); - lower_bound = CVMAT(lower); - } - } - if (upper_type != CV_32FC1 || upper_bound->cols != 1) { - if (CV_MAT_DEPTH(upper_type) == CV_32F) { - upper_bound = cvReshape(upper_bound, &ub_stub, 1, upper_bound->rows * upper_bound->cols); - } - else { - upper = cCvMat::new_object(cvSize(upper_bound->rows * upper_bound->cols, 1), CV_MAKETYPE(CV_32F, 1)); - cvConvertScale(upper_bound, CVARR(upper)); - upper_bound = CVMAT(upper); - } - } - if (lower_bound->rows != cd->DP || upper_bound->rows != cd->DP) { - rb_raise(rb_eTypeError, "sample matrix step unmatch."); - } - cvConDensInitSampleSet(cd, lower_bound, upper_bound); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * update_by_time - * - * Estimates subsequent model state. - */ -VALUE -rb_update_by_time(VALUE self) -{ - try { - cvConDensUpdateByTime(CVCONDENSATION(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * each_sample {|mat| ... } - * - * Evaluate each sample by given block. - */ -VALUE -rb_each_sample(VALUE self) -{ - CvConDensation *cd = CVCONDENSATION(self); - if (rb_block_given_p()) { - try { - for (int i = 0; i < cd->SamplesNum; ++i) { - CvMat* mat = cvInitMatHeader(ALLOC(CvMat), cd->DP, 1, CV_MAKETYPE(CV_32F, 1), cd->flSamples[i]); - rb_yield(DEPEND_OBJECT(cCvMat::rb_class(), mat, self)); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - } - return self; -} - -/* - * call-seq: - * calculate_confidence {|value| ... } - * - * Evalute each sample by given block, then return value set to confidence. - */ -VALUE -rb_calculate_confidence(VALUE self) -{ - VALUE value; - CvConDensation *cd = CVCONDENSATION(self); - if (rb_block_given_p()) { - try { - for (int i = 0; i < cd->SamplesNum; ++i) { - CvMat* mat = cvInitMatHeader(ALLOC(CvMat), cd->DP, 1, CV_MAKETYPE(CV_32F, 1), cd->flSamples[i]); - value = rb_yield(DEPEND_OBJECT(cCvMat::rb_class(), mat, self)); - cd->flConfidence[i] = NUM2DBL(value); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - } - return self; -} - -__NAMESPACE_END_CVCONDENSATION -__NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvcondensation.h b/ext/opencv/cvcondensation.h deleted file mode 100644 index ff4b3e1..0000000 --- a/ext/opencv/cvcondensation.h +++ /dev/null @@ -1,49 +0,0 @@ -/************************************************************ - - cvcondensation.h - - - $Author: lsxi $ - - Copyright (C) 2005-2006 Masakazu Yonekura - -************************************************************/ -#ifndef RUBY_OPENCV_CVCONDENSATION_H -#define RUBY_OPENCV_CVCONDENSATION_H - -#include "opencv.h" - -#define __NAMESPACE_BEGIN_CVCONDENSATION namespace cCvConDensation { -#define __NAMESPACE_END_CVCONDENSATION } - -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVCONDENSATION - -VALUE rb_class(); -void define_ruby_class(); - -VALUE rb_dp(VALUE self); -VALUE rb_mp(VALUE self); -VALUE rb_dynamic_matrix(VALUE self); -VALUE rb_state(VALUE self); -VALUE rb_confidence(VALUE self); -VALUE rb_cumulative(VALUE self); -VALUE rb_samples_num(VALUE self); - -VALUE rb_init_sample_set(VALUE self, VALUE lower, VALUE upper); -VALUE rb_update_by_time(VALUE self); -VALUE rb_each_sample(VALUE self); -VALUE rb_calculate_confidence(VALUE self); - -__NAMESPACE_END_CVCONDENSATION - -inline CvConDensation* -CVCONDENSATION(VALUE object) -{ - CvConDensation *ptr; - Data_Get_Struct(object, CvConDensation, ptr); - return ptr; -} - -__NAMESPACE_END_OPENCV - -#endif // RUBY_OPENCV_CVCONDENSATION_H diff --git a/ext/opencv/cvconnectedcomp.cpp b/ext/opencv/cvconnectedcomp.cpp index cfe5fd1..fb10309 100644 --- a/ext/opencv/cvconnectedcomp.cpp +++ b/ext/opencv/cvconnectedcomp.cpp @@ -10,17 +10,9 @@ #include "cvconnectedcomp.h" /* * Document-class: OpenCV::CvConnectedComp - * + * + * Connected component * see CvMat#flood_fill - * - * C structure is here. - * typedef struct CvConnectedComp - * { - * double area; - * CvScalar value; - * CvRect rect; - * CvSeq* contour; - * } CvConnectedComp; */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCONNECTEDCOMP @@ -33,28 +25,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvConnectedComp", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "area", RUBY_METHOD_FUNC(rb_area), 0); - rb_define_method(rb_klass, "value", RUBY_METHOD_FUNC(rb_value), 0); - rb_define_method(rb_klass, "rect", RUBY_METHOD_FUNC(rb_rect), 0); - rb_define_method(rb_klass, "rect=", RUBY_METHOD_FUNC(rb_set_rect), 1); - rb_define_method(rb_klass, "contour", RUBY_METHOD_FUNC(rb_contour), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -62,6 +32,15 @@ rb_allocate(VALUE klass) return Data_Make_Struct(klass, CvConnectedComp, 0, -1, ptr); } +/* + * Constructor + * @overload new(area = nil, value = nil, rect = nil, contour = nil) + * @param area [Number] Area of the segmented component + * @param value [CvScalar] Average color of the connected component + * @param rect [CvRect] ROI of the segmented component + * @param contour [CvSeq] Optional component boundary + * @return [CvConnectedComp] self + */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { @@ -80,7 +59,9 @@ rb_initialize(int argc, VALUE *argv, VALUE self) } /* - * Return area of connected component. + * Returns area of connected component + * @overload area + * @return [Number] Area of the connected component */ VALUE rb_area(VALUE self) @@ -90,6 +71,8 @@ rb_area(VALUE self) /* * Return average color of the connected component. + * @overload value + * @return [CvScalar] Average color of the connected component */ VALUE rb_value(VALUE self) @@ -98,7 +81,9 @@ rb_value(VALUE self) } /* - * Return ROI of the component. + * Return ROI of the segmented component + * @overload rect + * @return [CvRect] ROI of the segmented component */ VALUE rb_rect(VALUE self) @@ -107,7 +92,10 @@ rb_rect(VALUE self) } /* - * Set ROI of the component. + * Set ROI of the segmented component + * @overload rect=value + * @param value [CvRect] ROI to set + * @return [CvRect] ROI of the segmented component */ VALUE rb_set_rect(VALUE self, VALUE rect) @@ -117,7 +105,9 @@ rb_set_rect(VALUE self, VALUE rect) } /* - * Return optional component boundary + * Returns optional component boundary + * @overload contour + * @return [CvContour] Optional component boundary */ VALUE rb_contour(VALUE self) @@ -139,5 +129,28 @@ new_object(CvConnectedComp comp) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvConnectedComp", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "area", RUBY_METHOD_FUNC(rb_area), 0); + rb_define_method(rb_klass, "value", RUBY_METHOD_FUNC(rb_value), 0); + rb_define_method(rb_klass, "rect", RUBY_METHOD_FUNC(rb_rect), 0); + rb_define_method(rb_klass, "rect=", RUBY_METHOD_FUNC(rb_set_rect), 1); + rb_define_method(rb_klass, "contour", RUBY_METHOD_FUNC(rb_contour), 0); +} + __NAMESPACE_END_CVCONNECTEDCOMP __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvconnectedcomp.h b/ext/opencv/cvconnectedcomp.h index c0216d8..beadd29 100644 --- a/ext/opencv/cvconnectedcomp.h +++ b/ext/opencv/cvconnectedcomp.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVCONNECTEDCOMP VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvcontour.cpp b/ext/opencv/cvcontour.cpp index 96d95e0..6be883d 100644 --- a/ext/opencv/cvcontour.cpp +++ b/ext/opencv/cvcontour.cpp @@ -11,8 +11,9 @@ /* * Document-class: OpenCV::CvContour * - * Contour. - * CvMat#find_contours + * Contour + * + * @see CvMat#find_contours */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCONTOUR @@ -33,56 +34,19 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvseq = rb_define_class_under(opencv, "CvSeq"); - * curve = rb_define_module_under(opencv, "Curve"); - * pointset = rb_define_module_under(opencv, "PointSet"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - VALUE cvseq = cCvSeq::rb_class(); - VALUE curve = mCurve::rb_module(); - VALUE pointset = mPointSet::rb_module(); - - rb_klass = rb_define_class_under(opencv, "CvContour", cvseq); - rb_include_module(rb_klass, curve); - rb_include_module(rb_klass, pointset); - - rb_define_alloc_func(rb_klass, rb_allocate); - - VALUE approx_option = rb_hash_new(); - rb_define_const(rb_klass, "APPROX_OPTION", approx_option); - rb_hash_aset(approx_option, ID2SYM(rb_intern("method")), INT2FIX(CV_POLY_APPROX_DP)); - rb_hash_aset(approx_option, ID2SYM(rb_intern("accuracy")), rb_float_new(1.0)); - rb_hash_aset(approx_option, ID2SYM(rb_intern("recursive")), Qfalse); - - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "rect", RUBY_METHOD_FUNC(rb_rect), 0); - rb_define_method(rb_klass, "color", RUBY_METHOD_FUNC(rb_color), 0); - rb_define_method(rb_klass, "color=", RUBY_METHOD_FUNC(rb_set_color), 1); - rb_define_method(rb_klass, "reserved", RUBY_METHOD_FUNC(rb_reserved), 0); - rb_define_method(rb_klass, "approx_poly", RUBY_METHOD_FUNC(rb_approx_poly), -1); - rb_define_alias(rb_klass, "approx", "approx_poly"); - rb_define_method(rb_klass, "bounding_rect", RUBY_METHOD_FUNC(rb_bounding_rect), 0); - rb_define_method(rb_klass, "create_tree", RUBY_METHOD_FUNC(rb_create_tree), -1); - rb_define_method(rb_klass, "in?", RUBY_METHOD_FUNC(rb_in_q), 1); - rb_define_method(rb_klass, "measure_distance", RUBY_METHOD_FUNC(rb_measure_distance), 1); - rb_define_method(rb_klass, "point_polygon_test", RUBY_METHOD_FUNC(rb_point_polygon_test), 2); -} - VALUE rb_allocate(VALUE klass) { return Data_Wrap_Struct(klass, mark_root_object, unregister_object, NULL); } +/* + * Constructor + * @overload new(storage = nil) + * @param [CvMemStorage] storage Sequence location + * @return [CvContour] self + * @opencv_func cvCreateSeq + */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { @@ -107,18 +71,33 @@ rb_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* + * Returns bounding box of the contour + * @overload rect + * @return [CvRect] Bounding box of the contour + */ VALUE rb_rect(VALUE self) { return cCvRect::new_object(CVCONTOUR(self)->rect); } +/* + * Returns color of the contour + * @overload color + * @return [Number] Color of the contour + */ VALUE rb_color(VALUE self) { return INT2NUM(CVCONTOUR(self)->color); } +/* + * Set color of the contour + * @overload color=value + * @param value [Number] Color of the contour + */ VALUE rb_set_color(VALUE self, VALUE color) { @@ -126,6 +105,11 @@ rb_set_color(VALUE self, VALUE color) return self; } +/* + * Returns reserved region values of the contour + * @overload reserved + * @return [Array] Reserved region values of the contour + */ VALUE rb_reserved(VALUE self) { @@ -136,17 +120,18 @@ rb_reserved(VALUE self) } /* - * call-seq: - * approx_poly(approx_poly_option) -> cvcontour - * - * Approximates polygonal curve(s) with desired precision. - * approx_poly_option should be Hash include these keys. - * :method - Approximation method. - * :dp - corresponds to Douglas-Peucker algorithm. - * :accuracy - approximation accuracy. (high-accuracy will create more simple contours) - * :recursive - (default false) - * If not nil or false, the function approximates all chains that access can be obtained to - * from self by h_next or v_next links. If 0, approximated this one. + * Approximates polygonal curves with desired precision + * @overload approx_poly(options) + * @param options [Hash] Parameters + * @option options [Symbol] :method Approximation method (default :dp) + * * :dp - Douglas-Peucker algorithm. + * @option options [Number] :accuracy Parameter specifying the approximation accuracy. + * This is the maximum distance between the original curve and its approximation. + * @option options [Boolean] :recursive Recursion flag. If true, the function approximates + * all the contours accessible from curve by h_next and v_next links. + * @return [CvContour] Result of the approximation + * @return [nil] Approximation faied + * @opencv_func cvApproxPoly */ VALUE rb_approx_poly(int argc, VALUE *argv, VALUE self) @@ -167,11 +152,10 @@ rb_approx_poly(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * bounding_rect -> rect - * * Calculates up-right bounding rectangle of point set. - * + * @overload bounding_rect + * @return [CvRect] Bounding rectangle + * @opencv_func cvBoundingRect */ VALUE rb_bounding_rect(VALUE self) @@ -187,14 +171,12 @@ rb_bounding_rect(VALUE self) } /* - * call-seq: - * create_tree([threshold = 0.0]) -> cvcontourtree - * - * Creates hierarchical representation of contour. - * If the parameter threshold is less than or equal to 0, - * the method creates full binary tree representation. - * If the threshold is greater than 0, the function creates - * representation with the precision threshold: + * Creates hierarchical representation of contour + * @overload create_tree(threshold = 0.0) + * @param threshold [Number] If <= 0, the method creates full binary tree representation. + * If > 0, the method creates representation with the precision threshold. + * @return [CvContourTree] Hierarchical representation of the contour + * @opencv_func cvCreateContourTree */ VALUE rb_create_tree(int argc, VALUE *argv, VALUE self) @@ -213,10 +195,14 @@ rb_create_tree(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * in?(point) -> true or nil or false - * - * Determines whether the point is inside contour(true), outside(false) or lies on an edge(nil). + * Performs a point-in-contour test. + * The method determines whether the point is inside a contour, outside, + * or lies on an edge (or coincides with a vertex). + * @overload in?(point) + * @param point [CvPoint2D32f] Point tested against the contour + * @return [Boolean] If the point is inside, returns true. If outside, returns false. + * If lies on an edge, returns nil. + * @opencv_func cvPointPolygonTest */ VALUE rb_in_q(VALUE self, VALUE point) @@ -232,10 +218,11 @@ rb_in_q(VALUE self, VALUE point) } /* - * call-seq: - * measure_distance(point) -> float - * - * Return distance between the point and the nearest contour edge. + * Calculates distance between a point and the nearest contour edgex + * @overload measure_distance(point) + * @param point [CvPoint2D32f] Point tested against the contour + * @return Signed distance between the point and the nearest contour edge + * @opencv_func cvPointPolygonTest */ VALUE rb_measure_distance(VALUE self, VALUE point) @@ -251,11 +238,14 @@ rb_measure_distance(VALUE self, VALUE point) } /* - * call-seq: - * point_polygon_test(point, measure_dist) -> float - * * Determines whether the point is inside a contour, outside, or lies on an edge (or coinsides with a vertex). - * It returns positive, negative or zero value, correspondingly. When measure_dist = false or 0, the return value is +1, -1 and 0, respectively. When measure_dist = true or 1, it is a signed distance between the point and the nearest contour edge. + * @overload point_polygon_test(point, measure_dist) + * @param point [CvPoint2D32f] Point tested against the contour + * @param measure_dist [Boolean] If true, the method estimates the signed distance from the point to + * the nearest contour edge. Otherwise, the function only checks if the point is inside a contour or not. + * @return [Number] When measure_dist = false, the return value is +1, -1 and 0, respectively. + * When measure_dist = true, it is a signed distance between the point and the nearest contour edge. + * @opencv_func cvPointPolygonTest */ VALUE rb_point_polygon_test(VALUE self, VALUE point, VALUE measure_dist) @@ -291,6 +281,52 @@ VALUE new_object() return object; } + +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvseq = rb_define_class_under(opencv, "CvSeq"); + VALUE curve = rb_define_module_under(opencv, "Curve"); + VALUE pointset = rb_define_module_under(opencv, "PointSet"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + VALUE cvseq = cCvSeq::rb_class(); + VALUE curve = mCurve::rb_module(); + VALUE pointset = mPointSet::rb_module(); + + rb_klass = rb_define_class_under(opencv, "CvContour", cvseq); + rb_include_module(rb_klass, curve); + rb_include_module(rb_klass, pointset); + + rb_define_alloc_func(rb_klass, rb_allocate); + + VALUE approx_option = rb_hash_new(); + rb_define_const(rb_klass, "APPROX_OPTION", approx_option); + rb_hash_aset(approx_option, ID2SYM(rb_intern("method")), INT2FIX(CV_POLY_APPROX_DP)); + rb_hash_aset(approx_option, ID2SYM(rb_intern("accuracy")), rb_float_new(1.0)); + rb_hash_aset(approx_option, ID2SYM(rb_intern("recursive")), Qfalse); + + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "rect", RUBY_METHOD_FUNC(rb_rect), 0); + rb_define_method(rb_klass, "color", RUBY_METHOD_FUNC(rb_color), 0); + rb_define_method(rb_klass, "color=", RUBY_METHOD_FUNC(rb_set_color), 1); + rb_define_method(rb_klass, "reserved", RUBY_METHOD_FUNC(rb_reserved), 0); + rb_define_method(rb_klass, "approx_poly", RUBY_METHOD_FUNC(rb_approx_poly), -1); + rb_define_alias(rb_klass, "approx", "approx_poly"); + rb_define_method(rb_klass, "bounding_rect", RUBY_METHOD_FUNC(rb_bounding_rect), 0); + rb_define_method(rb_klass, "create_tree", RUBY_METHOD_FUNC(rb_create_tree), -1); + rb_define_method(rb_klass, "in?", RUBY_METHOD_FUNC(rb_in_q), 1); + rb_define_method(rb_klass, "measure_distance", RUBY_METHOD_FUNC(rb_measure_distance), 1); + rb_define_method(rb_klass, "point_polygon_test", RUBY_METHOD_FUNC(rb_point_polygon_test), 2); +} + __NAMESPACE_END_CVCONTOUR __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvcontour.h b/ext/opencv/cvcontour.h index 79f021f..4654654 100644 --- a/ext/opencv/cvcontour.h +++ b/ext/opencv/cvcontour.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_CVCONTOUR VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); VALUE rb_rect(VALUE self); diff --git a/ext/opencv/cvcontourtree.cpp b/ext/opencv/cvcontourtree.cpp index 90a1435..bb8b833 100644 --- a/ext/opencv/cvcontourtree.cpp +++ b/ext/opencv/cvcontourtree.cpp @@ -11,15 +11,9 @@ /* * Document-class: OpenCV::CvContourTree * - * Contour tree. CvContour#create_tree + * Contour tree * - * C structure is here. - * typedef struct CvContourTree { - * CV_SEQUENCE_FIELDS() - * CvPoint p1; - * CvPoint p2; - * } CvContourTree; - * + * @see CvContour#create_tree */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCONTOURTREE @@ -32,32 +26,22 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvseq = rb_define_class_under(opencv, "CvSeq"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - VALUE cvseq = cCvSeq::rb_class(); - - rb_klass = rb_define_class_under(opencv, "CvContourTree", cvseq); - rb_define_method(rb_klass, "p1", RUBY_METHOD_FUNC(rb_p1), 0); - rb_define_method(rb_klass, "p2", RUBY_METHOD_FUNC(rb_p2), 0); - rb_define_method(rb_klass, "contour", RUBY_METHOD_FUNC(rb_contour), 1); -} - +/* + * Returns the first point of the binary tree root segment + * @overload p1 + * @return [CvPoint] First point of the binary tree root segment + */ VALUE rb_p1(VALUE self) { return REFER_OBJECT(cCvPoint::rb_class(), &CVCONTOURTREE(self)->p1, self); } +/* + * Returns the last point of the binary tree root segment + * @overload p2 + * @return [CvPoint] Last point of the binary tree root segment + */ VALUE rb_p2(VALUE self) { @@ -65,12 +49,14 @@ rb_p2(VALUE self) } /* - * call-seq: - * contour([criteria = 0]) -> cvcontour - * * Restores the contour from its binary tree representation. - * The parameter criteria determines the accuracy and/or the number of tree levels + * + * The parameter +criteria+ determines the accuracy and/or the number of tree levels * used for reconstruction, so it is possible to build approximated contour. + * @overload contour(criteria = 0) + * @param criteria [Integer] Criteria, where to stop reconstruction + * @return [CvContour] Contour tree + * @opencv_func cvContourFromContourTree */ VALUE rb_contour(VALUE self, VALUE criteria) @@ -87,5 +73,24 @@ rb_contour(VALUE self, VALUE criteria) return cCvSeq::new_sequence(cCvContour::rb_class(), contour, cCvPoint::rb_class(), storage); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvseq = rb_define_class_under(opencv, "CvSeq"); +#endif + if (rb_klass) + return; + VALUE opencv = rb_module_opencv(); + VALUE cvseq = cCvSeq::rb_class(); + + rb_klass = rb_define_class_under(opencv, "CvContourTree", cvseq); + rb_define_method(rb_klass, "p1", RUBY_METHOD_FUNC(rb_p1), 0); + rb_define_method(rb_klass, "p2", RUBY_METHOD_FUNC(rb_p2), 0); + rb_define_method(rb_klass, "contour", RUBY_METHOD_FUNC(rb_contour), 1); +} + __NAMESPACE_END_CVCONTOURTREE __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvcontourtree.h b/ext/opencv/cvcontourtree.h index 685500f..570fcde 100644 --- a/ext/opencv/cvcontourtree.h +++ b/ext/opencv/cvcontourtree.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_CVCONTOURTREE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_p1(VALUE self); VALUE rb_p2(VALUE self); diff --git a/ext/opencv/cvconvexitydefect.cpp b/ext/opencv/cvconvexitydefect.cpp index d8ddfdc..e810e1a 100644 --- a/ext/opencv/cvconvexitydefect.cpp +++ b/ext/opencv/cvconvexitydefect.cpp @@ -11,15 +11,7 @@ /* * Document-class: OpenCV::CvConvexityDefect * - * Convexity. - * C structure is here. - * typedef struct CvConvexityDefect { - * CvPoint* start; - * CvPoint* end; - * CvPoint* depth_point; - * float depth; - * } CvConvexityDefect; - * + * Convexity defect */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVCONVEXITYDEFECT @@ -32,30 +24,10 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvConvexityDefect", rb_cObject); - rb_define_method(rb_klass, "start", RUBY_METHOD_FUNC(rb_start), 0); - rb_define_method(rb_klass, "end", RUBY_METHOD_FUNC(rb_end), 0); - rb_define_method(rb_klass, "depth_point", RUBY_METHOD_FUNC(rb_depth_point), 0); - rb_define_method(rb_klass, "depth", RUBY_METHOD_FUNC(rb_depth), 0); -} - /* - * call-seq: - * start -> cvpoint - * - * Return start point as CvPoint. + * Returns the point of the contour where the defect begins + * @overload start + * @return [CvPoint] Start point of the contour */ VALUE rb_start(VALUE self) @@ -64,10 +36,9 @@ rb_start(VALUE self) } /* - * call-seq: - * end -> cvpoint - * - * Return end point as CvPoint. + * Returns the point of the contour where the defect ends + * @overload end + * @return [CvPoint] End point of the contour */ VALUE rb_end(VALUE self) @@ -76,10 +47,9 @@ rb_end(VALUE self) } /* - * call-seq: - * depth_point -> cvpoint - * - * Return depth point as CvPoint. + * Returns the farthest from the convex hull point within the defect + * @overload depth_point + * @return [CvPoint] The farthest from the convex hull point within the defect */ VALUE rb_depth_point(VALUE self) @@ -88,10 +58,9 @@ rb_depth_point(VALUE self) } /* - * call-seq: - * depth -> float - * - * Return depth. + * Returns distance between the farthest point and the convex hull + * @overload depth + * @return [Number] Distance between the farthest point and the convex hull */ VALUE rb_depth(VALUE self) @@ -99,5 +68,25 @@ rb_depth(VALUE self) return rb_float_new(CVCONVEXITYDEFECT(self)->depth); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvConvexityDefect", rb_cObject); + rb_define_method(rb_klass, "start", RUBY_METHOD_FUNC(rb_start), 0); + rb_define_method(rb_klass, "end", RUBY_METHOD_FUNC(rb_end), 0); + rb_define_method(rb_klass, "depth_point", RUBY_METHOD_FUNC(rb_depth_point), 0); + rb_define_method(rb_klass, "depth", RUBY_METHOD_FUNC(rb_depth), 0); +} + __NAMESPACE_END_CVCONVEXITYDEFECT __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvconvexitydefect.h b/ext/opencv/cvconvexitydefect.h index 60c3473..6c7df25 100644 --- a/ext/opencv/cvconvexitydefect.h +++ b/ext/opencv/cvconvexitydefect.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVCONVEXITYDEFECT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_start(VALUE self); VALUE rb_end(VALUE self); diff --git a/ext/opencv/cverror.cpp b/ext/opencv/cverror.cpp index 1c7bb04..8b1edb3 100644 --- a/ext/opencv/cverror.cpp +++ b/ext/opencv/cverror.cpp @@ -11,51 +11,7 @@ /* * Document-class: OpenCV::CvError * - * =Internal OpenCV errors - * - * This module collect OpenCV internal error wrapper classes. - * * CvStatusBackTrace - * * CvStatusError - * * CvStatusInternal - * * CvStatusNoMemory - * * CvStatusBadArgument - * * CvStatusNoConverge - * * CvStatusAutoTrace - * - * * CvHeaderIsNull - * * CvBadImageSize - * * CvBadOffset - * * CvBadDataPointer - * * CvBadStep - * * CvBadModelOrChannelSequence - * * CvBadNumChannels - * * CvBadAlphaChannel - * * CvBadOrder - * * CvBadOrigin - * * CvBadAlign - * * CvBadCallback - * * CvBadTileSize - * * CvBadCOI - * * CvBadROISize - * - * * CvMaskIsTiled - * - * * CvStatusNullPointer - * * CvStatusVectorLengthError - * * CvStatusFilterStructContentError - * * CvStatusKernelStructContentError - * * CvStatusFilterOffsetError - * - * * CvStatusBadSize - * * CvStatusDivByZero - * * CvStatusInplaceNotSupported - * * CvStatusObjectNotFound - * * CvStatusUnmatchedFormant - * * CvStatusUnsupportedFormats - * * CvStatusOutOfRange - * * CvStatusParseError - * * CvStatusNotImplemented - * * CvStsBadMemoryBlock + * OpenCV errors */ __NAMESPACE_BEGIN_OPENCV @@ -78,18 +34,32 @@ rb_class() return rb_klass; } -void define_ruby_class() +VALUE +by_code(int error_code) { + VALUE klass = 0; + st_lookup(cv_error, (st_data_t)error_code, (st_data_t*)&klass); + return klass ? klass : rb_eStandardError; +} + +void +raise(cv::Exception e) +{ + rb_raise(by_code(e.code), "%s", e.what()); +} + +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + if (rb_klass) return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvError", rb_eStandardError); REGISTER_CVERROR("CvStsBackTrace", CV_StsBackTrace); REGISTER_CVERROR("CvStsError", CV_StsError); @@ -140,20 +110,6 @@ void define_ruby_class() REGISTER_CVERROR("CvGpuNotSupported", CV_GpuNotSupported); REGISTER_CVERROR("CvGpuApiCallError", CV_GpuApiCallError); } - -VALUE -by_code(int error_code) -{ - VALUE klass = 0; - st_lookup(cv_error, (st_data_t)error_code, (st_data_t*)&klass); - return klass ? klass : rb_eStandardError; -} - -void -raise(cv::Exception e) -{ - rb_raise(by_code(e.code), "%s", e.what()); -} __NAMESPACE_END_CVERROR __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cverror.h b/ext/opencv/cverror.h index 789191d..aba2cf8 100644 --- a/ext/opencv/cverror.h +++ b/ext/opencv/cverror.h @@ -18,7 +18,7 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVERROR -void define_ruby_class(); +void init_ruby_class(); VALUE by_code(int error_code); void raise(cv::Exception e); diff --git a/ext/opencv/cvfeaturetree.cpp b/ext/opencv/cvfeaturetree.cpp index 316da98..a559e8b 100644 --- a/ext/opencv/cvfeaturetree.cpp +++ b/ext/opencv/cvfeaturetree.cpp @@ -48,30 +48,12 @@ rb_allocate(VALUE klass) rb_release_feature_tree, ptr); } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvFeatureTree", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 1); - - rb_define_method(rb_klass, "find_features", RUBY_METHOD_FUNC(rb_find_features), 3); -} - /* - * call-seq: - * new(desc) - * * Create a new kd-tree + * @overload new(desc) + * @param desc [CvMat] Descriptors + * @return [CvFeatureTree] self + * @opencv_func cvCreateKDTree */ VALUE rb_initialize(VALUE self, VALUE desc) @@ -91,18 +73,15 @@ rb_initialize(VALUE self, VALUE desc) } /* - * call-seq: - * find_features(desc, rows, cols, k, emax) -> array(results, dist) - * * Find features from kd-tree - * - * desc: m x d matrix of (row-)vectors to find the nearest neighbors of. - * k: The number of neighbors to find. - * emax: The maximum number of leaves to visit. - * - * return - * results: m x k set of row indices of matching vectors (referring to matrix passed to cvCreateFeatureTree). Contains -1 in some columns if fewer than k neighbors found. - * dist: m x k matrix of distances to k nearest neighbors. + * @overload find_features(desc, k, emax) + * @param desc [CvMat] m x d matrix of (row-)vectors to find the nearest neighbors of. + * @param k [Integer] The number of neighbors to find. + * @param emax [Integer] The maximum number of leaves to visit. + * @return [Array] Array of [results, dist] + * - results: m x k set of row indices of matching vectors (referring to matrix passed to cvCreateFeatureTree). Contains -1 in some columns if fewer than k neighbors found. + * - dist: m x k matrix of distances to k nearest neighbors. + * @opencv_func cvFindFeatures */ VALUE rb_find_features(VALUE self, VALUE desc, VALUE k, VALUE emax) @@ -120,6 +99,25 @@ rb_find_features(VALUE self, VALUE desc, VALUE k, VALUE emax) return rb_assoc_new(results, dist); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvFeatureTree", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 1); + + rb_define_method(rb_klass, "find_features", RUBY_METHOD_FUNC(rb_find_features), 3); +} + __NAMESPACE_END_OPENCV __NAMESPACE_END_CVFEATURETREE diff --git a/ext/opencv/cvfeaturetree.h b/ext/opencv/cvfeaturetree.h index 5389aa9..9ddd012 100644 --- a/ext/opencv/cvfeaturetree.h +++ b/ext/opencv/cvfeaturetree.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVFEATURETREE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(VALUE self, VALUE desc); VALUE rb_find_features(VALUE self, VALUE desc, VALUE k, VALUE emax); diff --git a/ext/opencv/cvfont.cpp b/ext/opencv/cvfont.cpp index ca3a428..236593a 100644 --- a/ext/opencv/cvfont.cpp +++ b/ext/opencv/cvfont.cpp @@ -39,48 +39,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvFont", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - VALUE face = rb_hash_new(); - rb_define_const(rb_klass, "FACE", face); - rb_hash_aset(face, ID2SYM(rb_intern("simplex")), INT2FIX(CV_FONT_HERSHEY_SIMPLEX)); - rb_hash_aset(face, ID2SYM(rb_intern("plain")), INT2FIX(CV_FONT_HERSHEY_PLAIN)); - rb_hash_aset(face, ID2SYM(rb_intern("duplex")), INT2FIX(CV_FONT_HERSHEY_DUPLEX)); - rb_hash_aset(face, ID2SYM(rb_intern("triplex")), INT2FIX(CV_FONT_HERSHEY_TRIPLEX)); - rb_hash_aset(face, ID2SYM(rb_intern("complex_small")), INT2FIX(CV_FONT_HERSHEY_COMPLEX_SMALL)); - rb_hash_aset(face, ID2SYM(rb_intern("script_simplex")), INT2FIX(CV_FONT_HERSHEY_SCRIPT_SIMPLEX)); - rb_hash_aset(face, ID2SYM(rb_intern("script_complex")), INT2FIX(CV_FONT_HERSHEY_SCRIPT_COMPLEX)); - - VALUE default_option = rb_hash_new(); - rb_define_const(rb_klass, "FONT_OPTION", default_option); - rb_hash_aset(default_option, ID2SYM(rb_intern("hscale")), rb_float_new(1.0)); - rb_hash_aset(default_option, ID2SYM(rb_intern("vscale")), rb_float_new(1.0)); - rb_hash_aset(default_option, ID2SYM(rb_intern("shear")), INT2FIX(0)); - rb_hash_aset(default_option, ID2SYM(rb_intern("thickness")), INT2FIX(1)); - rb_hash_aset(default_option, ID2SYM(rb_intern("line_type")), INT2FIX(8)); - - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "face", RUBY_METHOD_FUNC(rb_face), 0); - rb_define_method(rb_klass, "hscale", RUBY_METHOD_FUNC(rb_hscale), 0); - rb_define_method(rb_klass, "vscale", RUBY_METHOD_FUNC(rb_vscale), 0); - rb_define_method(rb_klass, "shear", RUBY_METHOD_FUNC(rb_shear), 0); - rb_define_method(rb_klass, "thickness", RUBY_METHOD_FUNC(rb_thickness), 0); - rb_define_method(rb_klass, "line_type", RUBY_METHOD_FUNC(rb_line_type), 0); - rb_define_method(rb_klass, "italic", RUBY_METHOD_FUNC(rb_italic), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -88,46 +46,32 @@ rb_allocate(VALUE klass) return Data_Make_Struct(klass, CvFont, 0, -1, ptr); } - /* - * call-seq: - * CvFont.new(face[,font_option]) -> font + * Create font object + * @overload new(face, font_option = nil) + * @param face [Symbol] Font name identifier. Only a subset of Hershey fonts (http://sources.isc.org/utils/misc/hershey-font.txt) are supported now: + * - :simplex - normal size sans-serif font + * - :plain - small size sans-serif font + * - :duplex - normal size sans-serif font (more complex than :simplex) + * - :complex - normal size serif font + * - :triplex - normal size serif font (more complex than :complex) + * - :complex_small - smaller version of :complex + * - :script_simplex - hand-writing style font + * - :script_complex - more complex variant of :script_simplex * - * Create font object. - * face is font name identifier. - * - * Only a subset of Hershey fonts (http://sources.isc.org/utils/misc/hershey-font.txt) are supported now: - * * :simplex - normal size sans-serif font - * * :plain - small size sans-serif font - * * :duplex - normal size sans-serif font (more complex than :simplex) - * * :complex - normal size serif font - * * :triplex - normal size serif font (more complex than :complex) - * * :complex_small - smaller version of :complex - * * :script_simplex - hand-writing style font - * * :script_complex - more complex variant of :script_simplex + * @param font_option [Hash] should be Hash include these keys. + * @option font_option [Number] :hscale Horizontal scale. If equal to 1.0, the characters have the original width depending on the font type. If equal to 0.5, the characters are of half the original width. + * @option font_option [Number] :vscale Vertical scale. If equal to 1.0, the characters have the original height depending on the font type. If equal to 0.5, the characters are of half the original height. + * @option font_option [Number] :shear Approximate tangent of the character slope relative to the vertical line. Zero value means a non-italic font, 1.0f means ~45 degree slope, etc. + * @option font_option [Number] :thickness Thickness of the text strokes. + * @option font_option [Number] :line_type Type of the strokes, see CvMat#Line description. + * @option font_option [Number] :italic If value is not nil or false that means italic or oblique font. * - * font_option should be Hash include these keys. - * :hscale - * Horizontal scale. If equal to 1.0, the characters have the original width depending on the font type. - * If equal to 0.5, the characters are of half the original width. - * :vscale - * Vertical scale. If equal to 1.0, the characters have the original height depending on the font type. - * If equal to 0.5, the characters are of half the original height. - * :shear - * Approximate tangent of the character slope relative to the vertical line. - * Zero value means a non-italic font, 1.0f means ~45degree slope, etc. - * :thickness - * Thickness of the text strokes. - * :line_type - * Type of the strokes, see CvMat#Line description. - * :italic - * If value is not nil or false that means italic or oblique font. - * - * note: font_option's default value is CvFont::FONT_OPTION. - * - * e.g. Create Font + * @example Create Font * OpenCV::CvFont.new(:simplex, :hscale => 2, :vslace => 2, :italic => true) * # create 2x bigger than normal, italic type font. + * + * @opencv_func cvInitFont */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) @@ -161,48 +105,124 @@ rb_initialize(int argc, VALUE *argv, VALUE self) return self; } - +/* + * Returns font face + * @overload face + * @return [Fixnum] Font face + */ VALUE rb_face(VALUE self) { return INT2FIX(CVFONT(self)->font_face); } +/* + * Returns hscale + * @overload hscale + * @return [Number] hscale + */ VALUE rb_hscale(VALUE self) { return rb_float_new(CVFONT(self)->hscale); } +/* + * Returns vscale + * @overload vscale + * @return [Number] vscale + */ VALUE rb_vscale(VALUE self) { return rb_float_new(CVFONT(self)->vscale); } +/* + * Returns shear + * @overload shear + * @return [Number] shear + */ VALUE rb_shear(VALUE self) { return rb_float_new(CVFONT(self)->shear); } +/* + * Returns thickness + * @overload thickness + * @return [Fixnum] thickness + */ VALUE rb_thickness(VALUE self) { return INT2FIX(CVFONT(self)->thickness); } +/* + * Returns line type + * @overload line_type + * @return [Fixnum] line_type + */ VALUE rb_line_type(VALUE self) { return INT2FIX(CVFONT(self)->line_type); } +/* + * Returns italic or not + * @overload italic + * @return [Boolean] self is italic or not + */ VALUE rb_italic(VALUE self) { return ((CVFONT(self)->font_face & CV_FONT_ITALIC) > 0) ? Qtrue : Qfalse; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvFont", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + VALUE face = rb_hash_new(); + rb_define_const(rb_klass, "FACE", face); + rb_hash_aset(face, ID2SYM(rb_intern("simplex")), INT2FIX(CV_FONT_HERSHEY_SIMPLEX)); + rb_hash_aset(face, ID2SYM(rb_intern("plain")), INT2FIX(CV_FONT_HERSHEY_PLAIN)); + rb_hash_aset(face, ID2SYM(rb_intern("duplex")), INT2FIX(CV_FONT_HERSHEY_DUPLEX)); + rb_hash_aset(face, ID2SYM(rb_intern("triplex")), INT2FIX(CV_FONT_HERSHEY_TRIPLEX)); + rb_hash_aset(face, ID2SYM(rb_intern("complex_small")), INT2FIX(CV_FONT_HERSHEY_COMPLEX_SMALL)); + rb_hash_aset(face, ID2SYM(rb_intern("script_simplex")), INT2FIX(CV_FONT_HERSHEY_SCRIPT_SIMPLEX)); + rb_hash_aset(face, ID2SYM(rb_intern("script_complex")), INT2FIX(CV_FONT_HERSHEY_SCRIPT_COMPLEX)); + + VALUE default_option = rb_hash_new(); + rb_define_const(rb_klass, "FONT_OPTION", default_option); + rb_hash_aset(default_option, ID2SYM(rb_intern("hscale")), rb_float_new(1.0)); + rb_hash_aset(default_option, ID2SYM(rb_intern("vscale")), rb_float_new(1.0)); + rb_hash_aset(default_option, ID2SYM(rb_intern("shear")), INT2FIX(0)); + rb_hash_aset(default_option, ID2SYM(rb_intern("thickness")), INT2FIX(1)); + rb_hash_aset(default_option, ID2SYM(rb_intern("line_type")), INT2FIX(8)); + + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "face", RUBY_METHOD_FUNC(rb_face), 0); + rb_define_method(rb_klass, "hscale", RUBY_METHOD_FUNC(rb_hscale), 0); + rb_define_method(rb_klass, "vscale", RUBY_METHOD_FUNC(rb_vscale), 0); + rb_define_method(rb_klass, "shear", RUBY_METHOD_FUNC(rb_shear), 0); + rb_define_method(rb_klass, "thickness", RUBY_METHOD_FUNC(rb_thickness), 0); + rb_define_method(rb_klass, "line_type", RUBY_METHOD_FUNC(rb_line_type), 0); + rb_define_method(rb_klass, "italic", RUBY_METHOD_FUNC(rb_italic), 0); +} + __NAMESPACE_END_CVFONT __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvfont.h b/ext/opencv/cvfont.h index 31e34cb..f208303 100644 --- a/ext/opencv/cvfont.h +++ b/ext/opencv/cvfont.h @@ -28,7 +28,7 @@ __NAMESPACE_BEGIN_CVFONT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvhaarclassifiercascade.cpp b/ext/opencv/cvhaarclassifiercascade.cpp index fc2fda0..4a007b6 100644 --- a/ext/opencv/cvhaarclassifiercascade.cpp +++ b/ext/opencv/cvhaarclassifiercascade.cpp @@ -11,11 +11,7 @@ /* * Document-class: OpenCV::CvHaarClassifierCascade * - * CvHaarClassifierCascade object is "fast-object-detector". - * This detector can discover object (e.g. human's face) from image. - * - * Find face-area from picture "lena"... - * link:../images/face_detect_from_lena.jpg + * Haar Feature-based Cascade Classifier for Object Detection */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVHAARCLASSIFERCASCADE @@ -28,23 +24,6 @@ rb_class() return rb_klass; } -void define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvHaarClassifierCascade", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load), 1); - rb_define_method(rb_klass, "detect_objects", RUBY_METHOD_FUNC(rb_detect_objects), -1); -} - VALUE rb_allocate(VALUE klass) { @@ -61,18 +40,13 @@ cvhaarclassifiercascade_free(void* ptr) } /* - * call-seq: - * CvHaarClassiferCascade.load(path) -> object-detector - * * Load trained cascade of haar classifers from file. - * Object detection classifiers are stored in XML or YAML files. - * sample of object detection classifier files is included by OpenCV. * - * You can found these at - * C:\Program Files\OpenCV\data\haarcascades\*.xml (Windows, default install path) - * - * e.g. you want to try to detect human's face. - * detector = CvHaarClassiferCascade.load("haarcascade_frontalface_alt.xml") + * @overload load(filename) + * @param filename [String] Haar classifer file name + * @return [CvHaarClassifierCascade] Object detector + * @scope class + * @opencv_func cvLoad */ VALUE rb_load(VALUE klass, VALUE path) @@ -90,35 +64,23 @@ rb_load(VALUE klass, VALUE path) } /* - * call-seq: - * detect_objects(image[, options]) -> cvseq(include CvAvgComp object) - * detect_objects(image[, options]){|cmp| ... } -> cvseq(include CvAvgComp object) + * Detects objects of different sizes in the input image. * - * Detects objects in the image. This method finds rectangular regions in the - * given image that are likely to contain objects the cascade has been trained - * for and return those regions as a sequence of rectangles. - * - * * option should be Hash include these keys. - * :scale_factor (should be > 1.0) - * The factor by which the search window is scaled between the subsequent scans, - * 1.1 mean increasing window by 10%. - * :storage + * @overload detect_objects(image, options = nil) + * @param image [CvMat,IplImage] Matrix of the type CV_8U containing an image where objects are detected. + * @param options [Hash] Options + * @option options [Number] :scale_factor + * Parameter specifying how much the image size is reduced at each image scale. + * @option options [Number] :storage * Memory storage to store the resultant sequence of the object candidate rectangles - * :flags - * Mode of operation. Currently the only flag that may be specified is CV_HAAR_DO_CANNY_PRUNING . - * If it is set, the function uses Canny edge detector to reject some image regions that contain - * too few or too much edges and thus can not contain the searched object. The particular threshold - * values are tuned for face detection and in this case the pruning speeds up the processing - * :min_neighbors - * Minimum number (minus 1) of neighbor rectangles that makes up an object. - * All the groups of a smaller number of rectangles than min_neighbors - 1 are rejected. - * If min_neighbors is 0, the function does not any grouping at all and returns all the detected - * candidate rectangles, whitch many be useful if the user wants to apply a customized grouping procedure. - * :min_size - * Minimum window size. By default, it is set to size of samples the classifier has been - * trained on (~20x20 for face detection). - * :max_size - * aximum window size to use. By default, it is set to the size of the image. + * @option options [Number] :min_neighbors + * Parameter specifying how many neighbors each candidate rectangle should have to retain it. + * @option options [CvSize] :min_size + * Minimum possible object size. Objects smaller than that are ignored. + * @option options [CvSize] :max_size + * Maximum possible object size. Objects larger than that are ignored. + * @return [CvSeq] Detected objects as a list of rectangles + * @opencv_func cvHaarDetectObjects */ VALUE rb_detect_objects(int argc, VALUE *argv, VALUE self) @@ -164,5 +126,23 @@ rb_detect_objects(int argc, VALUE *argv, VALUE self) return result; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvHaarClassifierCascade", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load), 1); + rb_define_method(rb_klass, "detect_objects", RUBY_METHOD_FUNC(rb_detect_objects), -1); +} + __NAMESPACE_END_CVHAARCLASSIFERCASCADE __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvhaarclassifiercascade.h b/ext/opencv/cvhaarclassifiercascade.h index a167556..17e504c 100644 --- a/ext/opencv/cvhaarclassifiercascade.h +++ b/ext/opencv/cvhaarclassifiercascade.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVHAARCLASSIFERCASCADE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvhistogram.cpp b/ext/opencv/cvhistogram.cpp index e88eb8b..6e3ca33 100644 --- a/ext/opencv/cvhistogram.cpp +++ b/ext/opencv/cvhistogram.cpp @@ -11,7 +11,7 @@ /* * Document-class: OpenCV::CvHistogram * - * Muti-dimensional histogram. + * Multi-dimensional histogram. */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVHISTOGRAM @@ -24,57 +24,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvHistogram", rb_cObject); - - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "is_uniform?", RUBY_METHOD_FUNC(rb_is_uniform), 0); - rb_define_method(rb_klass, "is_sparse?", RUBY_METHOD_FUNC(rb_is_sparse), 0); - rb_define_method(rb_klass, "has_range?", RUBY_METHOD_FUNC(rb_has_range), 0); - rb_define_method(rb_klass, "dims", RUBY_METHOD_FUNC(rb_dims), 0); - rb_define_method(rb_klass, "calc_hist", RUBY_METHOD_FUNC(rb_calc_hist), -1); - rb_define_method(rb_klass, "calc_hist!", RUBY_METHOD_FUNC(rb_calc_hist_bang), -1); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), -2); - rb_define_alias(rb_klass, "query_hist_value", "[]"); - rb_define_method(rb_klass, "min_max_value", RUBY_METHOD_FUNC(rb_min_max_value), 0); - rb_define_method(rb_klass, "copy_hist", RUBY_METHOD_FUNC(rb_copy_hist), 0); - - rb_define_method(rb_klass, "clear_hist", RUBY_METHOD_FUNC(rb_clear_hist), 0); - rb_define_alias(rb_klass, "clear", "clear_hist"); - rb_define_method(rb_klass, "clear_hist!", RUBY_METHOD_FUNC(rb_clear_hist_bang), 0); - rb_define_alias(rb_klass, "clear!", "clear_hist!"); - - rb_define_method(rb_klass, "normalize_hist", RUBY_METHOD_FUNC(rb_normalize_hist), 1); - rb_define_alias(rb_klass, "normalize", "normalize_hist"); - rb_define_method(rb_klass, "normalize_hist!", RUBY_METHOD_FUNC(rb_normalize_hist_bang), 1); - rb_define_alias(rb_klass, "normalize!", "normalize_hist!"); - - rb_define_method(rb_klass, "thresh_hist", RUBY_METHOD_FUNC(rb_thresh_hist), 1); - rb_define_alias(rb_klass, "thresh", "thresh_hist"); - rb_define_method(rb_klass, "thresh_hist!", RUBY_METHOD_FUNC(rb_thresh_hist_bang), 1); - rb_define_alias(rb_klass, "thresh!", "thresh_hist!"); - - rb_define_method(rb_klass, "set_hist_bin_ranges", RUBY_METHOD_FUNC(rb_set_hist_bin_ranges), -1); - rb_define_method(rb_klass, "set_hist_bin_ranges!", RUBY_METHOD_FUNC(rb_set_hist_bin_ranges_bang), -1); - - rb_define_method(rb_klass, "calc_back_project", RUBY_METHOD_FUNC(rb_calc_back_project), 1); - rb_define_method(rb_klass, "calc_back_project_patch", RUBY_METHOD_FUNC(rb_calc_back_project_patch), 4); - - rb_define_singleton_method(rb_klass, "calc_prob_density", RUBY_METHOD_FUNC(rb_calc_prob_density), -1); - rb_define_singleton_method(rb_klass, "compare_hist", RUBY_METHOD_FUNC(rb_compare_hist), 3); -} - void release_hist(void* ptr) { @@ -119,6 +68,23 @@ ary2intptr(VALUE ary, int* buff) return buff; } +/* + * Creates a histogram + * @overload new(dims, sizes, type, ranges=nil, uniform=true) + * @param dims [Integer] Number of histogram dimensions + * @param sizes [Array] Array of the histogram dimension sizes + * @param type [Integer] + * Histogram representation format. CV_HIST_ARRAY means that the histogram data is represented + * as a multi-dimensional dense array CvMatND. CV_HIST_SPARSE means that histogram data is + * represented as a multi-dimensional sparse array CvSparseMat. + * @param ranges [Array] + * Array of ranges for the histogram bins. Its meaning depends on the uniform parameter value. + * The ranges are used when the histogram is calculated or backprojected to determine which + * histogram bin corresponds to which value/tuple of values from the input image(s). + * @param uniform [Boolean] Uniformity flag. + * @return [CvHistogram] Histogram + * @opencv_func cvCreateHist + */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { @@ -157,9 +123,10 @@ rb_initialize(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * is_uniform? -> true or false - * + * Returns self is uniform histogram or not + * @overload is_uniform? + * @return [Boolean] Uniform or not + * @opencv_func CV_IS_UNIFORM_HIST */ VALUE rb_is_uniform(VALUE self) @@ -168,9 +135,10 @@ rb_is_uniform(VALUE self) } /* - * call-seq: - * is_sparse? -> true or false - * + * Returns self is sparse histogram or not + * @overload is_sparse? + * @return [Boolean] Sparse or not + * @opencv_func CV_IS_SPARSE_HIST */ VALUE rb_is_sparse(VALUE self) @@ -179,21 +147,45 @@ rb_is_sparse(VALUE self) } /* - * call-seq: - * has_range? -> true or false - */ + * Returns self has range or not + * @overload has_range? + * @return [Boolean] Has range or not + * @opencv_func CV_HIST_HAS_RANGES +*/ VALUE rb_has_range(VALUE self) { return CV_HIST_HAS_RANGES(CVHISTOGRAM(self)) ? Qtrue : Qfalse; } +/* + * Calculates a histogram of a set of arrays. + * @overload calc_hist(images, accumulate=nil, mask=nil) + * @param images [Array] + * Source arrays. They all should have the same depth, CV_8U or CV_32F, and the same size. + * Each of them can have an arbitrary number of channels. + * @param accumulate [Boolean] + * Accumulation flag. If it is set, the histogram is not cleared in the beginning when it is allocated. + * This feature enables you to compute a single histogram from several sets of arrays, + * or to update the histogram in time. + * @param mask [CvMat] + * Optional mask. If the matrix is not empty, it must be an 8-bit array of the same size as images[i]. + * The non-zero mask elements mark the array elements counted in the histogram. + * @return [CvHistogram] Histogram of a set of arrays + * @opencv_func cvCalcHist + */ VALUE rb_calc_hist(int argc, VALUE* argv, VALUE self) { return rb_calc_hist_bang(argc, argv, rb_copy_hist(self)); } +/* + * Calculates a histogram of a set of arrays. + * @overload calc_hist!(images, accumulate=nil, mask=nil) + * @see #calc_hist + * @opencv_func cvCalcHist + */ VALUE rb_calc_hist_bang(int argc, VALUE* argv, VALUE self) { @@ -218,8 +210,17 @@ rb_calc_hist_bang(int argc, VALUE* argv, VALUE self) } /* - * call-seq: - * [idx1[,idx2]...] + * Queries the value of the histogram bin. + * @overload [](idx0) + * @overload [](idx0, idx1) + * @overload [](idx0, idx1, idx2) + * @overload [](idx0, idx1, idx2, idx3, ...) + * @param idx* [Integer] *-th index + * @return [Number] The value of the specified bin of the 1D, 2D, 3D, or N-D histogram. + * @opencv_func cvQueryHistValue_1D + * @opencv_func cvQueryHistValue_2D + * @opencv_func cvQueryHistValue_3D + * @opencv_func cvQueryHistValue_nD */ VALUE rb_aref(VALUE self, VALUE args) @@ -256,6 +257,18 @@ rb_aref(VALUE self, VALUE args) return rb_float_new((double)value); } +/* + * Finds the minimum and maximum histogram bins. + * @overload min_max_value + * @return [Array] + * [min_value, max_value, min_idx, max_idx]: Array of the minimum / maximum value of the histogram + * and their coordinates. + * - min_value: The minimum value of the histogram. + * - max_value: The maximum value of the histogram. + * - min_idx: The array of coordinates for the minimum. + * - max_idx: The array of coordinates for the maximum. + * @opencv_func cvGetMinMaxHistValue + */ VALUE rb_min_max_value(VALUE self) { @@ -286,8 +299,16 @@ rb_min_max_value(VALUE self) } /* - * call-seq: - * dims -> [int[,int...]] + * Returns number of array dimensions + * @overload [](idx0, idx1, ...) + * @param idx* [Integer] *-th index + * @return [Array>] + * [dims, sizes]: Number of array dimensions and its sizes. + * - dims (Integer): Number of array dimensions + * - sizes (Array): Vector of the array dimension sizes. + * For 2D arrays the number of rows (height) goes first, + * number of columns (width) next. + * @opencv_func cvGetDims */ VALUE rb_dims(VALUE self) @@ -309,10 +330,10 @@ rb_dims(VALUE self) } /* - * call-seq: - * copy_hist -> cvhist - * - * Clone histogram. + * Clones histogram + * @overload copy_hist + * @return [CvHistogram] Copy of the histogram + * @opencv_func cvCopyHist */ VALUE rb_copy_hist(VALUE self) @@ -328,8 +349,11 @@ rb_copy_hist(VALUE self) } /* - * call-seq: - * clear_hist + * Sets all histogram bins to 0 in case of dense histogram + * and removes all histogram bins in case of sparse array. + * @overload clear_hist + * @return [CvHistogram] Cleared histogram + * @opencv_func cvClearHist */ VALUE rb_clear_hist(VALUE self) @@ -338,10 +362,13 @@ rb_clear_hist(VALUE self) } /* - * call-seq: - * clear_hist! - * - * Sets all histogram bins to 0 in case of dense histogram and removes all histogram bins in case of sparse array. + * Sets all histogram bins to 0 in case of dense histogram + * and removes all histogram bins in case of sparse array. + * This method changes self. + * @overload clear_hist! + * @see #clear_hist + * @return [CvHistogram] Cleared histogram + * @opencv_func cvClearHist */ VALUE rb_clear_hist_bang(VALUE self) @@ -356,10 +383,12 @@ rb_clear_hist_bang(VALUE self) } /* - * call-seq: - * normalize(factor) -> cvhist - * - * Return normalized the histogram bins by scaling them, such that the sum of the bins becomes equal to factor. + * Returns normalized the histogram bins by scaling them, + * such that the sum of the bins becomes equal to factor. + * @overload normalize(factor) + * @param factor [Number] Normalization factor. The sum of the bins becomes equal to this value. + * @return [CvHistogram] Normalized histogram + * @opencv_func cvNormalizeHist */ VALUE rb_normalize_hist(VALUE self, VALUE factor) @@ -368,10 +397,14 @@ rb_normalize_hist(VALUE self, VALUE factor) } /* - * call-seq: - * normalize!(factor) -> self - * - * normalizes the histogram bins by scaling them, such that the sum of the bins becomes equal to factor. + * Returns normalized the histogram bins by scaling them, + * such that the sum of the bins becomes equal to factor. + * This method changes self. + * @overload normalize!(factor) + * @param factor [Number] Normalization factor. The sum of the bins becomes equal to this value. + * @return [CvHistogram] Normalized histogram + * @see #normalize + * @opencv_func cvNormalizeHist */ VALUE rb_normalize_hist_bang(VALUE self, VALUE factor) @@ -386,10 +419,11 @@ rb_normalize_hist_bang(VALUE self, VALUE factor) } /* - * call-seq: - * thresh_hist(threshold) -> cvhist - * - * Return cleared histogram bins that are below the specified threshold. + * Returns cleared histogram bins that are below the specified threshold. + * @overload thresh_hist(threshold) + * @param threshold [Number] Threshold value + * @return [CvHistogram] Cleared histogram + * @opencv_func cvThreshHist */ VALUE rb_thresh_hist(VALUE self, VALUE threshold) @@ -398,10 +432,13 @@ rb_thresh_hist(VALUE self, VALUE threshold) } /* - * call-seq: - * thresh_hist!(threshold) -> self - * * Cleares histogram bins that are below the specified threshold. + * This method changes self. + * @overload thresh_hist!(threshold) + * @param threshold [Number] Threshold value + * @return [CvHistogram] Cleared histogram + * @see #thresh_hist + * @opencv_func cvThreshHist */ VALUE rb_thresh_hist_bang(VALUE self, VALUE threshold) @@ -415,12 +452,39 @@ rb_thresh_hist_bang(VALUE self, VALUE threshold) return self; } +/* + * Sets the bounds of the histogram bins. + * @overload set_hist_bin_ranges(ranges, uniform=true) + * @param ranges [Array] + * Array of ranges for the histogram bins. Its meaning depends on the uniform parameter value. + * The ranges are used when the histogram is calculated or backprojected to determine + * which histogram bin corresponds to which value/tuple of values from the input image(s). + * @param uniform [Boolean] + * Uniformity flag. + * @return [CvHistogram] + * Histogram + * @opencv_func cvSetHistBinRanges + */ VALUE rb_set_hist_bin_ranges(int argc, VALUE* argv, VALUE self) { return rb_set_hist_bin_ranges_bang(argc, argv, rb_copy_hist(self)); } +/* + * Sets the bounds of the histogram bins. This method changes self. + * @overload set_hist_bin_ranges!(ranges, uniform=true) + * @param ranges [Array] + * Array of ranges for the histogram bins. Its meaning depends on the uniform parameter value. + * The ranges are used when the histogram is calculated or backprojected to determine + * which histogram bin corresponds to which value/tuple of values from the input image(s). + * @param uniform [Boolean] + * Uniformity flag. + * @return [CvHistogram] + * Histogram + * @see #set_hist_bin_ranges + * @opencv_func cvSetHistBinRanges + */ VALUE rb_set_hist_bin_ranges_bang(int argc, VALUE* argv, VALUE self) { @@ -446,6 +510,17 @@ rb_set_hist_bin_ranges_bang(int argc, VALUE* argv, VALUE self) return self; } +/* + * Calculates the back projection of a histogram. + * @overload calc_back_project(images) + * @param images [Array] + * Source arrays. They all should have the same depth, CV_8U or CV_32F, and the same size. + * Each of them can have an arbitrary number of channels. + * @return [CvMat,IplImage] + * Destination back projection array that is a single-channel array of the same size and depth + * as the first element of images + * @opencv_func cvCalcBackProject + */ VALUE rb_calc_back_project(VALUE self, VALUE image) { @@ -475,6 +550,24 @@ rb_calc_back_project(VALUE self, VALUE image) return back_project; } +/* + * Locates a template within an image by using a histogram comparison. + * @overload calc_back_project_patch(images, patch_size, method, factor) + * @param images [Array] Source arrays. + * @param pach_size [CvSize] Size of the patch slid though the source image. + * @param method [Integer] + * Comparison method that could be one of the following: + * - CV_COMP_CORREL: Correlation + * - CV_COMP_CHISQR: Chi-Square + * - CV_COMP_INTERSECT: Intersection + * - CV_COMP_BHATTACHARYYA: Bhattacharyya distance + * - CV_COMP_HELLINGER: Synonym for CV_COMP_BHATTACHARYYA + * @param factor [Number] + * Normalization factor for histograms that affects the normalization scale + * of the destination image. Pass 1 if not sure. + * @return [CvMat,IplImage] Destination image. + * @opencv_func cvCalcBackProject + */ VALUE rb_calc_back_project_patch(VALUE self, VALUE image, VALUE patch_size, VALUE method, VALUE factor) { @@ -507,6 +600,22 @@ rb_calc_back_project_patch(VALUE self, VALUE image, VALUE patch_size, VALUE meth return dst; } +/* + * Compares two histograms. + * @overload compare_hist(hist1, hist2, method) + * @param hist1 [CvHistogram] First compared histogram. + * @param hist2 [CvHistogram] Second compared histogram of the same size as hist1. + * @param method [Integer] + * Comparison method that could be one of the following: + * - CV_COMP_CORREL: Correlation + * - CV_COMP_CHISQR: Chi-Square + * - CV_COMP_INTERSECT: Intersection + * - CV_COMP_BHATTACHARYYA: Bhattacharyya distance + * - CV_COMP_HELLINGER: Synonym for CV_COMP_BHATTACHARYYA + * @return [Number] Distance of the two histograms. + * @scope class + * @opencv_func cvCompareHist + */ VALUE rb_compare_hist(VALUE self, VALUE hist1, VALUE hist2, VALUE method) { @@ -522,6 +631,15 @@ rb_compare_hist(VALUE self, VALUE hist1, VALUE hist2, VALUE method) return rb_float_new(result); } +/* + * Divides one histogram by another. + * @overload calc_prob_density(hist1, hist2, scale=255) + * @param hist1 [CvHistogram] First histogram (the divisor). + * @param hist2 [CvHistogram] Second histogram. + * @param scale [Number] Scale factor for the destination histogram. + * @return [CvHistogram] Destination histogram. + * @opencv_func cvCalcProbDensity + */ VALUE rb_calc_prob_density(int argc, VALUE* argv, VALUE self) { @@ -542,5 +660,56 @@ rb_calc_prob_density(int argc, VALUE* argv, VALUE self) return dst_hist; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvHistogram", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "is_uniform?", RUBY_METHOD_FUNC(rb_is_uniform), 0); + rb_define_method(rb_klass, "is_sparse?", RUBY_METHOD_FUNC(rb_is_sparse), 0); + rb_define_method(rb_klass, "has_range?", RUBY_METHOD_FUNC(rb_has_range), 0); + rb_define_method(rb_klass, "dims", RUBY_METHOD_FUNC(rb_dims), 0); + rb_define_method(rb_klass, "calc_hist", RUBY_METHOD_FUNC(rb_calc_hist), -1); + rb_define_method(rb_klass, "calc_hist!", RUBY_METHOD_FUNC(rb_calc_hist_bang), -1); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), -2); + rb_define_alias(rb_klass, "query_hist_value", "[]"); + rb_define_method(rb_klass, "min_max_value", RUBY_METHOD_FUNC(rb_min_max_value), 0); + rb_define_method(rb_klass, "copy_hist", RUBY_METHOD_FUNC(rb_copy_hist), 0); + + rb_define_method(rb_klass, "clear_hist", RUBY_METHOD_FUNC(rb_clear_hist), 0); + rb_define_alias(rb_klass, "clear", "clear_hist"); + rb_define_method(rb_klass, "clear_hist!", RUBY_METHOD_FUNC(rb_clear_hist_bang), 0); + rb_define_alias(rb_klass, "clear!", "clear_hist!"); + + rb_define_method(rb_klass, "normalize_hist", RUBY_METHOD_FUNC(rb_normalize_hist), 1); + rb_define_alias(rb_klass, "normalize", "normalize_hist"); + rb_define_method(rb_klass, "normalize_hist!", RUBY_METHOD_FUNC(rb_normalize_hist_bang), 1); + rb_define_alias(rb_klass, "normalize!", "normalize_hist!"); + + rb_define_method(rb_klass, "thresh_hist", RUBY_METHOD_FUNC(rb_thresh_hist), 1); + rb_define_alias(rb_klass, "thresh", "thresh_hist"); + rb_define_method(rb_klass, "thresh_hist!", RUBY_METHOD_FUNC(rb_thresh_hist_bang), 1); + rb_define_alias(rb_klass, "thresh!", "thresh_hist!"); + + rb_define_method(rb_klass, "set_hist_bin_ranges", RUBY_METHOD_FUNC(rb_set_hist_bin_ranges), -1); + rb_define_method(rb_klass, "set_hist_bin_ranges!", RUBY_METHOD_FUNC(rb_set_hist_bin_ranges_bang), -1); + + rb_define_method(rb_klass, "calc_back_project", RUBY_METHOD_FUNC(rb_calc_back_project), 1); + rb_define_method(rb_klass, "calc_back_project_patch", RUBY_METHOD_FUNC(rb_calc_back_project_patch), 4); + + rb_define_singleton_method(rb_klass, "calc_prob_density", RUBY_METHOD_FUNC(rb_calc_prob_density), -1); + rb_define_singleton_method(rb_klass, "compare_hist", RUBY_METHOD_FUNC(rb_compare_hist), 3); +} + __NAMESPACE_END_CVHISTOGRAM __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvhistogram.h b/ext/opencv/cvhistogram.h index 8c8418d..2ef3ad5 100644 --- a/ext/opencv/cvhistogram.h +++ b/ext/opencv/cvhistogram.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVHISTOGRAM VALUE rb_class(); VALUE rb_allocate(VALUE klass); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); VALUE rb_is_uniform(VALUE self); diff --git a/ext/opencv/cvhumoments.cpp b/ext/opencv/cvhumoments.cpp index 219037e..1930c8b 100644 --- a/ext/opencv/cvhumoments.cpp +++ b/ext/opencv/cvhumoments.cpp @@ -12,17 +12,11 @@ /* * Document-class: OpenCV::CvHuMoments * - * moments + * Hu invariants */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVHUMOMENTS -#define DEFINE_CVHUMOMENTS_GETTER(elem) \ - rb_define_method(rb_klass, #elem, RUBY_METHOD_FUNC(rb_##elem), 0) - -#define CVHUMOMENTS_GETTER(elem) \ - VALUE rb_##elem(VALUE self) { return DBL2NUM(CVHUMOMENTS(self)->elem); } - VALUE rb_klass; VALUE @@ -31,33 +25,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvHuMoments", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 1); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); - - DEFINE_CVHUMOMENTS_GETTER(hu1); - DEFINE_CVHUMOMENTS_GETTER(hu2); - DEFINE_CVHUMOMENTS_GETTER(hu3); - DEFINE_CVHUMOMENTS_GETTER(hu4); - DEFINE_CVHUMOMENTS_GETTER(hu5); - DEFINE_CVHUMOMENTS_GETTER(hu6); - DEFINE_CVHUMOMENTS_GETTER(hu7); -} - VALUE rb_allocate(VALUE klass) { @@ -66,21 +33,12 @@ rb_allocate(VALUE klass) } /* - * call-seq: - * CvHuMoments.new(src_moments) - * - * Calculates the seven Hu invariants. - * src_moments The input moments - * - * seven Hu invariants that are defined as: - * h1=η20+η02 - * h2=(η20-η02)²+4η11² - * h3=(η30-3η12)²+ (3η21-η03)² - * h4=(η30+η12)²+ (η21+η03)² - * h5=(η30-3η12)(η30+η12)[(η30+η12)²-3(η21+η03)²]+(3η21-η03)(η21+η03)[3(η30+η12)²-(η21+η03)²] - * h6=(η20-η02)[(η30+η12)²- (η21+η03)²]+4η11(η30+η12)(η21+η03) - * h7=(3η21-η03)(η21+η03)[3(η30+η12)²-(η21+η03)²]-(η30-3η12)(η21+η03)[3(η30+η12)²-(η21+η03)²] - * where ηi,j are normalized central moments of 2-nd and 3-rd orders. The computed values are proved to be invariant to the image scaling, rotation, and reflection except the seventh one, whose sign is changed by reflection. + * Calculates the seven Hu invariants + * @overload new(src_moments) + * @param src_moments [CvMoment] Input moments + * @return [CvHuMoments] Output Hu invariants + * @opencv_func cvGetHuMoments + * @see http://en.wikipedia.org/wiki/Image_moment#Rotation_invariant_moments */ VALUE rb_initialize(VALUE self, VALUE src_moments) @@ -94,19 +52,73 @@ rb_initialize(VALUE self, VALUE src_moments) return self; } -CVHUMOMENTS_GETTER(hu1); -CVHUMOMENTS_GETTER(hu2); -CVHUMOMENTS_GETTER(hu3); -CVHUMOMENTS_GETTER(hu4); -CVHUMOMENTS_GETTER(hu5); -CVHUMOMENTS_GETTER(hu6); -CVHUMOMENTS_GETTER(hu7); +/* + * Returns hu1 invariant + * @overload hu1 + * @return [Number] hu1 invariant + */ +VALUE rb_hu1(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu1); +} /* - * call-seq: - * to_ary -> [hu1, hu2, ... ,hu7] - * - * Return values by Array. + * Returns hu2 invariant + * @overload hu2 + * @return [Number] hu2 invariant + */ +VALUE rb_hu2(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu2); +} + +/* + * Returns hu3 invariant + * @overload hu3 + * @return [Number] hu3 invariant + */ +VALUE rb_hu3(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu3); +} + +/* + * Returns hu4 invariant + * @overload hu4 + * @return [Number] hu4 invariant + */ +VALUE rb_hu4(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu4); +} + +/* + * Returns hu5 invariant + * @overload hu5 + * @return [Number] hu5 invariant + */ +VALUE rb_hu5(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu5); +} + +/* + * Returns hu6 invariant + * @overload hu6 + * @return [Number] hu6 invariant + */ +VALUE rb_hu6(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu6); +} + +/* + * Returns hu7 invariant + * @overload hu7 + * @return [Number] hu7 invariant + */ +VALUE rb_hu7(VALUE self) { + return DBL2NUM(CVHUMOMENTS(self)->hu7); +} + +/* + * Returns hu invaliants as an Array + * @overload to_ary + * @return [Array] Hu invaliants */ VALUE rb_to_ary(VALUE self) @@ -135,5 +147,32 @@ new_object(CvMoments *src_moments) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvHuMoments", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 1); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); + + rb_define_method(rb_klass, "hu1", RUBY_METHOD_FUNC(rb_hu1), 0); + rb_define_method(rb_klass, "hu2", RUBY_METHOD_FUNC(rb_hu2), 0); + rb_define_method(rb_klass, "hu3", RUBY_METHOD_FUNC(rb_hu3), 0); + rb_define_method(rb_klass, "hu4", RUBY_METHOD_FUNC(rb_hu4), 0); + rb_define_method(rb_klass, "hu5", RUBY_METHOD_FUNC(rb_hu5), 0); + rb_define_method(rb_klass, "hu6", RUBY_METHOD_FUNC(rb_hu6), 0); + rb_define_method(rb_klass, "hu7", RUBY_METHOD_FUNC(rb_hu7), 0); +} + __NAMESPACE_END_CVHUMOMENTS __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvhumoments.h b/ext/opencv/cvhumoments.h index 52b0235..580f670 100644 --- a/ext/opencv/cvhumoments.h +++ b/ext/opencv/cvhumoments.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVHUMOMENTS VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(VALUE src_moments, VALUE self); diff --git a/ext/opencv/cvline.cpp b/ext/opencv/cvline.cpp index 792209d..20e3398 100644 --- a/ext/opencv/cvline.cpp +++ b/ext/opencv/cvline.cpp @@ -11,6 +11,8 @@ /* * Document-class: OpenCV::CvLine * + * Line parameters represented by a two-element (rho, theta) + * for CvMat#hough_lines */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVLINE @@ -23,28 +25,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvLine", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_method(rb_klass, "rho", RUBY_METHOD_FUNC(rb_rho), 0); - rb_define_method(rb_klass, "rho=", RUBY_METHOD_FUNC(rb_set_rho), 1); - rb_define_method(rb_klass, "theta", RUBY_METHOD_FUNC(rb_theta), 0); - rb_define_method(rb_klass, "theta=", RUBY_METHOD_FUNC(rb_set_theta), 1); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); - rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); -} - VALUE rb_allocate(VALUE klass) { @@ -53,7 +33,9 @@ rb_allocate(VALUE klass) } /* - * Return parameter on rho. + * Returns distance from the coordinate origin (0, 0) + * @overload rho + * @return [Number] Distance from the coordinate origin */ VALUE rb_rho(VALUE self) @@ -62,10 +44,9 @@ rb_rho(VALUE self) } /* - * call-seq: - * rho = val - * - * Set rho parameter, return self. + * Set distance from the coordinate origin (0, 0) + * @overload rho=(value) + * @param value [Number] Distance from the coordinate origin */ VALUE rb_set_rho(VALUE self, VALUE rho) @@ -75,7 +56,9 @@ rb_set_rho(VALUE self, VALUE rho) } /* - * Return parameter on theta. + * Returns line rotation angle in radians + * @overload theta + * @return [Number] Line rotation angle in radians */ VALUE rb_theta(VALUE self) @@ -84,10 +67,9 @@ rb_theta(VALUE self) } /* - * call-seq: - * y = val - * - * Set theta parameter, return self. + * Set line rotation angle in radians + * @overload theta=(value) + * @param value [Number] Line rotation angle */ VALUE rb_set_theta(VALUE self, VALUE theta) @@ -97,10 +79,10 @@ rb_set_theta(VALUE self, VALUE theta) } /* - * call-seq: - * [index] - * - * Return value of index dimension. + * Returns value of rho, theta + * @overload [](index) + * @param index [Integer] Index + * @return [Number] If index = 0, returns rho, else if index = 1, returns theta. */ VALUE rb_aref(VALUE self, VALUE index) @@ -120,10 +102,11 @@ rb_aref(VALUE self, VALUE index) } /* - * call-seq: - * [index] = value - * - * Set value of index dimension to value + * Set value of rho, theta + * @overload []=(index, value) + * @param index [Integer] Index + * @param value [Number] Value + * @return [Number] If index = 0, set rho, else if index = 1, set theta. */ VALUE rb_aset(VALUE self, VALUE index, VALUE value) @@ -150,5 +133,27 @@ new_object(CvLine line) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvLine", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "rho", RUBY_METHOD_FUNC(rb_rho), 0); + rb_define_method(rb_klass, "rho=", RUBY_METHOD_FUNC(rb_set_rho), 1); + rb_define_method(rb_klass, "theta", RUBY_METHOD_FUNC(rb_theta), 0); + rb_define_method(rb_klass, "theta=", RUBY_METHOD_FUNC(rb_set_theta), 1); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); +} + __NAMESPACE_END_CVLINE __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvline.h b/ext/opencv/cvline.h index b62e1c0..a5618a9 100644 --- a/ext/opencv/cvline.h +++ b/ext/opencv/cvline.h @@ -26,7 +26,7 @@ __NAMESPACE_BEGIN_CVLINE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvmat.cpp b/ext/opencv/cvmat.cpp index 6ac93da..b8c7e40 100644 --- a/ext/opencv/cvmat.cpp +++ b/ext/opencv/cvmat.cpp @@ -11,36 +11,6 @@ /* * Document-class: OpenCV::CvMat * - * CvMat is basic 2D matrix class in OpenCV. - * - * C structure is here. - * typedef struct CvMat { - * int type; - * int step; - * int *refcount; - * union - * { - * uchar *ptr; - * short *s; - * int *i; - * float *fl; - * double *db; - * } data; - * #ifdef __cplusplus - * union - * { - * int rows; - * int height; - * }; - * union - * { - * int cols; - * int width; - * }; - * #else - * int rows; // number of row - * int cols; // number of columns - * } CvMat; */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVMAT @@ -134,15 +104,5658 @@ rb_class() return rb_klass; } -void define_ruby_class() +VALUE +rb_allocate(VALUE klass) { + return OPENCV_OBJECT(klass, 0); +} + +/* + * Creates a matrix + * @overload new(rows, cols, depth = CV_8U, channels = 3) + * @param row [Integer] Number of rows in the matrix + * @param col [Integer] Number of columns in the matrix + * @param depth [Integer, Symbol] Depth type in the matrix. + * The type of the matrix elements in the form of constant CV_ + * or symbol :cv, where S=signed, U=unsigned, F=float. + * @param channels [Integer] Number of channels in the matrix + * @return [CvMat] Created matrix + * @opencv_func cvCreateMat + * @example + * mat1 = CvMat.new(3, 4) # Creates a 3-channels 3x4 matrix whose elements are 8bit unsigned. + * mat2 = CvMat.new(5, 6, CV_32F, 1) # Creates a 1-channel 5x6 matrix whose elements are 32bit float. + * mat3 = CvMat.new(5, 6, :cv32f, 1) # Same as CvMat.new(5, 6, CV_32F, 1) + */ +VALUE +rb_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE row, column, depth, channel; + rb_scan_args(argc, argv, "22", &row, &column, &depth, &channel); + + int ch = (argc < 4) ? 3 : NUM2INT(channel); + CvMat *ptr = rb_cvCreateMat(NUM2INT(row), NUM2INT(column), + CV_MAKETYPE(CVMETHOD("DEPTH", depth, CV_8U), ch)); + free(DATA_PTR(self)); + DATA_PTR(self) = ptr; + + return self; +} + +/* + * Load an image from the specified file + * @overload load(filename, iscolor = 1) + * @param filename [String] Name of file to be loaded + * @param iscolor [Integer] Flags specifying the color type of a loaded image: + * - > 0 Return a 3-channel color image. + * - = 0 Return a grayscale image. + * - < 0 Return the loaded image as is. + * @return [CvMat] Loaded image + * @opencv_func cvLoadImageM + * @scope class + */ +VALUE +rb_load_imageM(int argc, VALUE *argv, VALUE self) +{ + VALUE filename, iscolor; + rb_scan_args(argc, argv, "11", &filename, &iscolor); + Check_Type(filename, T_STRING); + + int _iscolor; + if (NIL_P(iscolor)) { + _iscolor = CV_LOAD_IMAGE_COLOR; + } + else { + Check_Type(iscolor, T_FIXNUM); + _iscolor = FIX2INT(iscolor); + } + + CvMat *mat = NULL; + try { + mat = cvLoadImageM(StringValueCStr(filename), _iscolor); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + if (mat == NULL) { + rb_raise(rb_eStandardError, "file does not exist or invalid format image."); + } + return OPENCV_OBJECT(rb_klass, mat); +} + +/* + * Encodes an image into a memory buffer. + * + * @overload encode_image(ext, params = nil) + * @param ext [String] File extension that defines the output format ('.jpg', '.png', ...) + * @param params [Hash] - Format-specific parameters. + * @option params [Integer] CV_IMWRITE_JPEG_QUALITY (95) For JPEG, it can be a quality + * ( CV_IMWRITE_JPEG_QUALITY ) from 0 to 100 (the higher is the better). + * @option params [Integer] CV_IMWRITE_PNG_COMPRESSION (3) For PNG, it can be the compression + * level ( CV_IMWRITE_PNG_COMPRESSION ) from 0 to 9. A higher value means a smaller size + * and longer compression time. + * @option params [Integer] CV_IMWRITE_PXM_BINARY (1) For PPM, PGM, or PBM, it can be a binary + * format flag ( CV_IMWRITE_PXM_BINARY ), 0 or 1. + * @return [Array] Encoded image as array of bytes. + * @opencv_func cvEncodeImage + * @example + * jpg = CvMat.load('image.jpg') + * bytes1 = jpg.encode_image('.jpg') # Encodes a JPEG image which quality is 95 + * bytes2 = jpg.encode_image('.jpg', CV_IMWRITE_JPEG_QUALITY => 10) # Encodes a JPEG image which quality is 10 + * + * png = CvMat.load('image.png') + * bytes3 = mat.encode_image('.png', CV_IMWRITE_PNG_COMPRESSION => 1) # Encodes a PNG image which compression level is 1 + */ +VALUE +rb_encode_imageM(int argc, VALUE *argv, VALUE self) +{ + VALUE _ext, _params; + rb_scan_args(argc, argv, "11", &_ext, &_params); + Check_Type(_ext, T_STRING); + const char* ext = RSTRING_PTR(_ext); + CvMat* buff = NULL; + int* params = NULL; + + if (!NIL_P(_params)) { + params = hash_to_format_specific_param(_params); + } + + try { + buff = cvEncodeImage(ext, CVARR(self), params); + } + catch (cv::Exception& e) { + if (params != NULL) { + free(params); + params = NULL; + } + raise_cverror(e); + } + if (params != NULL) { + free(params); + params = NULL; + } + + const int size = buff->rows * buff->cols; + VALUE array = rb_ary_new2(size); + for (int i = 0; i < size; i++) { + rb_ary_store(array, i, CHR2FIX(CV_MAT_ELEM(*buff, char, 0, i))); + } + + try { + cvReleaseMat(&buff); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return array; +} + +CvMat* +prepare_decoding(int argc, VALUE *argv, int* iscolor, int* need_release) +{ + VALUE _buff, _iscolor; + rb_scan_args(argc, argv, "11", &_buff, &_iscolor); + *iscolor = NIL_P(_iscolor) ? CV_LOAD_IMAGE_COLOR : NUM2INT(_iscolor); + + CvMat* buff = NULL; + *need_release = 0; + switch (TYPE(_buff)) { + case T_STRING: + _buff = rb_funcall(_buff, rb_intern("unpack"), 1, rb_str_new("c*", 2)); + case T_ARRAY: { + int cols = RARRAY_LEN(_buff); + *need_release = 1; + try { + buff = rb_cvCreateMat(1, cols, CV_8UC1); + VALUE *ary_ptr = RARRAY_PTR(_buff); + for (int i = 0; i < cols; i++) { + CV_MAT_ELEM(*buff, char, 0, i) = NUM2CHR(ary_ptr[i]); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + break; + } + case T_DATA: + if (rb_obj_is_kind_of(_buff, cCvMat::rb_class()) == Qtrue) { + buff = CVMAT(_buff); + break; + } + default: + raise_typeerror(_buff, "CvMat, Array or String"); + } + + return buff; +} + +/* + * Reads an image from a buffer in memory. + * @overload decode_image(buf, iscolor = 1) + * @param buf [CvMat, Array, String] Input array of bytes + * @param iscolor [Integer] Flags specifying the color type of a decoded image (the same flags as CvMat#load) + * @return [CvMat] Loaded matrix + * @opencv_func cvDecodeImageM + */ +VALUE +rb_decode_imageM(int argc, VALUE *argv, VALUE self) +{ + int iscolor, need_release; + CvMat* buff = prepare_decoding(argc, argv, &iscolor, &need_release); + CvMat* mat_ptr = NULL; + try { + mat_ptr = cvDecodeImageM(buff, iscolor); + if (need_release) { + cvReleaseMat(&buff); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return OPENCV_OBJECT(rb_klass, mat_ptr); +} + +/* + * nodoc + */ +VALUE +rb_method_missing(int argc, VALUE *argv, VALUE self) +{ + VALUE name, args, method; + rb_scan_args(argc, argv, "1*", &name, &args); + method = rb_funcall(name, rb_intern("to_s"), 0); + if (RARRAY_LEN(args) != 0 || !rb_respond_to(rb_module_opencv(), rb_intern(StringValuePtr(method)))) + return rb_call_super(argc, argv); + return rb_funcall(rb_module_opencv(), rb_intern(StringValuePtr(method)), 1, self); +} + +/* + * @overload to_s + * @return [String] String representation of the matrix + */ +VALUE +rb_to_s(VALUE self) +{ + const int i = 6; + VALUE str[i]; + str[0] = rb_str_new2("<%s:%dx%d,depth=%s,channel=%d>"); + str[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + str[2] = rb_width(self); + str[3] = rb_height(self); + str[4] = rb_depth(self); + str[5] = rb_channel(self); + return rb_f_sprintf(i, str); +} + +/* + * Tests whether a coordinate or rectangle is inside of the matrix + * @overload inside?(point) + * @param obj [#x, #y] Tested coordinate + * @overload inside?(rect) + * @param obj [#x, #y, #width, #height] Tested rectangle + * @return [Boolean] If the point or rectangle is inside of the matrix, return true. + * If not, return false. + */ +VALUE +rb_inside_q(VALUE self, VALUE object) +{ + if (cCvPoint::rb_compatible_q(cCvPoint::rb_class(), object)) { + CvMat *mat = CVMAT(self); + int x = NUM2INT(rb_funcall(object, rb_intern("x"), 0)); + int y = NUM2INT(rb_funcall(object, rb_intern("y"), 0)); + if (cCvRect::rb_compatible_q(cCvRect::rb_class(), object)) { + int width = NUM2INT(rb_funcall(object, rb_intern("width"), 0)); + int height = NUM2INT(rb_funcall(object, rb_intern("height"), 0)); + return (x >= 0) && (y >= 0) && (x < mat->width) && ((x + width) < mat->width) + && (y < mat->height) && ((y + height) < mat->height) ? Qtrue : Qfalse; + } + else { + return (x >= 0) && (y >= 0) && (x < mat->width) && (y < mat->height) ? Qtrue : Qfalse; + } + } + rb_raise(rb_eArgError, "argument 1 should have method \"x\", \"y\""); + return Qnil; +} + +/* + * Creates a structuring element from the matrix for morphological operations. + * @overload to_IplConvKernel(anchor) + * @param anchor [CvPoint] Anchor position within the element + * @return [IplConvKernel] Created IplConvKernel + * @opencv_func cvCreateStructuringElementEx + */ +VALUE +rb_to_IplConvKernel(VALUE self, VALUE anchor) +{ + CvMat *src = CVMAT(self); + CvPoint p = VALUE_TO_CVPOINT(anchor); + IplConvKernel *kernel = rb_cvCreateStructuringElementEx(src->cols, src->rows, p.x, p.y, + CV_SHAPE_CUSTOM, src->data.i); + return DEPEND_OBJECT(cIplConvKernel::rb_class(), kernel, self); +} + +/* + * Creates a mask (1-channel 8bit unsinged image whose elements are 0) from the matrix. + * The size of the mask is the same as source matrix. + * @overload create_mask + * @return [CvMat] Created mask + */ +VALUE +rb_create_mask(VALUE self) +{ + VALUE mask = cCvMat::new_object(cvGetSize(CVARR(self)), CV_8UC1); + try { + cvZero(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return mask; +} + +/* + * Returns number of columns of the matrix. + * @overload width + * @return [Integer] Number of columns of the matrix + */ +VALUE +rb_width(VALUE self) +{ + return INT2NUM(CVMAT(self)->width); +} + +/* + * Returns number of rows of the matrix. + * @overload rows + * @return [Integer] Number of rows of the matrix + */ +VALUE +rb_height(VALUE self) +{ + return INT2NUM(CVMAT(self)->height); +} + +/* + * Returns depth type of the matrix + * @overload depth + * @return [Symbol] Depth type in the form of symbol :cv, + * where s=signed, u=unsigned, f=float. + */ +VALUE +rb_depth(VALUE self) +{ + return rb_hash_lookup(rb_funcall(rb_const_get(rb_module_opencv(), rb_intern("DEPTH")), rb_intern("invert"), 0), + INT2FIX(CV_MAT_DEPTH(CVMAT(self)->type))); +} + +/* + * Returns number of channels of the matrix + * @overload channel + * @return [Integer] Number of channels of the matrix + */ +VALUE +rb_channel(VALUE self) +{ + return INT2FIX(CV_MAT_CN(CVMAT(self)->type)); +} + +/* + * @overload data + * @deprecated This method will be removed. + */ +VALUE +rb_data(VALUE self) +{ + IplImage *image = IPLIMAGE(self); + return rb_str_new((char *)image->imageData, image->imageSize); +} + +/* + * Makes a clone of an object. + * @overload clone + * @return [CvMat] Clone of the object + * @opencv_func cvClone + */ +VALUE +rb_clone(VALUE self) +{ + VALUE clone = rb_obj_clone(self); + try { + DATA_PTR(clone) = cvClone(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return clone; +} + +/* + * Copies one array to another. + * + * The function copies selected elements from an input array to an output array: + * dst(I) = src(I) if mask(I) != 0 + * + * @overload copy(dst = nil, mask = nil) + * @param dst [CvMat] The destination array. + * @param mask [CvMat] Operation mask, 8-bit single channel array; + * specifies elements of the destination array to be changed. + * @return [CvMat] Copy of the array + * @opencv_func cvCopy + */ +VALUE +rb_copy(int argc, VALUE *argv, VALUE self) +{ + VALUE _dst, _mask; + rb_scan_args(argc, argv, "02", &_dst, &_mask); + + CvMat* mask = MASK(_mask); + CvArr *src = CVARR(self); + if (NIL_P(_dst)) { + CvSize size = cvGetSize(src); + _dst = new_mat_kind_object(size, self); + } + + try { + cvCopy(src, CVARR_WITH_CHECK(_dst), mask); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return _dst; +} + +VALUE +copy(VALUE mat) +{ + return rb_clone(mat); +} + +inline VALUE +rb_to_X_internal(VALUE self, int depth) +{ + CvMat *src = CVMAT(self); + VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(depth, CV_MAT_CN(src->type))); + try { + cvConvert(src, CVMAT(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Converts the matrix to 8bit unsigned. + * @overload to_8u + * @return [CvMat] Converted matrix which depth is 8bit unsigned. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_8u(VALUE self) +{ + return rb_to_X_internal(self, CV_8U); +} + +/* + * Converts the matrix to 8bit signed. + * @overload to_8s + * @return [CvMat] Converted matrix which depth is 8bit signed. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_8s(VALUE self) +{ + return rb_to_X_internal(self, CV_8S); +} + +/* + * Converts the matrix to 16bit unsigned. + * @overload to_16u + * @return [CvMat] Converted matrix which depth is 16bit unsigned. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE rb_to_16u(VALUE self) +{ + return rb_to_X_internal(self, CV_16U); +} + +/* + * Converts the matrix to 16bit signed. + * @overload to_16s + * @return [CvMat] Converted matrix which depth is 16bit signed. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_16s(VALUE self) +{ + return rb_to_X_internal(self, CV_16S); +} + +/* + * Converts the matrix to 32bit signed. + * @overload to_32s + * @return [CvMat] Converted matrix which depth is 32bit signed. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_32s(VALUE self) +{ + return rb_to_X_internal(self, CV_32S); +} + +/* + * Converts the matrix to 32bit float. + * @overload to_32f + * @return [CvMat] Converted matrix which depth is 32bit float. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_32f(VALUE self) +{ + return rb_to_X_internal(self, CV_32F); +} + +/* + * Converts the matrix to 64bit float. + * @overload to_64f + * @return [CvMat] Converted matrix which depth is 64bit float. + * The size and channels of the new matrix are same as the source. + * @opencv_func cvConvert + */ +VALUE +rb_to_64f(VALUE self) +{ + return rb_to_X_internal(self, CV_64F); +} + +/* + * Returns whether the matrix is a vector. + * @overload vector? + * @return [Boolean] If width or height of the matrix is 1, returns true. + * if not, returns false. + */ +VALUE +rb_vector_q(VALUE self) +{ + CvMat *mat = CVMAT(self); + return (mat->width == 1|| mat->height == 1) ? Qtrue : Qfalse; +} + +/* + * Returns whether the matrix is a square. + * @overload square? + * @return [Boolean] If width = height, returns true. + * if not, returns false. + */ +VALUE +rb_square_q(VALUE self) +{ + CvMat *mat = CVMAT(self); + return mat->width == mat->height ? Qtrue : Qfalse; +} + +/************************************************************ + cxcore function +************************************************************/ +/* + * Converts an object to CvMat + * @overload to_CvMat + * @return [CvMat] Converted matrix + */ +VALUE +rb_to_CvMat(VALUE self) +{ + // CvMat#to_CvMat aborts when self's class is CvMat. + if (CLASS_OF(self) == rb_klass) + return self; + + CvMat *mat = NULL; + try { + mat = cvGetMat(CVARR(self), RB_CVALLOC(CvMat)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return DEPEND_OBJECT(rb_klass, mat, self); +} + +/* + * Returns matrix corresponding to the rectangular sub-array of input image or matrix + * + * @overload sub_rect(rect) + * @param rect [CvRect] Zero-based coordinates of the rectangle of interest. + * @overload sub_rect(topleft, size) + * @param topleft [CvPoint] Top-left coordinates of the rectangle of interest + * @param size [CvSize] Size of the rectangle of interest + * @overload sub_rect(x, y, width, height) + * @param x [Integer] X-coordinate of the rectangle of interest + * @param y [Integer] Y-coordinate of the rectangle of interest + * @param width [Integer] Width of the rectangle of interest + * @param height [Integer] Height of the rectangle of interest + * @return [CvMat] Sub-array of matrix + * @opencv_func cvGetSubRect + */ +VALUE +rb_sub_rect(VALUE self, VALUE args) +{ + CvRect area; + CvPoint topleft; + CvSize size; + switch(RARRAY_LEN(args)) { + case 1: + area = VALUE_TO_CVRECT(RARRAY_PTR(args)[0]); + break; + case 2: + topleft = VALUE_TO_CVPOINT(RARRAY_PTR(args)[0]); + size = VALUE_TO_CVSIZE(RARRAY_PTR(args)[1]); + area.x = topleft.x; + area.y = topleft.y; + area.width = size.width; + area.height = size.height; + break; + case 4: + area.x = NUM2INT(RARRAY_PTR(args)[0]); + area.y = NUM2INT(RARRAY_PTR(args)[1]); + area.width = NUM2INT(RARRAY_PTR(args)[2]); + area.height = NUM2INT(RARRAY_PTR(args)[3]); + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%ld of 1 or 2 or 4)", RARRAY_LEN(args)); + } + + CvMat* mat = NULL; + try { + mat = cvGetSubRect(CVARR(self), RB_CVALLOC(CvMat), area); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return DEPEND_OBJECT(rb_klass, mat, self); +} + +void +rb_get_range_index(VALUE index, int* start, int *end) { + if (rb_obj_is_kind_of(index, rb_cRange)) { + *start = NUM2INT(rb_funcall3(index, rb_intern("begin"), 0, NULL)); + *end = NUM2INT(rb_funcall3(index, rb_intern("end"), 0, NULL)); + if (rb_funcall3(index, rb_intern("exclude_end?"), 0, NULL) == Qfalse) { + (*end)++; + } + } + else { + *start = NUM2INT(index); + *end = *start + 1; + } +} + +/* + * Returns array of row or row span. + * @overload get_rows(index, delta_row = 1) + * @param index [Integer] Zero-based index of the selected row + * @param delta_row [Integer] Index step in the row span. + * @return [CvMat] Selected row + * @overload get_rows(range, delta_row = 1) + * @param range [Range] Zero-based index range of the selected row + * @param delta_row [Integer] Index step in the row span. + * @return [CvMat] Selected rows + * @opencv_func cvGetRows + */ +VALUE +rb_get_rows(int argc, VALUE* argv, VALUE self) +{ + VALUE row_val, delta_val; + rb_scan_args(argc, argv, "11", &row_val, &delta_val); + + int start, end; + rb_get_range_index(row_val, &start, &end); + int delta = NIL_P(delta_val) ? 1 : NUM2INT(delta_val); + CvMat* submat = RB_CVALLOC(CvMat); + try { + cvGetRows(CVARR(self), submat, start, end, delta); + } + catch (cv::Exception& e) { + cvFree(&submat); + raise_cverror(e); + } + + return DEPEND_OBJECT(rb_klass, submat, self); +} + +/* + * Returns array of column or column span. + * @overload get_cols(index) + * @param index [Integer] Zero-based index of the selected column + * @return [CvMat] Selected column + * @overload get_cols(range) + * @param range [Range] Zero-based index range of the selected column + * @return [CvMat] Selected columns + * @opencv_func cvGetCols + */ +VALUE +rb_get_cols(VALUE self, VALUE col) +{ + int start, end; + rb_get_range_index(col, &start, &end); + CvMat* submat = RB_CVALLOC(CvMat); + try { + cvGetCols(CVARR(self), submat, start, end); + } + catch (cv::Exception& e) { + cvFree(&submat); + raise_cverror(e); + } + + return DEPEND_OBJECT(rb_klass, submat, self); +} + +/* + * Calls block once for each row in the matrix, passing that + * row as a parameter. + * @yield [row] Each row in the matrix + * @return [CvMat] self + * @opencv_func cvGetRow + * @todo To return an enumerator if no block is given + */ +VALUE +rb_each_row(VALUE self) +{ + int rows = CVMAT(self)->rows; + CvMat* row = NULL; + for (int i = 0; i < rows; ++i) { + try { + row = cvGetRow(CVARR(self), RB_CVALLOC(CvMat), i); + } + catch (cv::Exception& e) { + if (row != NULL) + cvReleaseMat(&row); + raise_cverror(e); + } + rb_yield(DEPEND_OBJECT(rb_klass, row, self)); + } + return self; +} + +/* + * Calls block once for each column in the matrix, passing that + * column as a parameter. + * @yield [col] Each column in the matrix + * @return [CvMat] self + * @opencv_func cvGetCol + * @todo To return an enumerator if no block is given + */ +VALUE +rb_each_col(VALUE self) +{ + int cols = CVMAT(self)->cols; + CvMat *col = NULL; + for (int i = 0; i < cols; ++i) { + try { + col = cvGetCol(CVARR(self), RB_CVALLOC(CvMat), i); + } + catch (cv::Exception& e) { + if (col != NULL) + cvReleaseMat(&col); + raise_cverror(e); + } + rb_yield(DEPEND_OBJECT(rb_klass, col, self)); + } + return self; +} + +/* + * Returns a specified diagonal of the matrix + * @overload diag(val = 0) + * @param val [Integer] Index of the array diagonal. Zero value corresponds to the main diagonal, + * -1 corresponds to the diagonal above the main, 1 corresponds to the diagonal below the main, + * and so forth. + * @return [CvMat] Specified diagonal + * @opencv_func cvGetDiag + */ +VALUE +rb_diag(int argc, VALUE *argv, VALUE self) +{ + VALUE val; + if (rb_scan_args(argc, argv, "01", &val) < 1) + val = INT2FIX(0); + CvMat* diag = NULL; + try { + diag = cvGetDiag(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(val)); + } + catch (cv::Exception& e) { + cvReleaseMat(&diag); + raise_cverror(e); + } + return DEPEND_OBJECT(rb_klass, diag, self); +} + +/* + * Returns size of the matrix + * @overload size + * @return [CvSize] Size of the matrix + * @opencv_func cvGetSize + */ +VALUE +rb_size(VALUE self) +{ + CvSize size; + try { + size = cvGetSize(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvSize::new_object(size); +} + +/* + * Returns array dimensions sizes + * @overload dims + * @return [Array] Array dimensions sizes. + * For 2d arrays the number of rows (height) goes first, number of columns (width) next. + * @opencv_func cvGetDims + */ +VALUE +rb_dims(VALUE self) +{ + int size[CV_MAX_DIM]; + int dims = 0; + try { + dims = cvGetDims(CVARR(self), size); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + VALUE ary = rb_ary_new2(dims); + for (int i = 0; i < dims; ++i) { + rb_ary_store(ary, i, INT2NUM(size[i])); + } + return ary; +} + +/* + * Returns array size along the specified dimension. + * @overload dim_size(index) + * @param index [Intger] Zero-based dimension index + * (for matrices 0 means number of rows, 1 means number of columns; + * for images 0 means height, 1 means width) + * @return [Integer] Array size + * @opencv_func cvGetDimSize + */ +VALUE +rb_dim_size(VALUE self, VALUE index) +{ + int dimsize = 0; + try { + dimsize = cvGetDimSize(CVARR(self), NUM2INT(index)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return INT2NUM(dimsize); +} + +/* + * Returns a specific array element. + * @overload [](idx0) + * @overload [](idx0, idx1) + * @overload [](idx0, idx1, idx2) + * @overload [](idx0, idx1, idx2, ...) + * @param idx-n [Integer] Zero-based component of the element index + * @return [CvScalar] Array element + * @opencv_func cvGet1D + * @opencv_func cvGet2D + * @opencv_func cvGet3D + * @opencv_func cvGetND + */ +VALUE +rb_aref(VALUE self, VALUE args) +{ + int index[CV_MAX_DIM]; + for (int i = 0; i < RARRAY_LEN(args); ++i) + index[i] = NUM2INT(rb_ary_entry(args, i)); + + CvScalar scalar = cvScalarAll(0); + try { + switch (RARRAY_LEN(args)) { + case 1: + scalar = cvGet1D(CVARR(self), index[0]); + break; + case 2: + scalar = cvGet2D(CVARR(self), index[0], index[1]); + break; + default: + scalar = cvGetND(CVARR(self), index); + break; + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvScalar::new_object(scalar); +} + +/* + * Changes the particular array element + * @overload []=(idx0, value) + * @overload []=(idx0, idx1, value) + * @overload []=(idx0, idx1, idx2, value) + * @overload []=(idx0, idx1, idx2, ..., value) + * @param idx-n [Integer] Zero-based component of the element index + * @param value [CvScalar] The assigned value + * @return [CvMat] self + * @opencv_func cvSet1D + * @opencv_func cvSet2D + * @opencv_func cvSet3D + * @opencv_func cvSetND + */ +VALUE +rb_aset(VALUE self, VALUE args) +{ + CvScalar scalar = VALUE_TO_CVSCALAR(rb_ary_pop(args)); + int index[CV_MAX_DIM]; + for (int i = 0; i < RARRAY_LEN(args); ++i) + index[i] = NUM2INT(rb_ary_entry(args, i)); + + try { + switch (RARRAY_LEN(args)) { + case 1: + cvSet1D(CVARR(self), index[0], scalar); + break; + case 2: + cvSet2D(CVARR(self), index[0], index[1], scalar); + break; + default: + cvSetND(CVARR(self), index, scalar); + break; + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Assigns user data to the array header + * @overload set_data(data) + * @param data [Array] User data + * @return [CvMat] self + * @opencv_func cvSetData + */ +VALUE +rb_set_data(VALUE self, VALUE data) +{ + data = rb_funcall(data, rb_intern("flatten"), 0); + const int DATA_LEN = RARRAY_LEN(data); + CvMat *self_ptr = CVMAT(self); + int depth = CV_MAT_DEPTH(self_ptr->type); + void* array = NULL; + + switch (depth) { + case CV_8U: + array = rb_cvAlloc(sizeof(uchar) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((uchar*)array)[i] = (uchar)(NUM2INT(rb_ary_entry(data, i))); + break; + case CV_8S: + array = rb_cvAlloc(sizeof(char) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((char*)array)[i] = (char)(NUM2INT(rb_ary_entry(data, i))); + break; + case CV_16U: + array = rb_cvAlloc(sizeof(ushort) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((ushort*)array)[i] = (ushort)(NUM2INT(rb_ary_entry(data, i))); + break; + case CV_16S: + array = rb_cvAlloc(sizeof(short) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((short*)array)[i] = (short)(NUM2INT(rb_ary_entry(data, i))); + break; + case CV_32S: + array = rb_cvAlloc(sizeof(int) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((int*)array)[i] = NUM2INT(rb_ary_entry(data, i)); + break; + case CV_32F: + array = rb_cvAlloc(sizeof(float) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((float*)array)[i] = (float)NUM2DBL(rb_ary_entry(data, i)); + break; + case CV_64F: + array = rb_cvAlloc(sizeof(double) * DATA_LEN); + for (int i = 0; i < DATA_LEN; ++i) + ((double*)array)[i] = NUM2DBL(rb_ary_entry(data, i)); + break; + default: + rb_raise(rb_eArgError, "Invalid CvMat depth"); + break; + } + + try { + cvSetData(self_ptr, array, self_ptr->step); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return self; +} + +/* + * Returns a matrix which is set every element to a given value. + * The function copies the scalar value to every selected element of the destination array: + * mat[I] = value if mask(I) != 0 + * + * @overload set(value, mask = nil) Fill value + * @param value [CvScalar] Fill value + * @param mask [CvMat] Operation mask, 8-bit single channel array; + * specifies elements of the destination array to be changed + * @return [CvMat] Matrix which is set every element to a given value. + * @opencv_func cvSet + */ +VALUE +rb_set(int argc, VALUE *argv, VALUE self) +{ + return rb_set_bang(argc, argv, copy(self)); +} + +/* + * Sets every element of the matrix to a given value. + * The function copies the scalar value to every selected element of the destination array: + * mat[I] = value if mask(I) != 0 + * + * @overload set!(value, mask = nil) + * @param (see #set) + * @return [CvMat] self + * @opencv_func cvSet + */ +VALUE +rb_set_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE value, mask; + rb_scan_args(argc, argv, "11", &value, &mask); + try { + cvSet(CVARR(self), VALUE_TO_CVSCALAR(value), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Saves an image to a specified file. + * The image format is chosen based on the filename extension. + * @overload save_image(filename) + * @param filename [String] Name of the file + * @return [CvMat] self + * @opencv_func cvSaveImage + */ +VALUE +rb_save_image(int argc, VALUE *argv, VALUE self) +{ + VALUE _filename, _params; + rb_scan_args(argc, argv, "11", &_filename, &_params); + Check_Type(_filename, T_STRING); + int *params = NULL; + if (!NIL_P(_params)) { + params = hash_to_format_specific_param(_params); + } + + try { + cvSaveImage(StringValueCStr(_filename), CVARR(self), params); + } + catch (cv::Exception& e) { + if (params != NULL) { + free(params); + params = NULL; + } + raise_cverror(e); + } + if (params != NULL) { + free(params); + params = NULL; + } + + return self; +} + +/* + * Returns cleared array. + * @overload set_zero + * @return [CvMat] Cleared array + * @opencv_func cvSetZero + */ +VALUE +rb_set_zero(VALUE self) +{ + return rb_set_zero_bang(copy(self)); +} + +/* + * Clears the array. + * @overload set_zero! + * @return [CvMat] self + * @opencv_func cvSetZero + */ +VALUE +rb_set_zero_bang(VALUE self) +{ + try { + cvSetZero(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns a scaled identity matrix. + * arr(i, j) = value if i = j, 0 otherwise + * @overload identity(value) + * @param value [CvScalar] Value to assign to diagonal elements. + * @return [CvMat] Scaled identity matrix. + * @opencv_func cvSetIdentity + */ +VALUE +rb_set_identity(int argc, VALUE *argv, VALUE self) +{ + return rb_set_identity_bang(argc, argv, copy(self)); +} + +/* + * Initializes a scaled identity matrix. + * arr(i, j) = value if i = j, 0 otherwise + * @overload identity!(value) + * @param (see #identity) + * @return [CvMat] self + * @opencv_func cvSetIdentity + */ +VALUE +rb_set_identity_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE val; + CvScalar value; + if (rb_scan_args(argc, argv, "01", &val) < 1) + value = cvRealScalar(1); + else + value = VALUE_TO_CVSCALAR(val); + + try { + cvSetIdentity(CVARR(self), value); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns initialized matrix as following: + * arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr)) + * @overload range(start, end) + * @param start [Number] The lower inclusive boundary of the range + * @param end [Number] The upper exclusive boundary of the range + * @return [CvMat] Initialized matrix + * @opencv_func cvRange + */ +VALUE +rb_range(VALUE self, VALUE start, VALUE end) +{ + return rb_range_bang(copy(self), start, end); +} + +/* + * Initializes the matrix as following: + * arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr)) + * @overload range!(start, end) + * @param (see #range) + * @return [CvMat] self + * @opencv_func cvRange + */ +VALUE +rb_range_bang(VALUE self, VALUE start, VALUE end) +{ + try { + cvRange(CVARR(self), NUM2DBL(start), NUM2DBL(end)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Changes shape of matrix/image without copying data. + * @overload reshape(cn, rows=0) + * @param cn [Integer] New number of channels. If the parameter is 0, the number of channels remains the same. + * @param rows [Integer] New number of rows. If the parameter is 0, the number of rows remains the same. + * @return [CvMat] Changed matrix + * @opencv_func cvReshape + * @example + * mat = CvMat.new(3, 3, CV_8U, 3) #=> 3x3 3-channel matrix + * vec = mat.reshape(:rows => 1) #=> 1x9 3-channel matrix + * ch1 = mat.reshape(:channel => 1) #=> 9x3 1-channel matrix + */ +VALUE +rb_reshape(int argc, VALUE *argv, VALUE self) +{ + VALUE cn, rows; + CvMat *mat = NULL; + rb_scan_args(argc, argv, "11", &cn, &rows); + try { + mat = cvReshape(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(cn), IF_INT(rows, 0)); + } + catch (cv::Exception& e) { + if (mat != NULL) + cvReleaseMat(&mat); + raise_cverror(e); + } + return DEPEND_OBJECT(rb_klass, mat, self); +} + +/* + * Fills the destination array with repeated copies of the source array. + * + * @overload repeat(dst) + * @param dst [CvMat] Destination array of the same type as self. + * @return [CvMat] Destination array + * @opencv_func cvRepeat + */ +VALUE +rb_repeat(VALUE self, VALUE object) +{ + try { + cvRepeat(CVARR(self), CVARR_WITH_CHECK(object)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return object; +} + +/* + * Returns a fliped 2D array around vertical, horizontal, or both axes. + * + * @overload flip(flip_mode) + * @param flip_mode [Symbol] Flag to specify how to flip the array. + * - :x - Flipping around the x-axis. + * - :y - Flipping around the y-axis. + * - :xy - Flipping around both axes. + * @return [CvMat] Flipped array + * @opencv_func cvFlip + */ +VALUE +rb_flip(int argc, VALUE *argv, VALUE self) +{ + return rb_flip_bang(argc, argv, copy(self)); +} + +/* + * Flips a 2D array around vertical, horizontal, or both axes. + * + * @overload flip!(flip_mode) + * @param (see #flip) + * @return (see #flip) + * @opencv_func (see #flip) + */ +VALUE +rb_flip_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE format; + int mode = 1; + if (rb_scan_args(argc, argv, "01", &format) > 0) { + Check_Type(format, T_SYMBOL); + ID flip_mode = rb_to_id(format); + if (flip_mode == rb_intern("x")) { + mode = 1; + } + else if (flip_mode == rb_intern("y")) { + mode = 0; + } + else if (flip_mode == rb_intern("xy")) { + mode = -1; + } + } + try { + cvFlip(CVARR(self), NULL, mode); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Divides a multi-channel array into several single-channel arrays. + * + * @overload split + * @return [Array] Array of single-channel arrays + * @opencv_func cvSplit + * @see merge + * @example + * img = CvMat.new(640, 480, CV_8U, 3) #=> 3-channel image + * a = img.split #=> [img-ch1, img-ch2, img-ch3] + */ +VALUE +rb_split(VALUE self) +{ + CvArr* self_ptr = CVARR(self); + int type = cvGetElemType(self_ptr); + int depth = CV_MAT_DEPTH(type), channel = CV_MAT_CN(type); + VALUE dest = rb_ary_new2(channel); + try { + CvArr *dest_ptr[] = { NULL, NULL, NULL, NULL }; + CvSize size = cvGetSize(self_ptr); + for (int i = 0; i < channel; ++i) { + VALUE tmp = new_mat_kind_object(size, self, depth, 1); + rb_ary_store(dest, i, tmp); + dest_ptr[i] = CVARR(tmp); + } + cvSplit(self_ptr, dest_ptr[0], dest_ptr[1], dest_ptr[2], dest_ptr[3]); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dest; +} + +/* + * Composes a multi-channel array from several single-channel arrays. + * + * @overload merge(src1 = nil, src2 = nil, src3 = nil, src4 = nil) + * @param src-n [CvMat] Source arrays to be merged. + * All arrays must have the same size and the same depth. + * @return [CvMat] Merged array + * @opencv_func cvMerge + * @see split + * @scope class + */ +VALUE +rb_merge(VALUE klass, VALUE args) +{ + int len = RARRAY_LEN(args); + if (len <= 0 || len > 4) { + rb_raise(rb_eArgError, "wrong number of argument (%d for 1..4)", len); + } + CvMat *src[] = { NULL, NULL, NULL, NULL }, *prev_src = NULL; + for (int i = 0; i < len; ++i) { + VALUE object = rb_ary_entry(args, i); + if (NIL_P(object)) + src[i] = NULL; + else { + src[i] = CVMAT_WITH_CHECK(object); + if (CV_MAT_CN(src[i]->type) != 1) + rb_raise(rb_eArgError, "image should be single-channel CvMat."); + if (prev_src == NULL) + prev_src = src[i]; + else { + if (!CV_ARE_SIZES_EQ(prev_src, src[i])) + rb_raise(rb_eArgError, "image size should be same."); + if (!CV_ARE_DEPTHS_EQ(prev_src, src[i])) + rb_raise(rb_eArgError, "image depth should be same."); + } + } + } + // TODO: adapt IplImage + VALUE dest = Qnil; + try { + dest = new_object(cvGetSize(src[0]), CV_MAKETYPE(CV_MAT_DEPTH(src[0]->type), len)); + cvMerge(src[0], src[1], src[2], src[3], CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Returns shuffled matrix by swapping randomly chosen pairs of the matrix elements on each iteration + * (where each element may contain several components in case of multi-channel arrays) + * + * @overload rand_shuffle(seed = -1, iter_factor = 1) + * @param seed [Integer] Integer value used to initiate a random sequence + * @param iter_factor [Integer] The relative parameter that characterizes intensity of + * the shuffling performed. The number of iterations (i.e. pairs swapped) is + * round(iter_factor*rows(mat)*cols(mat)), so iter_factor = 0 means that no shuffling is done, + * iter_factor = 1 means that the function swaps rows(mat)*cols(mat) random pairs etc + * @return [CvMat] Shuffled matrix + * @opencv_func cvRandShuffle + */ +VALUE +rb_rand_shuffle(int argc, VALUE *argv, VALUE self) +{ + return rb_rand_shuffle_bang(argc, argv, copy(self)); +} + +/* + * Shuffles the matrix by swapping randomly chosen pairs of the matrix elements on each iteration + * (where each element may contain several components in case of multi-channel arrays) + * + * @overload rand_shuffle!(seed = -1, iter_factor = 1) + * @param (see #rand_shuffle) + * @return (see #rand_shuffle) + * @opencv_func (see #rand_shuffle) + */ +VALUE +rb_rand_shuffle_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE seed, iter; + rb_scan_args(argc, argv, "02", &seed, &iter); + try { + if (NIL_P(seed)) + cvRandShuffle(CVARR(self), NULL, IF_INT(iter, 1)); + else { + CvRNG rng = cvRNG(rb_num2ll(seed)); + cvRandShuffle(CVARR(self), &rng, IF_INT(iter, 1)); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Performs a look-up table transform of an array. + * + * @overload lut(lut) + * @param lut [CvMat] Look-up table of 256 elements. In case of multi-channel source array, + * the table should either have a single channel (in this case the same table is used + * for all channels) or the same number of channels as in the source array. + * @return [CvMat] Transformed array + * @opencv_func cvLUT + */ +VALUE +rb_lut(VALUE self, VALUE lut) +{ + VALUE dest = copy(self); + try { + cvLUT(CVARR(self), CVARR(dest), CVARR_WITH_CHECK(lut)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Converts one array to another with optional linear transformation. + * + * @overload convert_scale(params) + * @param params [Hash] Transform parameters + * @option params [Integer] :depth (same as self) Depth of the destination array + * @option params [Number] :scale (1.0) Scale factor + * @option params [Number] :shift (0.0) Value added to the scaled source array elements + * @return [CvMat] Converted array + * @opencv_func cvConvertScale + */ +VALUE +rb_convert_scale(VALUE self, VALUE hash) +{ + Check_Type(hash, T_HASH); + CvMat* self_ptr = CVMAT(self); + VALUE depth = LOOKUP_HASH(hash, "depth"); + VALUE scale = LOOKUP_HASH(hash, "scale"); + VALUE shift = LOOKUP_HASH(hash, "shift"); + + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self, + CVMETHOD("DEPTH", depth, CV_MAT_DEPTH(self_ptr->type)), + CV_MAT_CN(self_ptr->type)); + cvConvertScale(self_ptr, CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Scales, computes absolute values, and converts the result to 8-bit. + * + * @overload convert_scale_abs(params) + * @param params [Hash] Transform parameters + * @option params [Number] :scale (1.0) Scale factor + * @option params [Number] :shift (0.0) Value added to the scaled source array elements + * @return [CvMat] Converted array + * @opencv_func cvConvertScaleAbs + */ +VALUE +rb_convert_scale_abs(VALUE self, VALUE hash) +{ + Check_Type(hash, T_HASH); + CvMat* self_ptr = CVMAT(self); + VALUE scale = LOOKUP_HASH(hash, "scale"); + VALUE shift = LOOKUP_HASH(hash, "shift"); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_8U, CV_MAT_CN(CVMAT(self)->type)); + cvConvertScaleAbs(self_ptr, CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Computes the per-element sum of two arrays or an array and a scalar. + * + * @overload add(val, mask = nil) + * @param val [CvMat, CvScalar] Array or scalar to add + * @param mask [CvMat] Optional operation mask, 8-bit single channel array, + * that specifies elements of the destination array to be changed. + * @return [CvMat] Result array + * @opencv_func cvAdd + * @opencv_func cvAddS + */ +VALUE +rb_add(int argc, VALUE *argv, VALUE self) +{ + VALUE val, mask, dest; + rb_scan_args(argc, argv, "11", &val, &mask); + dest = copy(self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvAdd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); + else + cvAddS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the per-element difference between two arrays or array and a scalar. + * + * @overload sub(val, mask = nil) + * @param val [CvMat, CvScalar] Array or scalar to subtract + * @param mask [CvMat] Optional operation mask, 8-bit single channel array, + * that specifies elements of the destination array to be changed. + * @return [CvMat] Result array + * @opencv_func cvSub + * @opencv_func cvSubS + */ +VALUE +rb_sub(int argc, VALUE *argv, VALUE self) +{ + VALUE val, mask, dest; + rb_scan_args(argc, argv, "11", &val, &mask); + dest = copy(self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvSub(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); + else + cvSubS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the per-element scaled product of two arrays. + * + * @overload mul(val, scale = 1.0) + * @param val [CvMat, CvScalar] Array or scalar to multiply + * @param scale [Number] Optional scale factor. + * @return [CvMat] Result array + * @opencv_func cvMul + */ +VALUE +rb_mul(int argc, VALUE *argv, VALUE self) +{ + VALUE val, scale, dest; + if (rb_scan_args(argc, argv, "11", &val, &scale) < 2) + scale = rb_float_new(1.0); + dest = new_mat_kind_object(cvGetSize(CVARR(self)), self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvMul(CVARR(self), CVARR(val), CVARR(dest), NUM2DBL(scale)); + else { + CvScalar scl = VALUE_TO_CVSCALAR(val); + VALUE mat = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self))); + cvSet(CVARR(mat), scl); + cvMul(CVARR(self), CVARR(mat), CVARR(dest), NUM2DBL(scale)); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the product of two arrays. + * dst = self * val + shiftvec + * + * @overload mat_mul(val, shiftvec = nil) + * @param val [CvMat] Array to multiply + * @param shiftvec [CvMat] Optional translation vector + * @return [CvMat] Result array + * @opencv_func cvMatMul + * @opencv_func cvMatMulAdd + */ +VALUE +rb_mat_mul(int argc, VALUE *argv, VALUE self) +{ + VALUE val, shiftvec, dest; + rb_scan_args(argc, argv, "11", &val, &shiftvec); + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + try { + if (NIL_P(shiftvec)) + cvMatMul(self_ptr, CVARR_WITH_CHECK(val), CVARR(dest)); + else + cvMatMulAdd(self_ptr, CVARR_WITH_CHECK(val), CVARR_WITH_CHECK(shiftvec), CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs per-element division of two arrays or a scalar by an array. + * + * @overload div(val, scale = 1.0) + * @param val [CvMat, CvScalar] Array or scalar to divide + * @param scale [Number] Scale factor + * @return [CvMat] Result array + * @opencv_func cvDiv + */ +VALUE +rb_div(int argc, VALUE *argv, VALUE self) +{ + VALUE val, scale; + if (rb_scan_args(argc, argv, "11", &val, &scale) < 2) + scale = rb_float_new(1.0); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + if (rb_obj_is_kind_of(val, rb_klass)) + cvDiv(self_ptr, CVARR(val), CVARR(dest), NUM2DBL(scale)); + else { + CvScalar scl = VALUE_TO_CVSCALAR(val); + VALUE mat = new_mat_kind_object(cvGetSize(self_ptr), self); + CvArr* mat_ptr = CVARR(mat); + cvSet(mat_ptr, scl); + cvDiv(self_ptr, mat_ptr, CVARR(dest), NUM2DBL(scale)); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Computes the weighted sum of two arrays. + * This function calculates the weighted sum of two arrays as follows: + * dst(I) = src1(I) * alpha + src2(I) * beta + gamma + * + * @overload add_weighted(src1, alpha, src2, beta, gamma) + * @param src1 [CvMat] The first source array. + * @param alpha [Number] Weight for the first array elements. + * @param src2 [CvMat] The second source array. + * @param beta [Number] Weight for the second array elements. + * @param gamma [Number] Scalar added to each sum. + * @return [CvMat] Result array + * @opencv_func cvAddWeighted + */ +VALUE +rb_add_weighted(VALUE klass, VALUE src1, VALUE alpha, VALUE src2, VALUE beta, VALUE gamma) +{ + CvArr* src1_ptr = CVARR_WITH_CHECK(src1); + VALUE dst = new_mat_kind_object(cvGetSize(src1_ptr), src1); + try { + cvAddWeighted(src1_ptr, NUM2DBL(alpha), + CVARR_WITH_CHECK(src2), NUM2DBL(beta), + NUM2DBL(gamma), CVARR(dst)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dst; +} + +/* + * Calculates the per-element bit-wise conjunction of two arrays or an array and a scalar. + * + * @overload and(val, mask = nil) + * @param val [CvMat, CvScalar] Array or scalar to calculate bit-wise conjunction + * @param mask [CvMat] Optional operation mask, 8-bit single channel array, that specifies + * elements of the destination array to be changed. + * @return [CvMat] Result array + * @opencv_func cvAnd + * @opencv_func cvAndS + */ +VALUE +rb_and(int argc, VALUE *argv, VALUE self) +{ + VALUE val, mask, dest; + rb_scan_args(argc, argv, "11", &val, &mask); + dest = copy(self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvAnd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); + else + cvAndS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the per-element bit-wise disjunction of two arrays or an array and a scalar. + * + * @overload or(val, mask = nil) + * @param val [CvMat, CvScalar] Array or scalar to calculate bit-wise disjunction + * @param mask [CvMat] Optional operation mask, 8-bit single channel array, that specifies + * elements of the destination array to be changed. + * @return [CvMat] Result array + * @opencv_func cvOr + * @opencv_func cvOrS + */ +VALUE +rb_or(int argc, VALUE *argv, VALUE self) +{ + VALUE val, mask, dest; + rb_scan_args(argc, argv, "11", &val, &mask); + dest = copy(self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvOr(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); + else + cvOrS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the per-element bit-wise "exclusive or" operation on two arrays or an array and a scalar. + * + * @overload xor(val, mask = nil) + * @param val [CvMat, CvScalar] Array or scalar to calculate bit-wise xor operation. + * @param mask [CvMat] Optional operation mask, 8-bit single channel array, that specifies + * elements of the destination array to be changed. + * @return [CvMat] Result array + * @opencv_func cvXor + * @opencv_func cvXorS + */ +VALUE +rb_xor(int argc, VALUE *argv, VALUE self) +{ + VALUE val, mask, dest; + rb_scan_args(argc, argv, "11", &val, &mask); + dest = copy(self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvXor(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); + else + cvXorS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Returns an array which elements are bit-wise invertion of source array. + * + * @overload not + * @return [CvMat] Result array + * @opencv_func cvNot + */ +VALUE +rb_not(VALUE self) +{ + return rb_not_bang(copy(self)); +} + +/* + * Inverts every bit of an array. + * + * @overload not! + * @return [CvMat] Result array + * @opencv_func cvNot + */ +VALUE +rb_not_bang(VALUE self) +{ + try { + cvNot(CVARR(self), CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +VALUE +rb_cmp_internal(VALUE self, VALUE val, int operand) +{ + CvArr* self_ptr = CVARR(self); + VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_8U, 1); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvCmp(self_ptr, CVARR(val), CVARR(dest), operand); + else if (CV_MAT_CN(cvGetElemType(self_ptr)) == 1 && rb_obj_is_kind_of(val, rb_cNumeric)) + cvCmpS(self_ptr, NUM2DBL(val), CVARR(dest), operand); + else { + VALUE mat = new_mat_kind_object(cvGetSize(CVARR(self)), self); + cvSet(CVARR(mat), VALUE_TO_CVSCALAR(val)); + cvCmp(self_ptr, CVARR(mat), CVARR(dest), operand); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs the per-element comparison "equal" of two arrays or an array and scalar value. + * + * @overload eq(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_eq(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_EQ); +} + +/* + * Performs the per-element comparison "greater than" of two arrays or an array and scalar value. + * + * @overload gt(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_gt(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_GT); +} + +/* + * Performs the per-element comparison "greater than or equal" of two arrays or an array and scalar value. + * + * @overload ge(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_ge(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_GE); +} + +/* + * Performs the per-element comparison "less than" of two arrays or an array and scalar value. + * + * @overload lt(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_lt(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_LT); +} + +/* + * Performs the per-element comparison "less than or equal" of two arrays or an array and scalar value. + * + * @overload le(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_le(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_LE); +} + +/* + * Performs the per-element comparison "not equal" of two arrays or an array and scalar value. + * + * @overload ne(val) + * @param val [CvMat, CvScalar, Number] Array, scalar or number to compare + * @return [CvMat] Result array + * @opencv_func cvCmp + * @opencv_func cvCmpS + */ +VALUE +rb_ne(VALUE self, VALUE val) +{ + return rb_cmp_internal(self, val, CV_CMP_NE); +} + +/* + * Checks if array elements lie between the elements of two other arrays. + * + * @overload in_range(min, max) + * @param min [CvMat, CvScalar] Inclusive lower boundary array or a scalar. + * @param max [CvMat, CvScalar] Inclusive upper boundary array or a scalar. + * @return [CvMat] Result array + * @opencv_func cvInRange + * @opencv_func cvInRangeS + */ +VALUE +rb_in_range(VALUE self, VALUE min, VALUE max) +{ + CvArr* self_ptr = CVARR(self); + CvSize size = cvGetSize(self_ptr); + VALUE dest = new_object(size, CV_8UC1); + try { + if (rb_obj_is_kind_of(min, rb_klass) && rb_obj_is_kind_of(max, rb_klass)) + cvInRange(self_ptr, CVARR(min), CVARR(max), CVARR(dest)); + else if (rb_obj_is_kind_of(min, rb_klass)) { + VALUE tmp = new_object(size, cvGetElemType(self_ptr)); + cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(max)); + cvInRange(self_ptr, CVARR(min), CVARR(tmp), CVARR(dest)); + } + else if (rb_obj_is_kind_of(max, rb_klass)) { + VALUE tmp = new_object(size, cvGetElemType(self_ptr)); + cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(min)); + cvInRange(self_ptr, CVARR(tmp), CVARR(max), CVARR(dest)); + } + else + cvInRangeS(self_ptr, VALUE_TO_CVSCALAR(min), VALUE_TO_CVSCALAR(max), CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Computes the per-element absolute difference between two arrays or between an array and a scalar. + * + * @overload abs_diff(val) + * @param val [CvMat, CvScalar] Array or scalar to compute absolute difference + * @return [CvMat] Result array + * @opencv_func cvAbsDiff + * @opencv_func cvAbsDiffS + */ +VALUE +rb_abs_diff(VALUE self, VALUE val) +{ + CvArr* self_ptr = CVARR(self); + VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); + try { + if (rb_obj_is_kind_of(val, rb_klass)) + cvAbsDiff(self_ptr, CVARR(val), CVARR(dest)); + else + cvAbsDiffS(self_ptr, CVARR(dest), VALUE_TO_CVSCALAR(val)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Normalizes the norm or value range of an array. + * + * @overload normalize(alpha = 1.0, beta = 0.0, norm_type = NORM_L2, dtype = -1, mask = nil) + * @param alpha [Number] Norm value to normalize to or the lower range boundary + * in case of the range normalization. + * @param beta [Number] Upper range boundary in case of the range normalization. + * It is not used for the norm normalization. + * @param norm_type [Integer] Normalization type. + * @param dtype [Integer] when negative, the output array has the same type as src; + * otherwise, it has the same number of channels as src and the depth + * @param mask [CvMat] Optional operation mask. + * @return [CvMat] Normalized array. + * @opencv_func cv::normalize + */ +VALUE +rb_normalize(int argc, VALUE *argv, VALUE self) +{ + VALUE alpha_val, beta_val, norm_type_val, dtype_val, mask_val; + rb_scan_args(argc, argv, "05", &alpha_val, &beta_val, &norm_type_val, &dtype_val, &mask_val); + + double alpha = NIL_P(alpha_val) ? 1.0 : NUM2DBL(alpha_val); + double beta = NIL_P(beta_val) ? 0.0 : NUM2DBL(beta_val); + int norm_type = NIL_P(norm_type_val) ? cv::NORM_L2 : NUM2INT(norm_type_val); + int dtype = NIL_P(dtype_val) ? -1 : NUM2INT(dtype_val); + VALUE dst; + + try { + cv::Mat self_mat(CVMAT(self)); + cv::Mat dst_mat; + + if (NIL_P(mask_val)) { + cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype); + } + else { + cv::Mat mask(MASK(mask_val)); + cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype, mask); + } + dst = new_mat_kind_object(cvGetSize(CVARR(self)), self, dst_mat.depth(), dst_mat.channels()); + + CvMat tmp = dst_mat; + cvCopy(&tmp, CVMAT(dst)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dst; +} + +/* + * Counts non-zero array elements. + * + * @overload count_non_zero + * @return [Integer] The number of non-zero elements. + * @opencv_func cvCountNonZero + */ +VALUE +rb_count_non_zero(VALUE self) +{ + int n = 0; + try { + n = cvCountNonZero(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return INT2NUM(n); +} + +/* + * Calculates the sum of array elements. + * + * @overload sum + * @return [CvScalar] The sum of array elements. + * @opencv_func cvSum + */ +VALUE +rb_sum(VALUE self) +{ + CvScalar sum; + try { + sum = cvSum(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvScalar::new_object(sum); +} + +/* + * Calculates an average (mean) of array elements. + * @overload avg(mask = nil) + * @param mask [CvMat] Optional operation mask. + * @return [CvScalar] The average of array elements. + * @opencv_func cvAvg + */ +VALUE +rb_avg(int argc, VALUE *argv, VALUE self) +{ + VALUE mask; + rb_scan_args(argc, argv, "01", &mask); + CvScalar avg; + try { + avg = cvAvg(CVARR(self), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvScalar::new_object(avg); +} + +/* + * Calculates a mean and standard deviation of array elements. + * @overload avg_sdv(mask = nil) + * @param mask [CvMat] Optional operation mask. + * @return [Array] [mean, stddev], + * where mean is the computed mean value and stddev is the computed standard deviation. + * @opencv_func cvAvgSdv + */ +VALUE +rb_avg_sdv(int argc, VALUE *argv, VALUE self) +{ + VALUE mask, mean, std_dev; + rb_scan_args(argc, argv, "01", &mask); + mean = cCvScalar::new_object(); + std_dev = cCvScalar::new_object(); + try { + cvAvgSdv(CVARR(self), CVSCALAR(mean), CVSCALAR(std_dev), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, mean, std_dev); +} + +/* + * Calculates a standard deviation of array elements. + * @overload sdv(mask = nil) + * @param mask [CvMat] Optional operation mask. + * @return [CvScalar] The standard deviation of array elements. + * @opencv_func cvAvgSdv + */ +VALUE +rb_sdv(int argc, VALUE *argv, VALUE self) +{ + VALUE mask, std_dev; + rb_scan_args(argc, argv, "01", &mask); + std_dev = cCvScalar::new_object(); + try { + cvAvgSdv(CVARR(self), NULL, CVSCALAR(std_dev), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return std_dev; +} + +/* + * Finds the global minimum and maximum in an array. + * + * @overload min_max_loc(mask = nil) + * @param mask [CvMat] Optional mask used to select a sub-array. + * @return [Array] [min_val, max_val, min_loc, max_loc], where + * min_val, max_val are minimum, maximum values as Number and + * min_loc, max_loc are minimum, maximum locations as CvPoint, respectively. + * @opencv_func cvMinMaxLoc + */ +VALUE +rb_min_max_loc(int argc, VALUE *argv, VALUE self) +{ + VALUE mask, min_loc, max_loc; + double min_val = 0.0, max_val = 0.0; + rb_scan_args(argc, argv, "01", &mask); + min_loc = cCvPoint::new_object(); + max_loc = cCvPoint::new_object(); + try { + cvMinMaxLoc(CVARR(self), &min_val, &max_val, CVPOINT(min_loc), CVPOINT(max_loc), MASK(mask)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(4, rb_float_new(min_val), rb_float_new(max_val), min_loc, max_loc); +} + +/* + * Calculates the dot product of two arrays in Euclidean metrics. + * + * @overload dot_product(mat) + * @param mat [CvMat] An array to calculate the dot product. + * @return [Number] The dot product of two arrays. + * @opencv_func cvDotProduct + */ +VALUE +rb_dot_product(VALUE self, VALUE mat) +{ + double result = 0.0; + try { + result = cvDotProduct(CVARR(self), CVARR_WITH_CHECK(mat)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_float_new(result); +} + +/* + * Calculates the cross product of two 3D vectors. + * + * @overload cross_product(mat) + * @param mat [CvMat] A vector to calculate the cross product. + * @return [CvMat] The cross product of two vectors. + * @opencv_func cvCrossProduct + */ +VALUE +rb_cross_product(VALUE self, VALUE mat) +{ + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvCrossProduct(self_ptr, CVARR_WITH_CHECK(mat), CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs the matrix transformation of every array element. + * + * @overload transform(transmat, shiftvec = nil) + * @param transmat [CvMat] Transformation 2x2 or 2x3 floating-point matrix. + * @param shiftvec [CvMat] Optional translation vector. + * @return [CvMat] Transformed array. + * @opencv_func cvTransform + */ +VALUE +rb_transform(int argc, VALUE *argv, VALUE self) +{ + VALUE transmat, shiftvec; + rb_scan_args(argc, argv, "11", &transmat, &shiftvec); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvTransform(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(transmat), + NIL_P(shiftvec) ? NULL : CVMAT_WITH_CHECK(shiftvec)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs the perspective matrix transformation of vectors. + * + * @overload perspective_transform(mat) + * @param mat [CvMat] 3x3 or 4x4 floating-point transformation matrix. + * @return [CvMat] Transformed vector. + * @opencv_func cvPerspectiveTransform + */ +VALUE +rb_perspective_transform(VALUE self, VALUE mat) +{ + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvPerspectiveTransform(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(mat)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the product of a matrix and its transposition. + * + * This function calculates the product of self and its transposition: + * if :order = 0 + * dst = scale * (self - delta) * (self - delta)T + * otherwise + * dst = scale * (self - delta)T * (self - delta) + * + * @overload mul_transposed(options) + * @param options [Hash] Options + * @option options [Integer] :order (0) Flag specifying the multiplication ordering, should be 0 or 1. + * @option options [CvMat] :delta (nil) Optional delta matrix subtracted from source before the multiplication. + * @option options [Number] :scale (1.0) Optional scale factor for the matrix product. + * @return [CvMat] Result array. + * @opencv_func cvMulTransposed + */ +VALUE +rb_mul_transposed(int argc, VALUE *argv, VALUE self) +{ + VALUE options = Qnil; + VALUE _delta = Qnil, _scale = Qnil, _order = Qnil; + + if (rb_scan_args(argc, argv, "01", &options) > 0) { + Check_Type(options, T_HASH); + _delta = LOOKUP_HASH(options, "delta"); + _scale = LOOKUP_HASH(options, "scale"); + _order = LOOKUP_HASH(options, "order"); + } + + CvArr* delta = NIL_P(_delta) ? NULL : CVARR_WITH_CHECK(_delta); + double scale = NIL_P(_scale) ? 1.0 : NUM2DBL(_scale); + int order = NIL_P(_order) ? 0 : NUM2INT(_order); + CvArr* self_ptr = CVARR(self); + VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); + try { + cvMulTransposed(self_ptr, CVARR(dest), order, delta, scale); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dest; +} + + +/* + * Returns the trace of a matrix. + * + * @overload trace + * @return [CvScalar] The trace of a matrix. + * @opencv_func cvTrace + */ +VALUE +rb_trace(VALUE self) +{ + CvScalar scalar; + try { + scalar = cvTrace(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvScalar::new_object(scalar); +} + +/* + * Transposes a matrix. + * + * @overload transpose + * @return [CvMat] Transposed matrix. + * @opencv_func cvTranspose + */ +VALUE +rb_transpose(VALUE self) +{ + CvMat* self_ptr = CVMAT(self); + VALUE dest = new_mat_kind_object(cvSize(self_ptr->rows, self_ptr->cols), self); + try { + cvTranspose(self_ptr, CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Returns the determinant of a square floating-point matrix. + * + * @overload det + * @return [Number] The determinant of the matrix. + * @opencv_func cvDet + */ +VALUE +rb_det(VALUE self) +{ + double det = 0.0; + try { + det = cvDet(CVARR(self)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_float_new(det); +} + +/* + * Finds inverse or pseudo-inverse of matrix. + * + * @overload invert(inversion_method = :lu) + * @param inversion_method [Symbol] Inversion method. + * * :lu - Gaussian elimincation with optimal pivot element chose. + * * :svd - Singular value decomposition(SVD) method. + * * :svd_sym - SVD method for a symmetric positively-defined matrix. + * @return [Number] Inverse or pseudo-inverse of matrix. + * @opencv_func cvInvert + */ +VALUE +rb_invert(int argc, VALUE *argv, VALUE self) +{ + VALUE symbol; + rb_scan_args(argc, argv, "01", &symbol); + int method = CVMETHOD("INVERSION_METHOD", symbol, CV_LU); + VALUE dest = Qnil; + CvArr* self_ptr = CVARR(self); + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvInvert(self_ptr, CVARR(dest), method); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Solves one or more linear systems or least-squares problems. + * + * @overload solve(src1, src2, inversion_method = :lu) + * @param src1 [CvMat] Input matrix on the left-hand side of the system. + * @param src2 [CvMat] Input matrix on the right-hand side of the system. + * @param inversion_method [Symbol] Inversion method. + * * :lu - Gaussian elimincation with optimal pivot element chose. + * * :svd - Singular value decomposition(SVD) method. + * * :svd_sym - SVD method for a symmetric positively-defined matrix. + * @return [Number] Output solution. + * @scope class + * @opencv_func cvSolve + */ +VALUE +rb_solve(int argc, VALUE *argv, VALUE self) +{ + VALUE src1, src2, symbol; + rb_scan_args(argc, argv, "21", &src1, &src2, &symbol); + VALUE dest = Qnil; + CvArr* src2_ptr = CVARR_WITH_CHECK(src2); + try { + dest = new_mat_kind_object(cvGetSize(src2_ptr), src2); + cvSolve(CVARR_WITH_CHECK(src1), src2_ptr, CVARR(dest), CVMETHOD("INVERSION_METHOD", symbol, CV_LU)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs SVD of a matrix + * @overload svd(flag = 0) + * @param flag [Integer] Operation flags. + * * CV_SVD_MODIFY_A - Use the algorithm to modify the decomposed matrix. It can save space and speed up processing. + * * CV_SVD_U_T - Indicate that only a vector of singular values w is to be computed, while u and v will be set to empty matrices. + * * CV_SVD_V_T - When the matrix is not square, by default the algorithm produces u and v matrices of sufficiently large size for the further A reconstruction. If, however, CV_SVD_V_T flag is specified, u and v will be full-size square orthogonal matrices. + * @return [Array] Array of the computed values [w, u, v], where + * * w - Computed singular values + * * u - Computed left singular vectors + * * v - Computed right singular vectors + * @opencv_func cvSVD + */ +VALUE +rb_svd(int argc, VALUE *argv, VALUE self) +{ + VALUE _flag = Qnil; + int flag = 0; + if (rb_scan_args(argc, argv, "01", &_flag) > 0) { + flag = NUM2INT(_flag); + } + + CvMat* self_ptr = CVMAT(self); + VALUE w = new_mat_kind_object(cvSize(self_ptr->cols, self_ptr->rows), self); + + int rows = 0; + int cols = 0; + if (flag & CV_SVD_U_T) { + rows = MIN(self_ptr->rows, self_ptr->cols); + cols = self_ptr->rows; + } + else { + rows = self_ptr->rows; + cols = MIN(self_ptr->rows, self_ptr->cols); + } + VALUE u = new_mat_kind_object(cvSize(cols, rows), self); + + if (flag & CV_SVD_V_T) { + rows = MIN(self_ptr->rows, self_ptr->cols); + cols = self_ptr->cols; + } + else { + rows = self_ptr->cols; + cols = MIN(self_ptr->rows, self_ptr->cols); + } + VALUE v = new_mat_kind_object(cvSize(cols, rows), self); + + cvSVD(self_ptr, CVARR(w), CVARR(u), CVARR(v), flag); + + return rb_ary_new3(3, w, u, v); +} + +/* + * Computes eigenvalues and eigenvectors of symmetric matrix. + * self should be symmetric square matrix. self is modified during the processing. + * + * @overload eigenvv + * @return [Array] Array of [eigenvalues, eigenvectors] + * @opencv_func cvEigenVV + */ +VALUE +rb_eigenvv(int argc, VALUE *argv, VALUE self) +{ + VALUE epsilon, lowindex, highindex; + rb_scan_args(argc, argv, "03", &epsilon, &lowindex, &highindex); + double eps = (NIL_P(epsilon)) ? 0.0 : NUM2DBL(epsilon); + int lowidx = (NIL_P(lowindex)) ? -1 : NUM2INT(lowindex); + int highidx = (NIL_P(highindex)) ? -1 : NUM2INT(highindex); + VALUE eigen_vectors = Qnil, eigen_values = Qnil; + CvArr* self_ptr = CVARR(self); + try { + CvSize size = cvGetSize(self_ptr); + int type = cvGetElemType(self_ptr); + eigen_vectors = new_object(size, type); + eigen_values = new_object(size.height, 1, type); + // NOTE: eps, lowidx, highidx are ignored in the current OpenCV implementation. + cvEigenVV(self_ptr, CVARR(eigen_vectors), CVARR(eigen_values), eps, lowidx, highidx); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, eigen_vectors, eigen_values); +} + + +/* + * Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array. + * + * @overload dft(flags = CV_DXT_FORWARD, nonzero_rows = 0) + * @param flags [Integer] transformation flags, representing a combination of the following values: + * * CV_DXT_FORWARD - Performs a 1D or 2D transform. + * * CV_DXT_INVERSE - Performs an inverse 1D or 2D transform instead of the default forward transform. + * * CV_DXT_SCALE - Scales the result: divide it by the number of array elements. + * Normally, it is combined with CV_DXT_INVERSE. + * * CV_DXT_INV_SCALE - CV_DXT_INVERSE + CV_DXT_SCALE + * @param nonzero_rows [Integer] when the parameter is not zero, the function assumes that only + * the first nonzero_rows rows of the input array (CV_DXT_INVERSE is not set) + * or only the first nonzero_rows of the output array (CV_DXT_INVERSE is set) contain non-zeros. + * @return [CvMat] Output array + * @opencv_func cvDFT + */ +VALUE +rb_dft(int argc, VALUE *argv, VALUE self) +{ + VALUE flag_value, nonzero_row_value; + rb_scan_args(argc, argv, "02", &flag_value, &nonzero_row_value); + + int flags = NIL_P(flag_value) ? CV_DXT_FORWARD : NUM2INT(flag_value); + int nonzero_rows = NIL_P(nonzero_row_value) ? 0 : NUM2INT(nonzero_row_value); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvDFT(self_ptr, CVARR(dest), flags, nonzero_rows); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs forward or inverse Discrete Cosine Transform(DCT) of 1D or 2D floating-point array. + * + * @overload dct(flags = CV_DXT_FORWARD) + * @param flags [Integer] transformation flags, representing a combination of the following values: + * * CV_DXT_FORWARD - Performs a 1D or 2D transform. + * * CV_DXT_INVERSE - Performs an inverse 1D or 2D transform instead of the default forward transform. + * * CV_DXT_ROWS - Performs a forward or inverse transform of every individual row of the input matrix. + * This flag enables you to transform multiple vectors simultaneously and can be used to decrease + * the overhead (which is sometimes several times larger than the processing itself) to perform 3D + * and higher-dimensional transforms and so forth. + * @return [CvMat] Output array + * @opencv_func cvDCT + */ +VALUE +rb_dct(int argc, VALUE *argv, VALUE self) +{ + VALUE flag_value; + rb_scan_args(argc, argv, "01", &flag_value); + + int flags = NIL_P(flag_value) ? CV_DXT_FORWARD : NUM2INT(flag_value); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvDCT(self_ptr, CVARR(dest), flags); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Returns an image that is drawn a line segment connecting two points. + * + * @overload line(p1, p2, options = nil) + * @param p1 [CvPoint] First point of the line segment. + * @param p2 [CvPoint] Second point of the line segment. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvLine + */ +VALUE +rb_line(int argc, VALUE *argv, VALUE self) +{ + return rb_line_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a line segment connecting two points. + * + * @overload line!(p1, p2, options = nil) + * @param p1 [CvPoint] First point of the line segment. + * @param p2 [CvPoint] Second point of the line segment. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func (see #line) + */ +VALUE +rb_line_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, drawing_option; + rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option); + drawing_option = DRAWING_OPTION(drawing_option); + try { + cvLine(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is drawn a simple, thick, or filled up-right rectangle. + * + * @overload rectangle(p1, p2, options = nil) + * @param p1 [CvPoint] Vertex of the rectangle. + * @param p2 [CvPoint] Vertex of the rectangle opposite to p1. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvRectangle + */ +VALUE +rb_rectangle(int argc, VALUE *argv, VALUE self) +{ + return rb_rectangle_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a simple, thick, or filled up-right rectangle. + * + * @overload rectangle!(p1, p2, options = nil) + * @param p1 [CvPoint] Vertex of the rectangle. + * @param p2 [CvPoint] Vertex of the rectangle opposite to p1. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvRectangle + */ +VALUE +rb_rectangle_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, drawing_option; + rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option); + drawing_option = DRAWING_OPTION(drawing_option); + try { + cvRectangle(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is drawn a circle + * + * @overload circle(center, radius, options = nil) + * @param center [CvPoint] Center of the circle. + * @param radius [Integer] Radius of the circle. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvCircle + */ +VALUE +rb_circle(int argc, VALUE *argv, VALUE self) +{ + return rb_circle_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a circle + * + * @overload circle!(center, radius, options = nil) + * @param center [CvPoint] Center of the circle. + * @param radius [Integer] Radius of the circle. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvCircle + */ +VALUE +rb_circle_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE center, radius, drawing_option; + rb_scan_args(argc, argv, "21", ¢er, &radius, &drawing_option); + drawing_option = DRAWING_OPTION(drawing_option); + try { + cvCircle(CVARR(self), VALUE_TO_CVPOINT(center), NUM2INT(radius), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is drawn a simple or thick elliptic arc or fills an ellipse sector. + * + * @overload ellipse(center, axes, angle, start_angle, end_angle, options = nil) + * @param center [CvPoint] Center of the ellipse. + * @param axes [CvSize] Length of the ellipse axes. + * @param angle [Number] Ellipse rotation angle in degrees. + * @param start_angle [Number] Starting angle of the elliptic arc in degrees. + * @param end_angle [Number] Ending angle of the elliptic arc in degrees. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvEllipse + */ +VALUE +rb_ellipse(int argc, VALUE *argv, VALUE self) +{ + return rb_ellipse_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a simple or thick elliptic arc or fills an ellipse sector. + * + * @overload ellipse!(center, axes, angle, start_angle, end_angle, options = nil) + * @param center [CvPoint] Center of the ellipse. + * @param axes [CvSize] Length of the ellipse axes. + * @param angle [Number] Ellipse rotation angle in degrees. + * @param start_angle [Number] Starting angle of the elliptic arc in degrees. + * @param end_angle [Number] Ending angle of the elliptic arc in degrees. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvEllipse + */ +VALUE +rb_ellipse_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE center, axis, angle, start_angle, end_angle, drawing_option; + rb_scan_args(argc, argv, "51", ¢er, &axis, &angle, &start_angle, &end_angle, &drawing_option); + drawing_option = DRAWING_OPTION(drawing_option); + try { + cvEllipse(CVARR(self), VALUE_TO_CVPOINT(center), + VALUE_TO_CVSIZE(axis), + NUM2DBL(angle), NUM2DBL(start_angle), NUM2DBL(end_angle), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is drawn a simple or thick elliptic arc or fills an ellipse sector. + * + * @overload ellipse_box(box, options = nil) + * @param box [CvBox2D] Alternative ellipse representation via CvBox2D. This means that + * the function draws an ellipse inscribed in the rotated rectangle. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvEllipseBox + */ +VALUE +rb_ellipse_box(int argc, VALUE *argv, VALUE self) +{ + return rb_ellipse_box_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a simple or thick elliptic arc or fills an ellipse sector. + * + * @overload ellipse_box!(box, options = nil) + * @param box [CvBox2D] Alternative ellipse representation via CvBox2D. This means that + * the function draws an ellipse inscribed in the rotated rectangle. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvEllipseBox + */ +VALUE +rb_ellipse_box_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE box, drawing_option; + rb_scan_args(argc, argv, "11", &box, &drawing_option); + drawing_option = DRAWING_OPTION(drawing_option); + try { + cvEllipseBox(CVARR(self), VALUE_TO_CVBOX2D(box), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is filled the area bounded by one or more polygons. + * + * @overload fill_poly(points, options = nil) + * @param points [Array] Array of polygons where each polygon is represented as an array of points. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvFillPoly + */ +VALUE +rb_fill_poly(int argc, VALUE *argv, VALUE self) +{ + return rb_fill_poly_bang(argc, argv, self); +} + +/* + * Fills the area bounded by one or more polygons. + * + * @overload fill_poly!(points, options = nil) + * @param points [Array] Array of polygons where each polygon is represented as an array of points. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvFillPoly + */ +VALUE +rb_fill_poly_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE polygons, drawing_option; + VALUE points; + int i, j; + int num_polygons; + int *num_points; + CvPoint **p; + + rb_scan_args(argc, argv, "11", &polygons, &drawing_option); + Check_Type(polygons, T_ARRAY); + drawing_option = DRAWING_OPTION(drawing_option); + num_polygons = RARRAY_LEN(polygons); + num_points = ALLOCA_N(int, num_polygons); + + p = ALLOCA_N(CvPoint*, num_polygons); + for (j = 0; j < num_polygons; ++j) { + points = rb_ary_entry(polygons, j); + Check_Type(points, T_ARRAY); + num_points[j] = RARRAY_LEN(points); + p[j] = ALLOCA_N(CvPoint, num_points[j]); + for (i = 0; i < num_points[j]; ++i) { + p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); + } + } + try { + cvFillPoly(CVARR(self), p, num_points, num_polygons, + DO_COLOR(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is filled a convex polygon. + * + * @overload fill_convex_poly(points, options = nil) + * @param points [Array] Polygon vertices. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvFillConvexPoly + */ +VALUE +rb_fill_convex_poly(int argc, VALUE *argv, VALUE self) +{ + return rb_fill_convex_poly_bang(argc, argv, rb_clone(self)); +} + +/* + * Fills a convex polygon. + * + * @overload fill_convex_poly!(points, options = nil) + * @param points [Array] Polygon vertices. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvFillConvexPoly + */ +VALUE +rb_fill_convex_poly_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE points, drawing_option; + int i, num_points; + CvPoint *p; + + rb_scan_args(argc, argv, "11", &points, &drawing_option); + Check_Type(points, T_ARRAY); + drawing_option = DRAWING_OPTION(drawing_option); + num_points = RARRAY_LEN(points); + p = ALLOCA_N(CvPoint, num_points); + for (i = 0; i < num_points; ++i) + p[i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); + + try { + cvFillConvexPoly(CVARR(self), p, num_points, + DO_COLOR(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Returns an image that is drawn several polygonal curves. + * + * @overload poly_line(points, options = nil) + * @param points [Array] Array of polygonal curves. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Boolean] :is_closed + * Indicates whether the polylines must be drawn closed. + * If closed, the method draws the line from the last vertex + * of every contour to the first vertex. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] Output image + * @opencv_func cvPolyLine + */ +VALUE +rb_poly_line(int argc, VALUE *argv, VALUE self) +{ + return rb_poly_line_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws several polygonal curves. + * + * @overload poly_line!(points, options = nil) + * @param points [Array] Array of polygonal curves. + * @param options [Hash] Drawing options + * @option options [CvScalar] :color Line color. + * @option options [Integer] :thickness Line thickness. + * @option options [Integer] :line_type Type of the line. + * * 8 - 8-connected line. + * * 4 - 4-connected line. + * * CV_AA - Antialiased line. + * @option options [Boolean] :is_closed + * Indicates whether the polylines must be drawn closed. + * If closed, the method draws the line from the last vertex + * of every contour to the first vertex. + * @option options [Integer] :shift Number of fractional bits in the point coordinates. + * @return [CvMat] self + * @opencv_func cvPolyLine + */ +VALUE +rb_poly_line_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE polygons, drawing_option; + VALUE points; + int i, j; + int num_polygons; + int *num_points; + CvPoint **p; + + rb_scan_args(argc, argv, "11", &polygons, &drawing_option); + Check_Type(polygons, T_ARRAY); + drawing_option = DRAWING_OPTION(drawing_option); + num_polygons = RARRAY_LEN(polygons); + num_points = ALLOCA_N(int, num_polygons); + p = ALLOCA_N(CvPoint*, num_polygons); + + for (j = 0; j < num_polygons; ++j) { + points = rb_ary_entry(polygons, j); + Check_Type(points, T_ARRAY); + num_points[j] = RARRAY_LEN(points); + p[j] = ALLOCA_N(CvPoint, num_points[j]); + for (i = 0; i < num_points[j]; ++i) { + p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); + } + } + + try { + cvPolyLine(CVARR(self), p, num_points, num_polygons, + DO_IS_CLOSED(drawing_option), + DO_COLOR(drawing_option), + DO_THICKNESS(drawing_option), + DO_LINE_TYPE(drawing_option), + DO_SHIFT(drawing_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return self; +} + + +/* + * Returns an image which is drawn a text string. + * + * @overload put_text(text, org, font, color = CvColor::Black) + * @param text [String] Text string to be drawn. + * @param org [CvPoint] Bottom-left corner of the text string in the image. + * @param font [CvFont] CvFont object. + * @param color [CvScalar] Text color. + * @return [CvMat] Output image + * @opencv_func cvPutText + */ +VALUE +rb_put_text(int argc, VALUE* argv, VALUE self) +{ + return rb_put_text_bang(argc, argv, rb_clone(self)); +} + +/* + * Draws a text string. + * + * @overload put_text!(text, org, font, color = CvColor::Black) + * @param text [String] Text string to be drawn. + * @param org [CvPoint] Bottom-left corner of the text string in the image. + * @param font [CvFont] CvFont object. + * @param color [CvScalar] Text color. + * @return [CvMat] self + * @opencv_func cvPutText + */ +VALUE +rb_put_text_bang(int argc, VALUE* argv, VALUE self) +{ + VALUE _text, _point, _font, _color; + rb_scan_args(argc, argv, "31", &_text, &_point, &_font, &_color); + CvScalar color = NIL_P(_color) ? CV_RGB(0, 0, 0) : VALUE_TO_CVSCALAR(_color); + try { + cvPutText(CVARR(self), StringValueCStr(_text), VALUE_TO_CVPOINT(_point), + CVFONT_WITH_CHECK(_font), color); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. + * + * @overload sobel(xorder, yorder, aperture_size = 3) + * @param xorder [Integer] Order of the derivative x. + * @param yorder [Integer] Order of the derivative y. + * @param aperture_size [Integer] Size of the extended Sobel kernel; it must be 1, 3, 5, or 7. + * @return [CvMat] Output image. + * @opencv_func cvSovel + */ +VALUE +rb_sobel(int argc, VALUE *argv, VALUE self) +{ + VALUE xorder, yorder, aperture_size, dest; + if (rb_scan_args(argc, argv, "21", &xorder, &yorder, &aperture_size) < 3) + aperture_size = INT2FIX(3); + CvMat* self_ptr = CVMAT(self); + switch(CV_MAT_DEPTH(self_ptr->type)) { + case CV_8U: + dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_16S, 1); + break; + case CV_32F: + dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_32F, 1); + break; + default: + rb_raise(rb_eArgError, "source depth should be CV_8U or CV_32F."); + break; + } + + try { + cvSobel(self_ptr, CVARR(dest), NUM2INT(xorder), NUM2INT(yorder), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the Laplacian of an image. + * + * @overload laplace(aperture_size = 3) + * @param aperture_size [Integer] Aperture size used to compute the second-derivative filters. + * The size must be positive and odd. + * @return Output image. + * @opencv_func cvLaplace + */ +VALUE +rb_laplace(int argc, VALUE *argv, VALUE self) +{ + VALUE aperture_size, dest; + if (rb_scan_args(argc, argv, "01", &aperture_size) < 1) + aperture_size = INT2FIX(3); + CvMat* self_ptr = CVMAT(self); + switch(CV_MAT_DEPTH(self_ptr->type)) { + case CV_8U: + dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_16S, 1); + break; + case CV_32F: + dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_32F, 1); + break; + default: + rb_raise(rb_eArgError, "source depth should be CV_8U or CV_32F."); + } + + try { + cvLaplace(self_ptr, CVARR(dest), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Finds edges in an image using the [Canny86] algorithm. + * + * Canny86: J. Canny. A Computational Approach to Edge Detection, IEEE Trans. on Pattern Analysis + * and Machine Intelligence, 8(6), pp. 679-698 (1986). + * + * @overload canny(thresh1, thresh2, aperture_size = 3) + * @param thresh1 [Number] First threshold for the hysteresis procedure. + * @param thresh2 [Number] Second threshold for the hysteresis procedure. + * @param aperture_size [Integer] Aperture size for the sobel operator. + * @return [CvMat] Output edge map + * @opencv_func cvCanny + */ +VALUE +rb_canny(int argc, VALUE *argv, VALUE self) +{ + VALUE thresh1, thresh2, aperture_size; + if (rb_scan_args(argc, argv, "21", &thresh1, &thresh2, &aperture_size) < 3) + aperture_size = INT2FIX(3); + CvArr* self_ptr = CVARR(self); + VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); + + try { + cvCanny(self_ptr, CVARR(dest), NUM2INT(thresh1), NUM2INT(thresh2), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates a feature map for corner detection. + * + * @overload pre_corner_detect(aperture_size = 3) + * @param aperture_size [Integer] Aperture size for the sobel operator. + * @return [CvMat] Output image + * @opencv_func cvPreCornerDetect + */ +VALUE +rb_pre_corner_detect(int argc, VALUE *argv, VALUE self) +{ + VALUE aperture_size, dest = Qnil; + if (rb_scan_args(argc, argv, "01", &aperture_size) < 1) + aperture_size = INT2FIX(3); + + CvArr *self_ptr = CVARR(self); + try { + dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); + cvPreCornerDetect(self_ptr, CVARR(dest), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates eigenvalues and eigenvectors of image blocks for corner detection. + * + * @overload corner_eigenvv(block_size, aperture_size = 3) + * @param block_size [Integer] Neighborhood size. + * @param aperture_size [Integer] Aperture parameter for the sobel operator. + * @return [CvMat] Result array. + * @opencv_func cvCornerEigenValsAndVecs + */ +VALUE +rb_corner_eigenvv(int argc, VALUE *argv, VALUE self) +{ + VALUE block_size, aperture_size, dest; + if (rb_scan_args(argc, argv, "11", &block_size, &aperture_size) < 2) + aperture_size = INT2FIX(3); + CvMat* self_ptr = CVMAT(self); + dest = new_object(cvSize(self_ptr->cols * 6, self_ptr->rows), CV_MAKETYPE(CV_32F, 1)); + try { + cvCornerEigenValsAndVecs(self_ptr, CVARR(dest), NUM2INT(block_size), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Calculates the minimal eigenvalue of gradient matrices for corner detection. + * + * @overload corner_min_eigen_val(block_size, aperture_size = 3) + * @param block_size [Integer] Neighborhood size. + * @param aperture_size [Integer] Aperture parameter for the sobel operator. + * @return [CvMat] Result array. + * @opencv_func cvCornerMinEigenVal + */ +VALUE +rb_corner_min_eigen_val(int argc, VALUE *argv, VALUE self) +{ + VALUE block_size, aperture_size, dest; + if (rb_scan_args(argc, argv, "11", &block_size, &aperture_size) < 2) + aperture_size = INT2FIX(3); + CvArr* self_ptr = CVARR(self); + dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); + try { + cvCornerMinEigenVal(self_ptr, CVARR(dest), NUM2INT(block_size), NUM2INT(aperture_size)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Harris edge detector. + * + * @overload corner_harris(block_size, aperture_size = 3, k = 0.04) + * @param block_size [Integer] Neighborhood size. + * @param aperture_size [Integer] Aperture parameter for the sobel operator. + * @param k [Number] Harris detector free parameter. + * @return [CvMat] The Harris detector responses. + * @opencv_func cvCornerHarris + */ +VALUE +rb_corner_harris(int argc, VALUE *argv, VALUE self) +{ + VALUE block_size, aperture_size, k, dest; + rb_scan_args(argc, argv, "12", &block_size, &aperture_size, &k); + CvArr* self_ptr = CVARR(self); + dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); + try { + cvCornerHarris(self_ptr, CVARR(dest), NUM2INT(block_size), IF_INT(aperture_size, 3), IF_DBL(k, 0.04)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Finds the positions of internal corners of the chessboard. + * + * @overload find_chessboard_corners(pattern_size, flag = CV_CALIB_CB_ADAPTIVE_THRESH) + * @param pattern_size [CvSize] Number of inner corners per a chessboard row and column. + * @param flags [Integer] Various operation flags that can be zero or a combination of the following values. + * * CV_CALIB_CB_ADAPTIVE_THRESH + * * Use adaptive thresholding to convert the image to black and white, rather than + * a fixed threshold level (computed from the average image brightness). + * * CV_CALIB_CB_NORMALIZE_IMAGE + * * Normalize the image gamma with CvMat#equalize_hist() before applying fixed or adaptive thresholding. + * * CV_CALIB_CB_FILTER_QUADS + * * Use additional criteria (like contour area, perimeter, square-like shape) to + * filter out false quads extracted at the contour retrieval stage. + * * CALIB_CB_FAST_CHECK + * * Run a fast check on the image that looks for chessboard corners, and shortcut the call + * if none is found. This can drastically speed up the call in the degenerate condition + * when no chessboard is observed. + * @return [Array, Boolean>] An array which includes the positions of internal corners + * of the chessboard, and a parameter indicating whether the complete board was found or not. + * @opencv_func cvFindChessboardCorners + * @example + * mat = CvMat.load('chessboard.jpg', 1) + * gray = mat.BGR2GRAY + * pattern_size = CvSize.new(4, 4) + * corners, found = gray.find_chessboard_corners(pattern_size, CV_CALIB_CB_ADAPTIVE_THRESH) + * + * if found + * corners = gray.find_corner_sub_pix(corners, CvSize.new(3, 3), CvSize.new(-1, -1), CvTermCriteria.new(20, 0.03)) + * end + * + * result = mat.draw_chessboard_corners(pattern_size, corners, found) + * w = GUI::Window.new('Result') + * w.show result + * GUI::wait_key + */ +VALUE +rb_find_chessboard_corners(int argc, VALUE *argv, VALUE self) +{ + VALUE pattern_size_val, flag_val; + rb_scan_args(argc, argv, "11", &pattern_size_val, &flag_val); + + int flag = NIL_P(flag_val) ? CV_CALIB_CB_ADAPTIVE_THRESH : NUM2INT(flag_val); + CvSize pattern_size = VALUE_TO_CVSIZE(pattern_size_val); + CvPoint2D32f* corners = ALLOCA_N(CvPoint2D32f, pattern_size.width * pattern_size.height); + int num_found_corners = 0; + int pattern_was_found = 0; + try { + pattern_was_found = cvFindChessboardCorners(CVARR(self), pattern_size, corners, &num_found_corners, flag); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + VALUE found_corners = rb_ary_new2(num_found_corners); + for (int i = 0; i < num_found_corners; i++) { + rb_ary_store(found_corners, i, cCvPoint2D32f::new_object(corners[i])); + } + + VALUE found = (pattern_was_found > 0) ? Qtrue : Qfalse; + return rb_assoc_new(found_corners, found); +} + +/* + * Refines the corner locations. + * + * @overload find_corner_sub_pix(corners, win_size, zero_zone, criteria) + * @param corners [Array] Initial coordinates of the input corners. + * @param win_size [CvSize] Half of the side length of the search window. + * @param zero_zone [CvSize] Half of the size of the dead region in the middle of the search zone over + * which the summation in the formula below is not done. + * @param criteria [CvTermCriteria] Criteria for termination of the iterative process of corner refinement. + * @return [Array] Refined corner coordinates. + * @opencv_func cvFindCornerSubPix + */ +VALUE +rb_find_corner_sub_pix(VALUE self, VALUE corners, VALUE win_size, VALUE zero_zone, VALUE criteria) +{ + Check_Type(corners, T_ARRAY); + int count = RARRAY_LEN(corners); + CvPoint2D32f* corners_buff = ALLOCA_N(CvPoint2D32f, count); + VALUE* corners_ptr = RARRAY_PTR(corners); + + for (int i = 0; i < count; i++) { + corners_buff[i] = *(CVPOINT2D32F(corners_ptr[i])); + } + + try { + cvFindCornerSubPix(CVARR(self), corners_buff, count, VALUE_TO_CVSIZE(win_size), + VALUE_TO_CVSIZE(zero_zone), VALUE_TO_CVTERMCRITERIA(criteria)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + VALUE refined_corners = rb_ary_new2(count); + for (int i = 0; i < count; i++) { + rb_ary_store(refined_corners, i, cCvPoint2D32f::new_object(corners_buff[i])); + } + + return refined_corners; +} + +/* + * Determines strong corners on an image. + * + * @overload good_features_to_track(quality_level, min_distance, good_features_to_track_option = {}) + * @param quality_level [Number] Parameter characterizing the minimal accepted quality of image corners. + * The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue + * or the Harris function response. + * @param min_distance [Number] Minimum possible Euclidean distance between the returned corners. + * @param good_features_to_track_option [Hash] Options. + * @option good_features_to_track_option [CvMat] :mask (nil) Optional region of interest. + * If the image is not empty (it needs to have the type CV_8UC1 and the same size as image), + * it specifies the region in which the corners are detected. + * @option good_features_to_track_option [Integer] :block_size (3) Size of an average block for computing + * a derivative covariation matrix over each pixel neighborhood. + * @option good_features_to_track_option [Boolean] :use_harris (false) Parameter indicating whether + * to use a Harris detector. + * @option good_features_to_track_option [Number] :k (0.04) Free parameter of the Harris detector. + * @return [Array] Output vector of detected corners. + * @opencv_func cvGoodFeaturesToTrack + */ +VALUE +rb_good_features_to_track(int argc, VALUE *argv, VALUE self) +{ + VALUE quality_level, min_distance, good_features_to_track_option; + rb_scan_args(argc, argv, "21", &quality_level, &min_distance, &good_features_to_track_option); + good_features_to_track_option = GOOD_FEATURES_TO_TRACK_OPTION(good_features_to_track_option); + int np = GF_MAX(good_features_to_track_option); + if (np <= 0) + rb_raise(rb_eArgError, "option :max should be positive value."); + + CvMat *self_ptr = CVMAT(self); + CvPoint2D32f *p32 = (CvPoint2D32f*)rb_cvAlloc(sizeof(CvPoint2D32f) * np); + int type = CV_MAKETYPE(CV_32F, 1); + CvMat* eigen = rb_cvCreateMat(self_ptr->rows, self_ptr->cols, type); + CvMat* tmp = rb_cvCreateMat(self_ptr->rows, self_ptr->cols, type); + try { + cvGoodFeaturesToTrack(self_ptr, &eigen, &tmp, p32, &np, NUM2DBL(quality_level), NUM2DBL(min_distance), + GF_MASK(good_features_to_track_option), + GF_BLOCK_SIZE(good_features_to_track_option), + GF_USE_HARRIS(good_features_to_track_option), + GF_K(good_features_to_track_option)); + } + catch (cv::Exception& e) { + if (eigen != NULL) + cvReleaseMat(&eigen); + if (tmp != NULL) + cvReleaseMat(&tmp); + if (p32 != NULL) + cvFree(&p32); + raise_cverror(e); + } + VALUE corners = rb_ary_new2(np); + for (int i = 0; i < np; ++i) + rb_ary_store(corners, i, cCvPoint2D32f::new_object(p32[i])); + cvFree(&p32); + cvReleaseMat(&eigen); + cvReleaseMat(&tmp); + return corners; +} + +/* + * Retrieves a pixel rectangle from an image with sub-pixel accuracy. + * + * @overload rect_sub_pix(center, size = self.size) + * @param center [CvPoint2D32f] Floating point coordinates of the center of the extracted rectangle within + * the source image. The center must be inside the image. + * @param size [CvSize] Size of the extracted patch. + * @return [CvMat] Extracted patch that has the size size and the same number of channels as self. + * @opencv_func cvGetRectSubPix + */ +VALUE +rb_rect_sub_pix(int argc, VALUE *argv, VALUE self) +{ + VALUE center, size; + VALUE dest = Qnil; + CvSize _size; + CvArr* self_ptr = CVARR(self); + try { + if (rb_scan_args(argc, argv, "11", ¢er, &size) < 2) + _size = cvGetSize(self_ptr); + else + _size = VALUE_TO_CVSIZE(size); + dest = new_mat_kind_object(_size, self); + cvGetRectSubPix(self_ptr, CVARR(dest), VALUE_TO_CVPOINT2D32F(center)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Applies an affine transformation to an image. + * + * @overload quadrangle_sub_pix(map_matrix, size = self.size) + * @param map_matrix [CvMat] 2x3 transformation matrix. + * @param size [CvSize] Size of the output image. + * @return [CvMat] Output image that has the size size and the same type as self. + * @opencv_func cvGetQuadrangleSubPix + * @note CvMat#quadrangle_sub_pix is similar to CvMat#warp_affine, but the outliers are + * extrapolated using replication border mode. + */ +VALUE +rb_quadrangle_sub_pix(int argc, VALUE *argv, VALUE self) +{ + VALUE map_matrix, size; + VALUE dest = Qnil; + CvSize _size; + CvArr* self_ptr = CVARR(self); + try { + if (rb_scan_args(argc, argv, "11", &map_matrix, &size) < 2) + _size = cvGetSize(self_ptr); + else + _size = VALUE_TO_CVSIZE(size); + dest = new_mat_kind_object(_size, self); + cvGetQuadrangleSubPix(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Resizes an image. + * + * @overload resize(size, interpolation = :linear) + * @param size [CvSize] Output image size. + * @param interpolation [Symbol] Interpolation method: + * * CV_INTER_NN - A nearest-neighbor interpolation + * * CV_INTER_LINEAR - A bilinear interpolation (used by default) + * * CV_INTER_AREA - Resampling using pixel area relation. It may be a preferred method for + * image decimation, as it gives moire'-free results. But when the image is zoomed, + * it is similar to the :nn method. + * * CV_INTER_CUBIC - A bicubic interpolation over 4x4 pixel neighborhood + * * CV_INTER_LANCZOS4 - A Lanczos interpolation over 8x8 pixel neighborhood + * @return [CvMat] Output image. + * @opencv_func cvResize + */ +VALUE +rb_resize(int argc, VALUE *argv, VALUE self) +{ + VALUE size, interpolation; + rb_scan_args(argc, argv, "11", &size, &interpolation); + VALUE dest = new_mat_kind_object(VALUE_TO_CVSIZE(size), self); + int method = NIL_P(interpolation) ? CV_INTER_LINEAR : NUM2INT(interpolation); + + try { + cvResize(CVARR(self), CVARR(dest), method); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Applies an affine transformation to an image. + * + * @overload warp_affine(map_matrix, flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, fillval = 0) + * @param map_matrix [CvMat] 2x3 transformation matrix. + * @param flags [Integer] Combination of interpolation methods (#see resize) and the optional + * flag WARP_INVERSE_MAP that means that map_matrix is the inverse transformation. + * @return [CvMat] Output image that has the size size and the same type as self. + * @param fillval [Number, CvScalar] Value used in case of a constant border. + * @opencv_func cvWarpAffine + */ +VALUE +rb_warp_affine(int argc, VALUE *argv, VALUE self) +{ + VALUE map_matrix, flags_val, fill_value; + VALUE dest = Qnil; + if (rb_scan_args(argc, argv, "12", &map_matrix, &flags_val, &fill_value) < 3) + fill_value = INT2FIX(0); + CvArr* self_ptr = CVARR(self); + int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvWarpAffine(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix), + flags, VALUE_TO_CVSCALAR(fill_value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Finds a perspective transformation between two planes. + * + * @overload find_homography(src_points, dst_points, method = :all, ransac_reproj_threshold = 3, get_mask = false) + * @param src_points [CvMat] Coordinates of the points in the original plane. + * @param dst_points [CvMat] Coordinates of the points in the target plane. + * @param method [Symbol] Method used to computed a homography matrix. The following methods are possible: + * * :all - a regular method using all the points + * * :ransac - RANSAC-based robust method + * * :lmeds - Least-Median robust method + * @param ransac_reproj_threshold [Number] Maximum allowed reprojection error to treat a point pair as + * an inlier (used in the RANSAC method only). + * @param get_mask [Boolean] If true, the optional output mask set by + * a robust method (:ransac or :lmeds) is returned additionally. + * @return [CvMat, Array] The perspective transformation H between the source and the destination + * planes in CvMat. + * If method is :ransac or :lmeds and get_mask is true, the output mask + * is also returned in the form of an array [H, output_mask]. + * @scope class + * @opencv_func cvFindHomography + */ +VALUE +rb_find_homography(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_WITH_CHECK(src_points); + int num_points = MAX(src->rows, src->cols); + VALUE status = new_object(cvSize(num_points, 1), CV_8UC1); + try { + cvFindHomography(src, CVMAT_WITH_CHECK(dst_points), CVMAT(homography), + _method, _ransac_reproj_threshold, CVMAT(status)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_assoc_new(homography, status); + } + else { + try { + cvFindHomography(CVMAT(src_points), CVMAT(dst_points), CVMAT(homography), + _method, _ransac_reproj_threshold, NULL); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return homography; + } +} + +/* + * Calculates an affine matrix of 2D rotation. + * + * @overload rotation_matrix2D(center, angle, scale) + * @param center [CvPoint2D32f] Center of the rotation in the source image. + * @param angle [Number] Rotation angle in degrees. Positive values mean counter-clockwise rotation + * (the coordinate origin is assumed to be the top-left corner). + * @param scale [Number] Isotropic scale factor. + * @return [CvMat] The output affine transformation, 2x3 floating-point matrix. + * @scope class + * @opencv_func cv2DRotationMatrix + */ +VALUE +rb_rotation_matrix2D(VALUE self, VALUE center, VALUE angle, VALUE scale) +{ + VALUE map_matrix = new_object(cvSize(3, 2), CV_MAKETYPE(CV_32F, 1)); + try { + cv2DRotationMatrix(VALUE_TO_CVPOINT2D32F(center), NUM2DBL(angle), NUM2DBL(scale), CVMAT(map_matrix)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return map_matrix; +} + +/* + * Calculates a perspective transform from four pairs of the corresponding points. + * + * @overload get_perspective_transform(src, dst) + * @param src [Array] Coordinates of quadrangle vertices in the source image. + * @param dst [Array] Coordinates of the corresponding quadrangle vertices in the destination image. + * @return [CvMat] Map matrix + * @scope class + * @opencv_func cvGetPerspectiveTransform + */ +VALUE +rb_get_perspective_transform(VALUE self, VALUE source, VALUE dest) +{ + Check_Type(source, T_ARRAY); + Check_Type(dest, T_ARRAY); + + int count = RARRAY_LEN(source); + + CvPoint2D32f* source_buff = ALLOCA_N(CvPoint2D32f, count); + CvPoint2D32f* dest_buff = ALLOCA_N(CvPoint2D32f, count); + + for (int i = 0; i < count; i++) { + source_buff[i] = *(CVPOINT2D32F(RARRAY_PTR(source)[i])); + dest_buff[i] = *(CVPOINT2D32F(RARRAY_PTR(dest)[i])); + } + + VALUE map_matrix = new_object(cvSize(3, 3), CV_MAKETYPE(CV_32F, 1)); + + try { + cvGetPerspectiveTransform(source_buff, dest_buff, CVMAT(map_matrix)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return map_matrix; +} + +/* + * Applies a perspective transformation to an image. + * + * @overload warp_perspective(map_matrix, flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, fillval = 0) + * @param map_matrix [CvMat] 3x3 transformation matrix. + * @param flags [Integer] Combination of interpolation methods (CV_INTER_LINEAR or CV_INTER_NEAREST) + * and the optional flag CV_WARP_INVERSE_MAP, that sets map_matrix as the inverse transformation. + * @param fillval [Number, CvScalar] Value used in case of a constant border. + * @return [CvMat] Output image. + * @opencv_func cvWarpPerspective + */ +VALUE +rb_warp_perspective(int argc, VALUE *argv, VALUE self) +{ + VALUE map_matrix, flags_val, option, fillval; + if (rb_scan_args(argc, argv, "13", &map_matrix, &flags_val, &option, &fillval) < 4) + fillval = INT2FIX(0); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvWarpPerspective(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix), + flags, VALUE_TO_CVSCALAR(fillval)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Applies a generic geometrical transformation to an image. + * + * @overload remap(mapx, mapy, flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, fillval = 0) + * @param mapx [CvMat] The first map of either (x,y) points or just x values having the type + * CV_16SC2, CV_32FC1, or CV_32FC2. + * @param mapy [CvMat] The second map of y values having the type CV_16UC1, CV_32FC1, or none + * (empty map if mapx is (x,y) points), respectively. + * @param flags [Integer] Combination of interpolation methods (CV_INTER_LINEAR or CV_INTER_NEAREST) + * and the optional flag CV_WARP_INVERSE_MAP, that sets map_matrix as the inverse transformation. + * @param fillval [Number, CvScalar] Value used in case of a constant border. + * @return [CvMat] Output image. + * @opencv_func cvRemap + */ +VALUE +rb_remap(int argc, VALUE *argv, VALUE self) +{ + VALUE mapx, mapy, flags_val, option, fillval; + if (rb_scan_args(argc, argv, "23", &mapx, &mapy, &flags_val, &option, &fillval) < 5) + fillval = INT2FIX(0); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvRemap(self_ptr, CVARR(dest), CVARR_WITH_CHECK(mapx), CVARR_WITH_CHECK(mapy), + flags, VALUE_TO_CVSCALAR(fillval)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Remaps an image to log-polar space. + * + * @overload log_polar(size, center, magnitude, flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) + * @param size [CvSize] Size of the destination image. + * @param center [CvPoint2D32f] The transformation center; where the output precision is maximal. + * @param magnitude [Number] Magnitude scale parameter. + * @param flags [Integer] A combination of interpolation methods and the following optional flags: + * * CV_WARP_FILL_OUTLIERS - fills all of the destination image pixels. If some of them + * correspond to outliers in the source image, they are set to zero. + * * CV_WARP_INVERSE_MAP - performs inverse transformation. + * @return [CvMat] Destination image. + * @opencv_func cvLogPolar + */ +VALUE +rb_log_polar(int argc, VALUE *argv, VALUE self) +{ + VALUE dst_size, center, m, flags; + rb_scan_args(argc, argv, "31", &dst_size, ¢er, &m, &flags); + int _flags = NIL_P(flags) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags); + VALUE dest = new_mat_kind_object(VALUE_TO_CVSIZE(dst_size), self); + try { + cvLogPolar(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT2D32F(center), NUM2DBL(m), _flags); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * call-seq: + * erode([element = nil, iteration = 1]) -> cvmat + * + * Create erodes image by using arbitrary structuring element. + * element is structuring element used for erosion. + * element should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used. + * iterations is number of times erosion is applied. + */ +VALUE +rb_erode(int argc, VALUE *argv, VALUE self) +{ + return rb_erode_bang(argc, argv, rb_clone(self)); +} + +/* + * call-seq: + * erode!([element = nil][,iteration = 1]) -> self + * + * Erodes image by using arbitrary structuring element. + * see also #erode. + */ +VALUE +rb_erode_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE element, iteration; + rb_scan_args(argc, argv, "02", &element, &iteration); + IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); + try { + cvErode(CVARR(self), CVARR(self), kernel, IF_INT(iteration, 1)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * call-seq: + * dilate([element = nil][,iteration = 1]) -> cvmat + * + * Create dilates image by using arbitrary structuring element. + * element is structuring element used for erosion. + * element should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used. + * iterations is number of times erosion is applied. + */ +VALUE +rb_dilate(int argc, VALUE *argv, VALUE self) +{ + return rb_dilate_bang(argc, argv, rb_clone(self)); +} + +/* + * call-seq: + * dilate!([element = nil][,iteration = 1]) -> self + * + * Dilate image by using arbitrary structuring element. + * see also #dilate. + */ +VALUE +rb_dilate_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE element, iteration; + rb_scan_args(argc, argv, "02", &element, &iteration); + IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); + try { + cvDilate(CVARR(self), CVARR(self), kernel, IF_INT(iteration, 1)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * call-seq: + * morpholohy(operation[,element = nil][,iteration = 1]) -> cvmat + * + * Performs advanced morphological transformations. + * operation + * Type of morphological operation, one of: + * CV_MOP_OPEN - opening + * CV_MOP_CLOSE - closing + * CV_MOP_GRADIENT - morphological gradient + * CV_MOP_TOPHAT - top hat + * CV_MOP_BLACKHAT - black hat + */ +VALUE +rb_morphology(int argc, VALUE *argv, VALUE self) +{ + VALUE element, iteration, operation_val; + rb_scan_args(argc, argv, "12", &operation_val, &element, &iteration); + + int operation = CVMETHOD("MORPHOLOGICAL_OPERATION", operation_val, -1); + CvArr* self_ptr = CVARR(self); + CvSize size = cvGetSize(self_ptr); + VALUE dest = new_mat_kind_object(size, self); + IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); + try { + if (operation == CV_MOP_GRADIENT) { + CvMat* temp = rb_cvCreateMat(size.height, size.width, cvGetElemType(self_ptr)); + cvMorphologyEx(self_ptr, CVARR(dest), temp, kernel, CV_MOP_GRADIENT, IF_INT(iteration, 1)); + cvReleaseMat(&temp); + } + else { + cvMorphologyEx(self_ptr, CVARR(dest), 0, kernel, operation, IF_INT(iteration, 1)); + } + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dest; +} + +/* + * call-seq: + * smooth_blur_no_scale([p1 = 3, p2 = 3]) -> cvmat + * + * Smooths the image by simple blur with no scaling. + * * 8bit unsigned -> return 16bit unsigned + * * 32bit floating point -> return 32bit floating point + * support single-channel image only. + */ +VALUE +rb_smooth_blur_no_scale(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, dest; + rb_scan_args(argc, argv, "02", &p1, &p2); + CvArr* self_ptr = CVARR(self); + int type = cvGetElemType(self_ptr), dest_type; + switch (CV_MAT_DEPTH(type)) { + case CV_8U: + dest_type = CV_16U; + break; + case CV_32F: + dest_type = CV_32F; + break; + default: + rb_raise(rb_eNotImpError, "unsupport format. (support 8bit unsigned/signed or 32bit floating point only)"); + } + dest = new_mat_kind_object(cvGetSize(self_ptr), self, dest_type, CV_MAT_CN(type)); + cvSmooth(self_ptr, CVARR(dest), CV_BLUR_NO_SCALE, IF_INT(p1, 3), IF_INT(p2, 3)); + return dest; +} + +/* + * call-seq: + * smooth_blur([p1 = 3, p2 = 3]) -> cvmat + * + * Smooths the image by simple blur. + * Summation over a pixel p1 x p2 neighborhood with subsequent scaling by 1 / (p1*p2). + */ +VALUE +rb_smooth_blur(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, dest; + rb_scan_args(argc, argv, "02", &p1, &p2); + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvSmooth(self_ptr, CVARR(dest), CV_BLUR, IF_INT(p1, 3), IF_INT(p2, 3)); + return dest; +} + +/* + * call-seq: + * smooth_gaussian([p1 = 3, p2 = 3, p3 = 0.0, p4 = 0.0]) -> cvmat + * + * Smooths the image by gaussian blur. + * Convolving image with p1 x p2 Gaussian kernel. + * + * p3 may specify Gaussian sigma (standard deviation). + * If it is zero, it is calculated from the kernel size: + * sigma = (n/2 - 1)*0.3 + 0.8, where n = p1 for horizontal kernel, + * n = p2 for vertical kernel. + * + * p4 is in case of non-square Gaussian kernel the parameter. + * It may be used to specify a different (from p3) sigma in the vertical direction. + */ +VALUE +rb_smooth_gaussian(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, p3, p4, dest; + rb_scan_args(argc, argv, "04", &p1, &p2, &p3, &p4); + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvSmooth(self_ptr, CVARR(dest), CV_GAUSSIAN, IF_INT(p1, 3), IF_INT(p2, 3), IF_DBL(p3, 0.0), IF_DBL(p4, 0.0)); + return dest; +} + +/* + * call-seq: + * smooth_median([p1 = 3]) -> cvmat + * + * Smooths the image by median blur. + * Finding median of p1 x p1 neighborhood (i.e. the neighborhood is square). + */ +VALUE +rb_smooth_median(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, dest; + rb_scan_args(argc, argv, "01", &p1); + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvSmooth(self_ptr, CVARR(dest), CV_MEDIAN, IF_INT(p1, 3)); + return dest; +} + +/* + * call-seq: + * smooth_bilateral([p1 = 3][p2 = 3]) -> cvmat + * + * Smooths the image by bilateral filter. + * Applying bilateral 3x3 filtering with color sigma=p1 and space sigma=p2. + */ +VALUE +rb_smooth_bilateral(int argc, VALUE *argv, VALUE self) +{ + VALUE p1, p2, dest; + rb_scan_args(argc, argv, "02", &p1, &p2); + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvSmooth(self_ptr, CVARR(dest), CV_BILATERAL, IF_INT(p1, 3), IF_INT(p2, 3)); + return dest; +} + +/** + * Smooths the image in one of several ways. + * + * @overload smooth(smoothtype, size1 = 3, size2 = 0, sigma1 = 0, sigma2 = 0) + * @param smoothtype [Integer] Type of the smoothing. + * * CV_BLUR_NO_SCALE - linear convolution with size1 x size2 box kernel (all 1's). + * If you want to smooth different pixels with different-size box kernels, + * you can use the integral image that is computed using CvMat#integral. + * * CV_BLUR - linear convolution with size1 x size2 box kernel (all 1's) + * with subsequent scaling by 1 / (size1 x size1). + * * CV_GAUSSIAN - linear convolution with a size1 x size2 Gaussian kernel. + * * CV_MEDIAN - median filter with a size1 x size1 square aperture + * * CV_BILATERAL - bilateral filter with a size1 x size1 square aperture, + * color sigma = sigma1 and spatial sigma = sigma2. + * If size1 = 0, the aperture square side is set to CvMat#round(sigma2 * 1.5) * 2 + 1. + * @param size1 [Integer] The first parameter of the smoothing operation, the aperture width. + * Must be a positive odd number (1, 3, 5, ...) + * @param size2 [Integer] The second parameter of the smoothing operation, the aperture height. + * Ignored by CV_MEDIAN and CV_BILATERAL methods. In the case of simple + * scaled/non-scaled and Gaussian blur if size2 is zero, it is set to size1. + * Otherwise it must be a positive odd number. + * @param sigma1 [Integer] In the case of a Gaussian parameter this parameter may specify + * Gaussian sigma (standard deviation). If it is zero, it is calculated from the kernel size. + * @return [CvMat] The destination image. + * @opencv_func cvSmooth + */ +VALUE +rb_smooth(int argc, VALUE *argv, VALUE self) +{ + VALUE smoothtype, p1, p2, p3, p4; + rb_scan_args(argc, argv, "14", &smoothtype, &p1, &p2, &p3, &p4); + int _smoothtype = CVMETHOD("SMOOTHING_TYPE", smoothtype, -1); + + VALUE (*smooth_func)(int c, VALUE* v, VALUE s); + argc--; + switch (_smoothtype) { + case CV_BLUR_NO_SCALE: + smooth_func = rb_smooth_blur_no_scale; + argc = (argc > 2) ? 2 : argc; + break; + case CV_BLUR: + smooth_func = rb_smooth_blur; + argc = (argc > 2) ? 2 : argc; + break; + case CV_GAUSSIAN: + smooth_func = rb_smooth_gaussian; + break; + case CV_MEDIAN: + smooth_func = rb_smooth_median; + argc = (argc > 1) ? 1 : argc; + break; + case CV_BILATERAL: + smooth_func = rb_smooth_bilateral; + argc = (argc > 2) ? 2 : argc; + break; + default: + smooth_func = rb_smooth_gaussian; + break; + } + VALUE result = Qnil; + try { + result = (*smooth_func)(argc, argv + 1, self); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return result; +} + +/* + * call-seq: + * filter2d(kernel[,anchor]) -> cvmat + * + * Convolves image with the kernel. + * Convolution kernel, single-channel floating point matrix (or same depth of self's). + * If you want to apply different kernels to different channels, + * split the image using CvMat#split into separate color planes and process them individually. + */ +VALUE +rb_filter2d(int argc, VALUE *argv, VALUE self) +{ + VALUE _kernel, _anchor; + rb_scan_args(argc, argv, "11", &_kernel, &_anchor); + CvMat* kernel = CVMAT_WITH_CHECK(_kernel); + CvArr* self_ptr = CVARR(self); + VALUE _dest = Qnil; + try { + _dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvFilter2D(self_ptr, CVARR(_dest), kernel, NIL_P(_anchor) ? cvPoint(-1,-1) : VALUE_TO_CVPOINT(_anchor)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return _dest; +} + +/* + * call-seq: + * copy_make_border(border_type, size, offset[,value = CvScalar.new(0)]) + * + * Copies image and makes border around it. + * border_type: + * - IPL_BORDER_CONSTANT, :constant + * border is filled with the fixed value, passed as last parameter of the function. + * - IPL_BORDER_REPLICATE, :replicate + * the pixels from the top and bottom rows, the left-most and right-most columns are replicated to fill the border + * size: The destination image size + * offset: Coordinates of the top-left corner (or bottom-left in the case of images with bottom-left origin) of the destination image rectangle. + * value: Value of the border pixels if bordertype is IPL_BORDER_CONSTANT or :constant. + */ +VALUE +rb_copy_make_border(int argc, VALUE *argv, VALUE self) +{ + VALUE border_type, size, offset, value, dest; + rb_scan_args(argc, argv, "31", &border_type, &size, &offset, &value); + dest = new_mat_kind_object(VALUE_TO_CVSIZE(size), self); + + int type = 0; + if (SYMBOL_P(border_type)) { + ID type_id = rb_to_id(border_type); + if (type_id == rb_intern("constant")) + type = IPL_BORDER_CONSTANT; + else if (type_id == rb_intern("replicate")) + type = IPL_BORDER_REPLICATE; + else + rb_raise(rb_eArgError, "Invalid border_type (should be :constant or :replicate)"); + } + else + type = NUM2INT(border_type); + + try { + cvCopyMakeBorder(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT(offset), type, + NIL_P(value) ? cvScalar(0) : VALUE_TO_CVSCALAR(value)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * call-seq: + * integral(need_sqsum = false, need_tilted_sum = false) -> [cvmat, cvmat or nil, cvmat or nil] + * + * Calculates integral images. + * If need_sqsum = true, calculate the integral image for squared pixel values. + * If need_tilted_sum = true, calculate the integral for the image rotated by 45 degrees. + * + * sum(X,Y)=sumxCV_THRESH_BINARY + * and CV_THRESH_BINARY_INV thresholding types. + * @param threshold_type [Integer] Thresholding type + * * CV_THRESH_BINARY + * * CV_THRESH_BINARY_INV + * * CV_THRESH_TRUNC + * * CV_THRESH_TOZERO + * * CV_THRESH_TOZERO_INV + * @return [CvMat] Output array of the same size and type as self. + * @overload threshold(threshold, max_value, threshold_type, use_otsu) + * @param threshold [Number] Threshold value. + * @param max_value [Number] Maximum value to use with the CV_THRESH_BINARY + * and CV_THRESH_BINARY_INV thresholding types. + * @param threshold_type [Integer] Thresholding type + * * CV_THRESH_BINARY + * * CV_THRESH_BINARY_INV + * * CV_THRESH_TRUNC + * * CV_THRESH_TOZERO + * * CV_THRESH_TOZERO_INV + * @param use_otsu [Boolean] Determines the optimal threshold value using the Otsu's algorithm + * @return [Array] Output array and Otsu's threshold. + * @opencv_func cvThreshold + * @example + * mat = CvMat.new(3, 3, CV_8U, 1) + * mat.set_data([1, 2, 3, 4, 5, 6, 7, 8, 9]) + * mat #=> [1, 2, 3, + * 4, 5, 6, + * 7, 8, 9] + * result = mat.threshold(4, 7, CV_THRESH_BINARY) + * result #=> [0, 0, 0, + * 0, 7, 7, + * 7, 7, 7] + */ +VALUE +rb_threshold(int argc, VALUE *argv, VALUE self) +{ + VALUE threshold, max_value, threshold_type, use_otsu; + rb_scan_args(argc, argv, "31", &threshold, &max_value, &threshold_type, &use_otsu); + const int INVALID_TYPE = -1; + int type = CVMETHOD("THRESHOLD_TYPE", threshold_type, INVALID_TYPE); + if (type == INVALID_TYPE) + rb_raise(rb_eArgError, "Invalid threshold type."); + + return rb_threshold_internal(type, threshold, max_value, use_otsu, self); +} + +/* + * Applies an adaptive threshold to an array. + * + * @overload adaptive_threshold(max_value, options) + * @param max_value [Number] Non-zero value assigned to the pixels for which the condition is satisfied. + * @param options [Hash] Threshold option + * @option options [Integer, Symbol] :threshold_type (CV_THRESH_BINARY) Thresholding type; + * must be one of CV_THRESH_BINARY or :binary, CV_THRESH_BINARY_INV or :binary_inv. + * @option options [Integer, Symbol] :adaptive_method (CV_ADAPTIVE_THRESH_MEAN_C) Adaptive thresholding algorithm to use: + * CV_ADAPTIVE_THRESH_MEAN_C or :mean_c, CV_ADAPTIVE_THRESH_GAUSSIAN_C or :gaussian_c. + * @option options [Integer] :block_size (3) The size of a pixel neighborhood that is used to calculate a threshold value + * for the pixel: 3, 5, 7, and so on. + * @option options :param1 [Number] (5) The method-dependent parameter. For the methods CV_ADAPTIVE_THRESH_MEAN_C + * and CV_ADAPTIVE_THRESH_GAUSSIAN_C it is a constant subtracted from the mean or weighted mean, though it may be negative + * @return [CvMat] Destination image of the same size and the same type as self. + * @opencv_func cvAdaptiveThreshold + * @example + * mat = CvMat.new(3, 3, CV_8U, 1) + * mat.set_data([1, 2, 3, 4, 5, 6, 7, 8, 9]) + * mat #=> [1, 2, 3, + * 4, 5, 6, + * 7, 8, 9] + * result = mat.adaptive_threshold(7, threshold_type: CV_THRESH_BINARY, + * adaptive_method: CV_ADAPTIVE_THRESH_MEAN_C, + * block_size: 3, param1: 1) + * result #=> [0, 0, 0, + * 7, 7, 7, + * 7, 7, 7] + */ +VALUE +rb_adaptive_threshold(int argc, VALUE *argv, VALUE self) +{ + VALUE max_value, options; + rb_scan_args(argc, argv, "11", &max_value, &options); + + int threshold_type = CV_THRESH_BINARY; + int adaptive_method = CV_ADAPTIVE_THRESH_MEAN_C; + int block_size = 3; + double param1 = 5; + if (!NIL_P(options)) { + Check_Type(options, T_HASH); + threshold_type = CVMETHOD("THRESHOLD_TYPE", LOOKUP_HASH(options, "threshold_type"), + CV_THRESH_BINARY); + adaptive_method = CVMETHOD("ADAPTIVE_METHOD", LOOKUP_HASH(options, "adaptive_method"), + CV_ADAPTIVE_THRESH_MEAN_C); + VALUE _block_size = LOOKUP_HASH(options, "block_size"); + if (!NIL_P(_block_size)) { + block_size = NUM2INT(_block_size); + } + VALUE _param1 = LOOKUP_HASH(options, "param1"); + if (!NIL_P(_param1)) { + param1 = NUM2INT(_param1); + } + } + CvArr* self_ptr = CVARR(self); + VALUE dst = new_mat_kind_object(cvGetSize(self_ptr), self); + try { + cvAdaptiveThreshold(self_ptr, CVARR(dst), NUM2DBL(max_value), adaptive_method, threshold_type, + block_size, param1); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dst; +} + +/* + * call-seq: + * pyr_down([filter = :gaussian_5x5]) -> cvmat + * + * Return downsamples image. + * + * This operation performs downsampling step of Gaussian pyramid decomposition. + * First it convolves source image with the specified filter and then downsamples the image + * by rejecting even rows and columns. + * + * note: filter - only :gaussian_5x5 is currently supported. + */ +VALUE +rb_pyr_down(int argc, VALUE *argv, VALUE self) +{ + int filter = CV_GAUSSIAN_5x5; + if (argc > 0) { + VALUE filter_type = argv[0]; + switch (TYPE(filter_type)) { + case T_SYMBOL: + // currently suport CV_GAUSSIAN_5x5 only. + break; + default: + raise_typeerror(filter_type, rb_cSymbol); + } + } + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + CvSize original_size = cvGetSize(self_ptr); + CvSize size = { original_size.width >> 1, original_size.height >> 1 }; + dest = new_mat_kind_object(size, self); + cvPyrDown(self_ptr, CVARR(dest), filter); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * call-seq: + * pyr_up([filter = :gaussian_5x5]) -> cvmat + * + * Return upsamples image. + * + * This operation performs up-sampling step of Gaussian pyramid decomposition. + * First it upsamples the source image by injecting even zero rows and columns and + * then convolves result with the specified filter multiplied by 4 for interpolation. + * So the destination image is four times larger than the source image. + * + * note: filter - only :gaussian_5x5 is currently supported. + */ +VALUE +rb_pyr_up(int argc, VALUE *argv, VALUE self) +{ + VALUE filter_type; + rb_scan_args(argc, argv, "01", &filter_type); + int filter = CV_GAUSSIAN_5x5; + if (argc > 0) { + switch (TYPE(filter_type)) { + case T_SYMBOL: + // currently suport CV_GAUSSIAN_5x5 only. + break; + default: + raise_typeerror(filter_type, rb_cSymbol); + } + } + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + CvSize original_size = cvGetSize(self_ptr); + CvSize size = { original_size.width << 1, original_size.height << 1 }; + dest = new_mat_kind_object(size, self); + cvPyrUp(self_ptr, CVARR(dest), filter); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Fills a connected component with the given color. + * + * @overload flood_fill(seed_point, new_val, lo_diff = CvScalar.new(0), up_diff = CvScalar.new(0), flood_fill_option = nil) + * @param seed_point [CvPoint] Starting point. + * @param new_val [CvScalar] New value of the repainted domain pixels. + * @param lo_diff [CvScalar] Maximal lower brightness/color difference between the currently observed pixel + * and one of its neighbor belong to the component or seed pixel to add the pixel to component. + * In case of 8-bit color images it is packed value. + * @param up_diff [CvScalar] Maximal upper brightness/color difference between the currently observed pixel and + * one of its neighbor belong to the component or seed pixel to add the pixel to component. + * In case of 8-bit color images it is packed value. + * @param flood_fill_option [Hash] + * @option flood_fill_option [Integer] :connectivity (4) + * Connectivity determines which neighbors of a pixel are considered (4 or 8). + * @option flood_fill_option [Boolean] :fixed_range (false) + * If set the difference between the current pixel and seed pixel is considered, otherwise difference between + * neighbor pixels is considered (the range is floating). + * @option flood_fill_option [Boolean] :mask_only (false) + * If set, the function does not fill the image(new_val is ignored), but the fills mask. + * @return [Array] Array of output image, connected component and mask. + * @opencv_func cvFloodFill + */ +VALUE +rb_flood_fill(int argc, VALUE *argv, VALUE self) +{ + return rb_flood_fill_bang(argc, argv, copy(self)); +} + +/* + * Fills a connected component with the given color. + * + * @overload flood_fill!(seed_point, new_val, lo_diff = CvScalar.new(0), up_diff = CvScalar.new(0), flood_fill_option = nil) + * @param (see #flood_fill) + * @return (see #flood_fill) + * @opencv_func (see #flood_fill) + */ +VALUE +rb_flood_fill_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE seed_point, new_val, lo_diff, up_diff, flood_fill_option; + rb_scan_args(argc, argv, "23", &seed_point, &new_val, &lo_diff, &up_diff, &flood_fill_option); + flood_fill_option = FLOOD_FILL_OPTION(flood_fill_option); + int flags = FF_CONNECTIVITY(flood_fill_option); + if (FF_FIXED_RANGE(flood_fill_option)) { + flags |= CV_FLOODFILL_FIXED_RANGE; + } + if (FF_MASK_ONLY(flood_fill_option)) { + flags |= CV_FLOODFILL_MASK_ONLY; + } + CvArr* self_ptr = CVARR(self); + VALUE comp = cCvConnectedComp::new_object(); + VALUE mask = Qnil; + try { + CvSize size = cvGetSize(self_ptr); + // TODO: Change argument format to set mask + mask = new_object(size.height + 2, size.width + 2, CV_MAKETYPE(CV_8U, 1)); + CvMat* mask_ptr = CVMAT(mask); + cvSetZero(mask_ptr); + cvFloodFill(self_ptr, + VALUE_TO_CVPOINT(seed_point), + VALUE_TO_CVSCALAR(new_val), + NIL_P(lo_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(lo_diff), + NIL_P(up_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(up_diff), + CVCONNECTEDCOMP(comp), + flags, + mask_ptr); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(3, self, comp, mask); +} + +/* + * Finds contours in binary image. + * + * @overload find_contours(find_contours_options) + * @param find_contours_options [Hash] Options + * @option find_contours_options [Symbol] :mode (:list) Retrieval mode. + * * :external - retrive only the extreme outer contours + * * :list - retrieve all the contours and puts them in the list. + * * :ccomp - retrieve all the contours and organizes them into two-level hierarchy: + * top level are external boundaries of the components, second level are bounda boundaries of the holes + * * :tree - retrieve all the contours and reconstructs the full hierarchy of nested contours + * Connectivity determines which neighbors of a pixel are considered. + * @option find_contours_options [Symbol] :method (:approx_simple) Approximation method. + * * :code - output contours in the Freeman chain code. All other methods output polygons (sequences of vertices). + * * :approx_none - translate all the points from the chain code into points; + * * :approx_simple - compress horizontal, vertical, and diagonal segments, that is, the function leaves only their ending points; + * * :approx_tc89_l1, :approx_tc89_kcos - apply one of the flavors of Teh-Chin chain approximation algorithm. + * @option find_contours_options [CvPoint] :offset (CvPoint.new(0, 0)) Offset, by which every contour point is shifted. + * @return [CvContour, CvChain] Detected contours. If :method is :code, + * returns as CvChain, otherwise CvContour. + * @opencv_func cvFindContours + */ +VALUE +rb_find_contours(int argc, VALUE *argv, VALUE self) +{ + return rb_find_contours_bang(argc, argv, copy(self)); +} + +/* + * Finds contours in binary image. + * + * @overload find_contours!(find_contours_options) + * @param (see #find_contours) + * @return (see #find_contours) + * @opencv_func (see #find_contours) + */ +VALUE +rb_find_contours_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE find_contours_option, klass, element_klass, storage; + rb_scan_args(argc, argv, "01", &find_contours_option); + CvSeq *contour = NULL; + find_contours_option = FIND_CONTOURS_OPTION(find_contours_option); + int mode = FC_MODE(find_contours_option); + int method = FC_METHOD(find_contours_option); + int header_size; + if (method == CV_CHAIN_CODE) { + klass = cCvChain::rb_class(); + element_klass = T_FIXNUM; + header_size = sizeof(CvChain); + } + else { + klass = cCvContour::rb_class(); + element_klass = cCvPoint::rb_class(); + header_size = sizeof(CvContour); + } + storage = cCvMemStorage::new_object(); + + int count = 0; + try { + count = cvFindContours(CVARR(self), CVMEMSTORAGE(storage), &contour, header_size, + mode, method, FC_OFFSET(find_contours_option)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + if (count == 0) + return Qnil; + else + return cCvSeq::new_sequence(klass, contour, element_klass, storage); +} + +/* + * call-seq: + * draw_contours(contour, external_color, hole_color, max_level, options) -> cvmat + * + * Draws contour outlines or interiors in an image. + * + * * contour (CvContour) - Pointer to the first contour + * * external_color (CvScalar) - Color of the external contours + * * hole_color (CvScalar) - Color of internal contours (holes) + * * max_level (Integer) - Maximal level for drawn contours. If 0, only contour is drawn. If 1, the contour and all contours following it on the same level are drawn. If 2, all contours following and all contours one level below the contours are drawn, and so forth. If the value is negative, the function does not draw the contours following after contour but draws the child contours of contour up to the |max_level| - 1 level. + * * options (Hash) - Drawing options. + * * :thickness (Integer) - Thickness of lines the contours are drawn with. If it is negative, the contour interiors are drawn (default: 1). + * * :line_type (Integer or Symbol) - Type of the contour segments, see CvMat#line description (default: 8). + */ +VALUE +rb_draw_contours(int argc, VALUE *argv, VALUE self) +{ + return rb_draw_contours_bang(argc, argv, copy(self)); +} + +/* + * call-seq: + * draw_contours!(contour, external_color, hole_color, max_level, options) -> cvmat + * + * Draws contour outlines or interiors in an image. + * + * see CvMat#draw_contours + */ +VALUE +rb_draw_contours_bang(int argc, VALUE *argv, VALUE self) +{ + VALUE contour, external_color, hole_color, max_level, options; + rb_scan_args(argc, argv, "41", &contour, &external_color, &hole_color, &max_level, &options); + options = DRAWING_OPTION(options); + try { + cvDrawContours(CVARR(self), CVSEQ_WITH_CHECK(contour), VALUE_TO_CVSCALAR(external_color), + VALUE_TO_CVSCALAR(hole_color), NUM2INT(max_level), + DO_THICKNESS(options), DO_LINE_TYPE(options)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return self; +} + +/* + * call-seq: + * draw_chessboard_corners(pattern_size, corners, pattern_was_found) -> nil + * + * Returns an image which is rendered the detected chessboard corners. + * + * pattern_size (CvSize) - Number of inner corners per a chessboard row and column. + * corners (Array) - Array of detected corners, the output of CvMat#find_chessboard_corners. + * pattern_was_found (Boolean)- Parameter indicating whether the complete board was found or not. + */ +VALUE +rb_draw_chessboard_corners(VALUE self, VALUE pattern_size, VALUE corners, VALUE pattern_was_found) +{ + return rb_draw_chessboard_corners_bang(copy(self), pattern_size, corners, pattern_was_found); +} + +/* + * call-seq: + * draw_chessboard_corners!(pattern_size, corners, pattern_was_found) -> self + * + * Renders the detected chessboard corners. + * + * pattern_size (CvSize) - Number of inner corners per a chessboard row and column. + * corners (Array) - Array of detected corners, the output of CvMat#find_chessboard_corners. + * pattern_was_found (Boolean)- Parameter indicating whether the complete board was found or not. + */ +VALUE +rb_draw_chessboard_corners_bang(VALUE self, VALUE pattern_size, VALUE corners, VALUE pattern_was_found) +{ + Check_Type(corners, T_ARRAY); + int count = RARRAY_LEN(corners); + CvPoint2D32f* corners_buff = ALLOCA_N(CvPoint2D32f, count); + VALUE* corners_ptr = RARRAY_PTR(corners); + for (int i = 0; i < count; i++) { + corners_buff[i] = *(CVPOINT2D32F(corners_ptr[i])); + } + + try { + int found = (pattern_was_found == Qtrue); + cvDrawChessboardCorners(CVARR(self), VALUE_TO_CVSIZE(pattern_size), corners_buff, count, found); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return self; +} + +/* + * call-seq: + * pyr_mean_shift_filtering(sp, sr[,max_level = 1][termcrit = CvTermCriteria.new(5,1)]) -> cvmat + * + * Does meanshift image segmentation. + * + * sp - The spatial window radius. + * sr - The color window radius. + * max_level - Maximum level of the pyramid for the segmentation. + * termcrit - Termination criteria: when to stop meanshift iterations. + * + * This method is implements the filtering stage of meanshift segmentation, + * that is, the output of the function is the filtered "posterized" image with color gradients and fine-grain texture flattened. + * At every pixel (X,Y) of the input image (or down-sized input image, see below) + * the function executes meanshift iterations, that is, the pixel (X,Y) neighborhood in the joint space-color hyperspace is considered: + * {(x,y): X-sp≤x≤X+sp && Y-sp≤y≤Y+sp && ||(R,G,B)-(r,g,b)|| ≤ sr}, + * where (R,G,B) and (r,g,b) are the vectors of color components at (X,Y) and (x,y), + * respectively (though, the algorithm does not depend on the color space used, + * so any 3-component color space can be used instead). + * Over the neighborhood the average spatial value (X',Y') + * and average color vector (R',G',B') are found and they act as the neighborhood center on the next iteration: + * (X,Y)~(X',Y'), (R,G,B)~(R',G',B'). + * After the iterations over, the color components of the initial pixel (that is, the pixel from where the iterations started) + * are set to the final value (average color at the last iteration): + * I(X,Y) <- (R*,G*,B*). + * Then max_level > 0, the gaussian pyramid of max_level+1 levels is built, + * and the above procedure is run on the smallest layer. + * After that, the results are propagated to the larger layer and the iterations are run again + * only on those pixels where the layer colors differ much (>sr) from the lower-resolution layer, + * that is, the boundaries of the color regions are clarified. + * + * Note, that the results will be actually different from the ones obtained by running the meanshift procedure on the whole original image (i.e. when max_level==0). + */ +VALUE +rb_pyr_mean_shift_filtering(int argc, VALUE *argv, VALUE self) +{ + VALUE spatial_window_radius, color_window_radius, max_level, termcrit; + rb_scan_args(argc, argv, "22", &spatial_window_radius, &color_window_radius, &max_level, &termcrit); + CvArr* self_ptr = CVARR(self); + VALUE dest = Qnil; + try { + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvPyrMeanShiftFiltering(self_ptr, CVARR(dest), + NUM2DBL(spatial_window_radius), + NUM2DBL(color_window_radius), + IF_INT(max_level, 1), + NIL_P(termcrit) ? cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 5, 1) + : VALUE_TO_CVTERMCRITERIA(termcrit)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * Performs a marker-based image segmentation using the watershed algorithm. + * + * @overload watershed(markers) + * @param markers [CvMat] Input 32-bit single-channel image of markers. It should have the same size as self + * @return [CvMat] Output image + * @opencv_func cvWatershed + */ +VALUE +rb_watershed(VALUE self, VALUE markers) +{ + try { + cvWatershed(CVARR(self), CVARR_WITH_CHECK(markers)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return markers; +} + +/* + * call-seq: + * moments -> cvmoments + * + * Calculates moments. + */ +VALUE +rb_moments(int argc, VALUE *argv, VALUE self) +{ + VALUE is_binary; + rb_scan_args(argc, argv, "01", &is_binary); + CvArr *self_ptr = CVARR(self); + VALUE moments = Qnil; + try { + moments = cCvMoments::new_object(self_ptr, TRUE_OR_FALSE(is_binary, 0)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return moments; +} + +/* + * Finds lines in binary image using a Hough transform. + * + * @overload hough_lines(method, rho, theta, threshold, param1, param2) + * @param method [Integer] The Hough transform variant, one of the following: + * * CV_HOUGH_STANDARD - classical or standard Hough transform. + * * CV_HOUGH_PROBABILISTIC - probabilistic Hough transform (more efficient in case if picture contains a few long linear segments). + * * CV_HOUGH_MULTI_SCALE - multi-scale variant of the classical Hough transform. The lines are encoded the same way as CV_HOUGH_STANDARD. + * @param rho [Number] Distance resolution in pixel-related units. + * @param theta [Number] Angle resolution measured in radians. + * @param threshold [Number] Threshold parameter. A line is returned by the function if the corresponding + * accumulator value is greater than threshold. + * @param param1 [Number] The first method-dependent parameter: + * * For the classical Hough transform it is not used (0). + * * For the probabilistic Hough transform it is the minimum line length. + * * For the multi-scale Hough transform it is the divisor for the distance resolution. + * (The coarse distance resolution will be rho and the accurate resolution will be (rho / param1)). + * @param param2 [Number] The second method-dependent parameter: + * * For the classical Hough transform it is not used (0). + * * For the probabilistic Hough transform it is the maximum gap between line segments lying + * on the same line to treat them as a single line segment (i.e. to join them). + * * For the multi-scale Hough transform it is the divisor for the angle resolution. + * (The coarse angle resolution will be theta and the accurate resolution will be (theta / param2).) + * @return [CvSeq] Output lines. If method is CV_HOUGH_STANDARD or CV_HOUGH_MULTI_SCALE, + * the class of elements is CvLine, otherwise CvTwoPoints. + * @opencv_func cvHoughLines2 + */ +VALUE +rb_hough_lines(int argc, VALUE *argv, VALUE self) +{ + const int INVALID_TYPE = -1; + VALUE method, rho, theta, threshold, p1, p2; + rb_scan_args(argc, argv, "42", &method, &rho, &theta, &threshold, &p1, &p2); + int method_flag = CVMETHOD("HOUGH_TRANSFORM_METHOD", method, INVALID_TYPE); + if (method_flag == INVALID_TYPE) + rb_raise(rb_eArgError, "Invalid method: %d", method_flag); + VALUE storage = cCvMemStorage::new_object(); + CvSeq *seq = NULL; + try { + seq = cvHoughLines2(CVARR(copy(self)), CVMEMSTORAGE(storage), + method_flag, NUM2DBL(rho), NUM2DBL(theta), NUM2INT(threshold), + IF_DBL(p1, 0), IF_DBL(p2, 0)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + switch (method_flag) { + case CV_HOUGH_STANDARD: + case CV_HOUGH_MULTI_SCALE: + return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvLine::rb_class(), storage); + break; + case CV_HOUGH_PROBABILISTIC: + return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvTwoPoints::rb_class(), storage); + break; + default: + break; + } + + return Qnil; +} + +/* + * Finds circles in a grayscale image using the Hough transform. + * + * @overload hough_circles(method, dp, min_dist, param1, param2, min_radius = 0, max_radius = 0) + * @param method [Integer] Detection method to use. Currently, the only implemented method is CV_HOUGH_GRADIENT. + * @param dp [Number] Inverse ratio of the accumulator resolution to the image resolution. + * For example, if dp=1, the accumulator has the same resolution as the input image. + * If dp=2, the accumulator has half as big width and height. + * @param min_dist [Number] Minimum distance between the centers of the detected circles. + * If the parameter is too small, multiple neighbor circles may be falsely detected + * in addition to a true one. If it is too large, some circles may be missed. + * @param param1 [Number] First method-specific parameter. In case of CV_HOUGH_GRADIENT, + * it is the higher threshold of the two passed to the #canny detector (the lower one is twice smaller). + * @param param2 [Number] Second method-specific parameter. In case of CV_HOUGH_GRADIENT, + * it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, + * the more false circles may be detected. Circles, corresponding to the larger accumulator values, + * will be returned first. + * @return [CvSeq] Output circles. + * @opencv_func cvHoughCircles + */ +VALUE +rb_hough_circles(int argc, VALUE *argv, VALUE self) +{ + const int INVALID_TYPE = -1; + VALUE method, dp, min_dist, param1, param2, min_radius, max_radius, storage; + rb_scan_args(argc, argv, "52", &method, &dp, &min_dist, ¶m1, ¶m2, + &min_radius, &max_radius); + storage = cCvMemStorage::new_object(); + int method_flag = CVMETHOD("HOUGH_TRANSFORM_METHOD", method, INVALID_TYPE); + if (method_flag == INVALID_TYPE) + rb_raise(rb_eArgError, "Invalid method: %d", method_flag); + CvSeq *seq = NULL; + try { + seq = cvHoughCircles(CVARR(self), CVMEMSTORAGE(storage), + method_flag, NUM2DBL(dp), NUM2DBL(min_dist), + NUM2DBL(param1), NUM2DBL(param2), + IF_INT(min_radius, 0), IF_INT(max_radius, 0)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvCircle32f::rb_class(), storage); +} + +/* + * call-seq: + * inpaint(inpaint_method, mask, radius) -> cvmat + * + * Inpaints the selected region in the image + * The radius of circlular neighborhood of each point inpainted that is considered by the algorithm. + */ +VALUE +rb_inpaint(VALUE self, VALUE inpaint_method, VALUE mask, VALUE radius) +{ + const int INVALID_TYPE = -1; + VALUE dest = Qnil; + int method = CVMETHOD("INPAINT_METHOD", inpaint_method, INVALID_TYPE); + if (method == INVALID_TYPE) + rb_raise(rb_eArgError, "Invalid method"); + try { + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvInpaint(self_ptr, MASK(mask), CVARR(dest), NUM2DBL(radius), method); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * call-seq: + * equalize_hist - cvmat + * + * Equalize histgram of grayscale of image. + * + * equalizes histogram of the input image using the following algorithm: + * 1. calculate histogram H for src. + * 2. normalize histogram, so that the sum of histogram bins is 255. + * 3. compute integral of the histogram: + * H’(i) = sum0≤j≤iH(j) + * 4. transform the image using H’ as a look-up table: dst(x,y)=H’(src(x,y)) + * The algorithm normalizes brightness and increases contrast of the image. + * + * support single-channel 8bit image (grayscale) only. + */ +VALUE +rb_equalize_hist(VALUE self) +{ + VALUE dest = Qnil; + try { + CvArr* self_ptr = CVARR(self); + dest = new_mat_kind_object(cvGetSize(self_ptr), self); + cvEqualizeHist(self_ptr, CVARR(dest)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return dest; +} + +/* + * call-seq: + * apply_color_map(colormap) -> cvmat + * + * Applies a GNU Octave/MATLAB equivalent colormap on a given image. + * + * Parameters: + * colormap - The colormap to apply. + */ +VALUE +rb_apply_color_map(VALUE self, VALUE colormap) +{ + VALUE dst; + try { + cv::Mat dst_mat; + cv::Mat self_mat(CVMAT(self)); + + cv::applyColorMap(self_mat, dst_mat, NUM2INT(colormap)); + CvMat tmp = dst_mat; + dst = new_object(tmp.rows, tmp.cols, tmp.type); + cvCopy(&tmp, CVMAT(dst)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return dst; +} + +/* + * Compares template against overlapped image regions. + * + * @overload match_template(template, method = CV_TM_SQDIFF) + * @param template [CvMat] Searched template. It must be not greater than the source image and have the same data type. + * @param method [Integer] Parameter specifying the comparison method. + * * CV_TM_SQDIFF + * * CV_TM_SQDIFF_NORMED + * * CV_TM_CCORR + * * CV_TM_CCORR_NORMED + * * CV_TM_CCOEFF + * * CV_TM_CCOEFF_NORMED + * @opencv_func cvMatchTemplate + * + * After the match_template finishes comparison, the best matches can be found as global + * minimums (CV_TM_SQDIFF) or maximums(CV_TM_CCORR or CV_TM_CCOEFF) using CvMat#min_max_loc. + * In case of color image and template summation in both numerator and each sum in denominator + * is done over all the channels (and separate mean values are used for each channel). + */ +VALUE +rb_match_template(int argc, VALUE *argv, VALUE self) +{ + VALUE templ, method; + int method_flag; + if (rb_scan_args(argc, argv, "11", &templ, &method) == 1) + method_flag = CV_TM_SQDIFF; + else + method_flag = CVMETHOD("MATCH_TEMPLATE_METHOD", method); + + CvArr* self_ptr = CVARR(self); + CvArr* templ_ptr = CVARR_WITH_CHECK(templ); + VALUE result = Qnil; + try { + CvSize src_size = cvGetSize(self_ptr); + CvSize template_size = cvGetSize(templ_ptr); + result = cCvMat::new_object(src_size.height - template_size.height + 1, + src_size.width - template_size.width + 1, + CV_32FC1); + cvMatchTemplate(self_ptr, templ_ptr, CVARR(result), method_flag); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return result; +} + +/* + * call-seq: + * match_shapes(object, method) -> float + * + * Compares two shapes(self and object). object should be CvMat or CvContour. + * + * A - object1, B - object2: + * * method=CV_CONTOURS_MATCH_I1 + * I1(A,B)=sumi=1..7abs(1/mAi - 1/mBi) + * * method=CV_CONTOURS_MATCH_I2 + * I2(A,B)=sumi=1..7abs(mAi - mBi) + * * method=CV_CONTOURS_MATCH_I3 + * I3(A,B)=sumi=1..7abs(mAi - mBi)/abs(mAi) + */ +VALUE +rb_match_shapes(int argc, VALUE *argv, VALUE self) +{ + VALUE object, method, param; + rb_scan_args(argc, argv, "21", &object, &method, ¶m); + int method_flag = CVMETHOD("COMPARISON_METHOD", method); + if (!(rb_obj_is_kind_of(object, cCvMat::rb_class()) || rb_obj_is_kind_of(object, cCvContour::rb_class()))) + rb_raise(rb_eTypeError, "argument 1 (shape) should be %s or %s", + rb_class2name(cCvMat::rb_class()), rb_class2name(cCvContour::rb_class())); + double result = 0; + try { + result = cvMatchShapes(CVARR(self), CVARR(object), method_flag); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_float_new(result); +} + +/* + * call-seq: + * mean_shift(window, criteria) -> comp + * + * Implements CAMSHIFT object tracking algrorithm. + * First, it finds an object center using mean_shift and, after that, + * calculates the object size and orientation. + */ +VALUE +rb_mean_shift(VALUE self, VALUE window, VALUE criteria) +{ + VALUE comp = cCvConnectedComp::new_object(); + try { + cvMeanShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), CVCONNECTEDCOMP(comp)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return comp; +} + +/* + * call-seq: + * cam_shift(window, criteria) -> [comp, box] + * + * Implements CAMSHIFT object tracking algrorithm. First, it finds an object center using cvMeanShift and, + * after that, calculates the object size and orientation. The function returns number of iterations made + * within cvMeanShift. + */ +VALUE +rb_cam_shift(VALUE self, VALUE window, VALUE criteria) +{ + VALUE comp = cCvConnectedComp::new_object(); + VALUE box = cCvBox2D::new_object(); + try { + cvCamShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), + CVCONNECTEDCOMP(comp), CVBOX2D(box)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, comp, box); +} + +/* + * 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) +{ + 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; +} + +/* + * call-seq: + * optical_flow_hs(prev[,velx = nil][,vely = nil][,options]) -> [cvmat, cvmat] + * + * Calculates optical flow for two images (previous -> self) using Horn & Schunck algorithm. + * Return horizontal component of the optical flow and vertical component of the optical flow. + * prev is previous image + * velx is previous velocity field of x-axis, and vely is previous velocity field of y-axis. + * + * options + * * :lambda -> should be Float (default is 0.0005) + * Lagrangian multiplier. + * * :criteria -> should be CvTermCriteria object (default is CvTermCriteria(1, 0.001)) + * Criteria of termination of velocity computing. + * note: option's default value is CvMat::OPTICAL_FLOW_HS_OPTION. + * + * sample code + * velx, vely = nil, nil + * while true + * current = capture.query + * velx, vely = current.optical_flow_hs(prev, velx, vely) if prev + * prev = current + * end + */ +VALUE +rb_optical_flow_hs(int argc, VALUE *argv, VALUE self) +{ + VALUE prev, velx, vely, options; + int use_previous = 0; + rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options); + options = OPTICAL_FLOW_HS_OPTION(options); + CvMat *velx_ptr, *vely_ptr; + CvArr* self_ptr = CVARR(self); + try { + if (NIL_P(velx) && NIL_P(vely)) { + CvSize size = cvGetSize(self_ptr); + int type = CV_MAKETYPE(CV_32F, 1); + velx = cCvMat::new_object(size, type); + vely = cCvMat::new_object(size, type); + velx_ptr = CVMAT(velx); + vely_ptr = CVMAT(vely); + } + else { + use_previous = 1; + velx_ptr = CVMAT_WITH_CHECK(velx); + vely_ptr = CVMAT_WITH_CHECK(vely); + } + cvCalcOpticalFlowHS(CVMAT_WITH_CHECK(prev), self_ptr, use_previous, velx_ptr, vely_ptr, + HS_LAMBDA(options), HS_CRITERIA(options)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, velx, vely); +} + +/* + * call-seq: + * optical_flow_lk(prev, win_size) -> [cvmat, cvmat] + * + * Calculates optical flow for two images (previous -> self) using Lucas & Kanade algorithm + * Return horizontal component of the optical flow and vertical component of the optical flow. + * + * win_size is size of the averaging window used for grouping pixels. + */ +VALUE +rb_optical_flow_lk(VALUE self, VALUE prev, VALUE win_size) +{ + VALUE velx = Qnil; + VALUE vely = Qnil; + try { + CvArr* self_ptr = CVARR(self); + CvSize size = cvGetSize(self_ptr); + int type = CV_MAKETYPE(CV_32F, 1); + velx = cCvMat::new_object(size, type); + vely = cCvMat::new_object(size, type); + cvCalcOpticalFlowLK(CVMAT_WITH_CHECK(prev), self_ptr, VALUE_TO_CVSIZE(win_size), + CVARR(velx), CVARR(vely)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, velx, vely); +} + +/* + * call-seq: + * optical_flow_bm(prev[,velx = nil][,vely = nil][,option]) -> [cvmat, cvmat] + * + * Calculates optical flow for two images (previous -> self) using block matching method. + * Return horizontal component of the optical flow and vertical component of the optical flow. + * prev is previous image. + * velx is previous velocity field of x-axis, and vely is previous velocity field of y-axis. + * + * options + * * :block_size -> should be CvSize (default is CvSize(4,4)) + * Size of basic blocks that are compared. + * * :shift_size -> should be CvSize (default is CvSize(1,1)) + * Block coordinate increments. + * * :max_range -> should be CvSize (default is CVSize(4,4)) + * Size of the scanned neighborhood in pixels around block. + * note: option's default value is CvMat::OPTICAL_FLOW_BM_OPTION. + * + * Velocity is computed for every block, but not for every pixel, + * so velocity image pixels correspond to input image blocks. + * input/output velocity field's size should be (self.width / block_size.width)x(self.height / block_size.height). + * e.g. image.size is 320x240 and block_size is 4x4, velocity field's size is 80x60. + * + */ +VALUE +rb_optical_flow_bm(int argc, VALUE *argv, VALUE self) +{ + VALUE prev, velx, vely, options; + rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options); + options = OPTICAL_FLOW_BM_OPTION(options); + CvArr* self_ptr = CVARR(self); + CvSize block_size = BM_BLOCK_SIZE(options); + CvSize shift_size = BM_SHIFT_SIZE(options); + CvSize max_range = BM_MAX_RANGE(options); + + int use_previous = 0; + try { + CvSize image_size = cvGetSize(self_ptr); + CvSize velocity_size = cvSize((image_size.width - block_size.width + shift_size.width) / shift_size.width, + (image_size.height - block_size.height + shift_size.height) / shift_size.height); + CvMat *velx_ptr, *vely_ptr; + if (NIL_P(velx) && NIL_P(vely)) { + int type = CV_MAKETYPE(CV_32F, 1); + velx = cCvMat::new_object(velocity_size, type); + vely = cCvMat::new_object(velocity_size, type); + velx_ptr = CVMAT(velx); + vely_ptr = CVMAT(vely); + } + else { + use_previous = 1; + velx_ptr = CVMAT_WITH_CHECK(velx); + vely_ptr = CVMAT_WITH_CHECK(vely); + } + cvCalcOpticalFlowBM(CVMAT_WITH_CHECK(prev), self_ptr, + block_size, shift_size, max_range, use_previous, + velx_ptr, vely_ptr); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return rb_ary_new3(2, velx, vely); +} + +/* + * call-seq: + * CvMat.find_fundamental_mat(points1, points2[,options = {}]) -> fundamental_matrix(cvmat) or nil + * + * Calculates fundamental matrix from corresponding points. + * Size of the output fundamental matrix is 3x3 or 9x3 (7-point method may return up to 3 matrices) + * + * points1 and points2 should be 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 multi-channel matrix. + * method is method for computing the fundamental matrix + * - CV_FM_7POINT for a 7-point algorithm. (N = 7) + * - CV_FM_8POINT for an 8-point algorithm. (N >= 8) + * - CV_FM_RANSAC for the RANSAC algorithm. (N >= 8) + * - CV_FM_LMEDS for the LMedS algorithm. (N >= 8) + * option should be Hash include these keys. + * :with_status (true or false) + * If set true, return fundamental_matrix and status. [fundamental_matrix, status] + * Otherwise return fundamental matrix only(default). + * :maximum_distance + * The parameter is used for RANSAC. It is the maximum distance from point to epipolar line in pixels, beyond which the point is considered an outlier and is not used for computing the final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the point localization, image resolution and the image noise. + * :desirable_level + * The optional output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in RANSAC and LMedS methods. For other methods it is set to all 1's. + * + * note: option's default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION. + */ +VALUE +rb_find_fundamental_mat(int argc, VALUE *argv, VALUE klass) +{ + VALUE points1, points2, method, option, fundamental_matrix, status; + int num = 0; + rb_scan_args(argc, argv, "31", &points1, &points2, &method, &option); + option = FIND_FUNDAMENTAL_MAT_OPTION(option); + int fm_method = FIX2INT(method); + CvMat *points1_ptr = CVMAT_WITH_CHECK(points1); + if (fm_method == CV_FM_7POINT) + fundamental_matrix = cCvMat::new_object(9, 3, CV_MAT_DEPTH(points1_ptr->type)); + else + fundamental_matrix = cCvMat::new_object(3, 3, CV_MAT_DEPTH(points1_ptr->type)); + + if (FFM_WITH_STATUS(option)) { + int status_len = (points1_ptr->rows > points1_ptr->cols) ? points1_ptr->rows : points1_ptr->cols; + status = cCvMat::new_object(1, status_len, CV_8UC1); + try { + num = cvFindFundamentalMat(points1_ptr, CVMAT_WITH_CHECK(points2), CVMAT(fundamental_matrix), fm_method, + FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), CVMAT(status)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status); + } + else { + try { + num = cvFindFundamentalMat(points1_ptr, CVMAT_WITH_CHECK(points2), CVMAT(fundamental_matrix), fm_method, + FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return num == 0 ? Qnil : fundamental_matrix; + } +} + + +/* + * call-seq: + * CvMat.compute_correspond_epilines(points, which_image, fundamental_matrix) -> correspondent_lines(cvmat) + * + * For points in one image of stereo pair computes the corresponding epilines in the other image. + * Finds equation of a line that contains the corresponding point (i.e. projection of the same 3D point) + * in the other image. Each line is encoded by a vector of 3 elements l=[a,b,c]T, so that: + * lT*[x, y, 1]T=0, + * or + * a*x + b*y + c = 0 + * From the fundamental matrix definition (see cvFindFundamentalMatrix discussion), line l2 for a point p1 + * in the first image (which_image=1) can be computed as: + * l2=F*p1 + * and the line l1 for a point p2 in the second image (which_image=1) can be computed as: + * l1=FT*p2 + * Line coefficients are defined up to a scale. They are normalized (a2+b2=1) are stored into correspondent_lines. + */ +VALUE +rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_image, VALUE fundamental_matrix) +{ + VALUE correspondent_lines; + CvMat* points_ptr = CVMAT_WITH_CHECK(points); + int n; + if (points_ptr->cols <= 3 && points_ptr->rows >= 7) + n = points_ptr->rows; + else if (points_ptr->rows <= 3 && points_ptr->cols >= 7) + n = points_ptr->cols; + else + rb_raise(rb_eArgError, "input points should 2xN, Nx2 or 3xN, Nx3 matrix(N >= 7)."); + + correspondent_lines = cCvMat::new_object(n, 3, CV_MAT_DEPTH(points_ptr->type)); + try { + cvComputeCorrespondEpilines(points_ptr, NUM2INT(which_image), CVMAT_WITH_CHECK(fundamental_matrix), + CVMAT(correspondent_lines)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + return correspondent_lines; +} + +/* + * Extracts Speeded Up Robust Features from an image + * + * @overload extract_surf(params, mask = nil) -> [cvseq(cvsurfpoint), array(float)] + * @param params [CvSURFParams] Various algorithm parameters put to the structure CvSURFParams. + * @param mask [CvMat] The optional input 8-bit mask. The features are only found + * in the areas that contain more than 50% of non-zero mask pixels. + * @return [Array, Array>] Output vector of keypoints and descriptors. + * @opencv_func cvExtractSURF + */ +VALUE +rb_extract_surf(int argc, VALUE *argv, VALUE self) +{ + VALUE _params, _mask; + rb_scan_args(argc, argv, "11", &_params, &_mask); + + // Prepare arguments + CvSURFParams params = *CVSURFPARAMS_WITH_CHECK(_params); + CvMat* mask = MASK(_mask); + VALUE storage = cCvMemStorage::new_object(); + CvSeq* keypoints = NULL; + CvSeq* descriptors = NULL; + + // Compute SURF keypoints and descriptors + try { + cvExtractSURF(CVARR(self), mask, &keypoints, &descriptors, CVMEMSTORAGE(storage), + params, 0); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + VALUE _keypoints = cCvSeq::new_sequence(cCvSeq::rb_class(), keypoints, cCvSURFPoint::rb_class(), storage); + + // Create descriptor array + const int DIM_SIZE = (params.extended) ? 128 : 64; + const int NUM_KEYPOINTS = keypoints->total; + VALUE _descriptors = rb_ary_new2(NUM_KEYPOINTS); + for (int m = 0; m < NUM_KEYPOINTS; ++m) { + VALUE elem = rb_ary_new2(DIM_SIZE); + float *descriptor = (float*)cvGetSeqElem(descriptors, m); + for (int n = 0; n < DIM_SIZE; ++n) { + rb_ary_store(elem, n, rb_float_new(descriptor[n])); + } + rb_ary_store(_descriptors, m, elem); + } + + return rb_assoc_new(_keypoints, _descriptors); +} + + +/* + * call-seq: + * subspace_project(w, mean) -> cvmat + */ +VALUE +rb_subspace_project(VALUE self, VALUE w, VALUE mean) +{ + VALUE projection; + try { + cv::Mat w_mat(CVMAT_WITH_CHECK(w)); + cv::Mat mean_mat(CVMAT_WITH_CHECK(mean)); + cv::Mat self_mat(CVMAT(self)); + cv::Mat pmat = cv::subspaceProject(w_mat, mean_mat, self_mat); + projection = new_object(pmat.rows, pmat.cols, pmat.type()); + CvMat tmp = pmat; + cvCopy(&tmp, CVMAT(projection)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return projection; +} + +/* + * call-seq: + * subspace_reconstruct(w, mean) -> cvmat + */ +VALUE +rb_subspace_reconstruct(VALUE self, VALUE w, VALUE mean) +{ + VALUE result; + try { + cv::Mat w_mat(CVMAT_WITH_CHECK(w)); + cv::Mat mean_mat(CVMAT_WITH_CHECK(mean)); + cv::Mat self_mat(CVMAT(self)); + cv::Mat rmat = cv::subspaceReconstruct(w_mat, mean_mat, self_mat); + result = new_object(rmat.rows, rmat.cols, rmat.type()); + CvMat tmp = rmat; + cvCopy(&tmp, CVMAT(result)); + } + catch (cv::Exception& e) { + raise_cverror(e); + } + + return result; +} + +VALUE +new_object(int rows, int cols, int type) +{ + return OPENCV_OBJECT(rb_klass, rb_cvCreateMat(rows, cols, type)); +} + +VALUE +new_object(CvSize size, int type) +{ + return OPENCV_OBJECT(rb_klass, rb_cvCreateMat(size.height, size.width, type)); +} + +VALUE +new_mat_kind_object(CvSize size, VALUE ref_obj) +{ + VALUE return_type = CLASS_OF(ref_obj); + if (rb_obj_is_kind_of(ref_obj, cIplImage::rb_class())) { + IplImage* img = IPLIMAGE(ref_obj); + return OPENCV_OBJECT(return_type, rb_cvCreateImage(size, img->depth, img->nChannels)); + } + else if (rb_obj_is_kind_of(ref_obj, rb_klass)) // CvMat + return OPENCV_OBJECT(return_type, rb_cvCreateMat(size.height, size.width, cvGetElemType(CVMAT(ref_obj)))); + else + rb_raise(rb_eNotImpError, "Only CvMat or IplImage are supported"); + + return Qnil; +} + +VALUE +new_mat_kind_object(CvSize size, VALUE ref_obj, int cvmat_depth, int channel) +{ + VALUE return_type = CLASS_OF(ref_obj); + if (rb_obj_is_kind_of(ref_obj, cIplImage::rb_class())) { + return OPENCV_OBJECT(return_type, rb_cvCreateImage(size, CV2IPL_DEPTH(cvmat_depth), channel)); + } + else if (rb_obj_is_kind_of(ref_obj, rb_klass)) // CvMat + return OPENCV_OBJECT(return_type, rb_cvCreateMat(size.height, size.width, + CV_MAKETYPE(cvmat_depth, channel))); + else + rb_raise(rb_eNotImpError, "Only CvMat or IplImage are supported"); + + return Qnil; +} + +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + if (rb_klass) return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ VALUE opencv = rb_module_opencv(); rb_klass = rb_define_class_under(opencv, "CvMat", rb_cObject); @@ -354,7 +5967,7 @@ void define_ruby_class() rb_define_singleton_method(rb_klass, "rotation_matrix2D", RUBY_METHOD_FUNC(rb_rotation_matrix2D), 3); rb_define_singleton_method(rb_klass, "get_perspective_transform", RUBY_METHOD_FUNC(rb_get_perspective_transform), 2); 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_singleton_method(rb_klass, "find_homography", RUBY_METHOD_FUNC(rb_find_homography), -1); rb_define_method(rb_klass, "remap", RUBY_METHOD_FUNC(rb_remap), -1); rb_define_method(rb_klass, "log_polar", RUBY_METHOD_FUNC(rb_log_polar), -1); @@ -396,7 +6009,6 @@ void define_ruby_class() rb_define_method(rb_klass, "apply_color_map", RUBY_METHOD_FUNC(rb_apply_color_map), 1); rb_define_method(rb_klass, "match_template", RUBY_METHOD_FUNC(rb_match_template), -1); rb_define_method(rb_klass, "match_shapes", RUBY_METHOD_FUNC(rb_match_shapes), -1); - rb_define_method(rb_klass, "match_descriptors", RUBY_METHOD_FUNC(rb_match_descriptors), -1); 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); @@ -425,5553 +6037,6 @@ void define_ruby_class() rb_define_alias(rb_singleton_class(rb_klass), "decode", "decode_image"); } - -VALUE -rb_allocate(VALUE klass) -{ - return OPENCV_OBJECT(klass, 0); -} - -/* - * call-seq: - * CvMat.new(row, col[, depth = CV_8U][, channel = 3]) -> cvmat - * - * Create col * row matrix. Each element set 0. - * - * Each element possigle range is set by depth. Default is unsigned 8bit. - * - * Number of channel is set by channel. channel should be 1..4. - * - */ -VALUE -rb_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE row, column, depth, channel; - rb_scan_args(argc, argv, "22", &row, &column, &depth, &channel); - - int ch = (argc < 4) ? 3 : NUM2INT(channel); - CvMat *ptr = rb_cvCreateMat(NUM2INT(row), NUM2INT(column), - CV_MAKETYPE(CVMETHOD("DEPTH", depth, CV_8U), ch)); - free(DATA_PTR(self)); - DATA_PTR(self) = ptr; - - return self; -} - -/* - * call-seq: - * CvMat::load(filename[,iscolor = CV_LOAD_IMAGE_COLOR]) - * - * Load an image from file. - * iscolor = CV_LOAD_IMAGE_COLOR, the loaded image is forced to be a 3-channel color image - * iscolor = CV_LOAD_IMAGE_GRAYSCALE, the loaded image is forced to be grayscale - * iscolor = CV_LOAD_IMAGE_UNCHANGED, the loaded image will be loaded as is. - * Currently the following file format are supported. - * * Windows bitmaps - BMP,DIB - * * JPEG files - JPEG,JPG,JPE - * * Portable Network Graphics - PNG - * * Portable image format - PBM,PGM,PPM - * * Sun rasters - SR,RAS - * * TIFF files - TIFF,TIF - */ -VALUE -rb_load_imageM(int argc, VALUE *argv, VALUE self) -{ - VALUE filename, iscolor; - rb_scan_args(argc, argv, "11", &filename, &iscolor); - Check_Type(filename, T_STRING); - - int _iscolor; - if (NIL_P(iscolor)) { - _iscolor = CV_LOAD_IMAGE_COLOR; - } - else { - Check_Type(iscolor, T_FIXNUM); - _iscolor = FIX2INT(iscolor); - } - - CvMat *mat = NULL; - try { - mat = cvLoadImageM(StringValueCStr(filename), _iscolor); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - if (mat == NULL) { - rb_raise(rb_eStandardError, "file does not exist or invalid format image."); - } - return OPENCV_OBJECT(rb_klass, mat); -} - -/* - * call-seq: - * encode_image(ext [,params]) -> Array - * - * Encodes an image into a memory buffer. - * - * Parameters: - * ext - File extension that defines the output format ('.jpg', '.png', ...) - * params - Format-specific parameters. - */ -VALUE -rb_encode_imageM(int argc, VALUE *argv, VALUE self) -{ - VALUE _ext, _params; - rb_scan_args(argc, argv, "11", &_ext, &_params); - Check_Type(_ext, T_STRING); - const char* ext = RSTRING_PTR(_ext); - CvMat* buff = NULL; - int* params = NULL; - - if (!NIL_P(_params)) { - params = hash_to_format_specific_param(_params); - } - - try { - buff = cvEncodeImage(ext, CVARR(self), params); - } - catch (cv::Exception& e) { - if (params != NULL) { - free(params); - params = NULL; - } - raise_cverror(e); - } - if (params != NULL) { - free(params); - params = NULL; - } - - const int size = buff->rows * buff->cols; - VALUE array = rb_ary_new2(size); - for (int i = 0; i < size; i++) { - rb_ary_store(array, i, CHR2FIX(CV_MAT_ELEM(*buff, char, 0, i))); - } - - try { - cvReleaseMat(&buff); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return array; -} - -CvMat* -prepare_decoding(int argc, VALUE *argv, int* iscolor, int* need_release) -{ - VALUE _buff, _iscolor; - rb_scan_args(argc, argv, "11", &_buff, &_iscolor); - *iscolor = NIL_P(_iscolor) ? CV_LOAD_IMAGE_COLOR : NUM2INT(_iscolor); - - CvMat* buff = NULL; - *need_release = 0; - switch (TYPE(_buff)) { - case T_STRING: - _buff = rb_funcall(_buff, rb_intern("unpack"), 1, rb_str_new("c*", 2)); - case T_ARRAY: { - int cols = RARRAY_LEN(_buff); - *need_release = 1; - try { - buff = rb_cvCreateMat(1, cols, CV_8UC1); - VALUE *ary_ptr = RARRAY_PTR(_buff); - for (int i = 0; i < cols; i++) { - CV_MAT_ELEM(*buff, char, 0, i) = NUM2CHR(ary_ptr[i]); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - break; - } - case T_DATA: - if (rb_obj_is_kind_of(_buff, cCvMat::rb_class()) == Qtrue) { - buff = CVMAT(_buff); - break; - } - default: - raise_typeerror(_buff, "CvMat, Array or String"); - } - - return buff; -} - -/* - * call-seq: - * decode_image(buf[, iscolor=CV_LOAD_IMAGE_COLOR]) -> CvMat - * - * Reads an image from a buffer in memory. - * - * Parameters: - * buf - Input array - * iscolor - Flags specifying the color type of a decoded image (the same flags as CvMat#load) - */ -VALUE -rb_decode_imageM(int argc, VALUE *argv, VALUE self) -{ - int iscolor, need_release; - CvMat* buff = prepare_decoding(argc, argv, &iscolor, &need_release); - CvMat* mat_ptr = NULL; - try { - mat_ptr = cvDecodeImageM(buff, iscolor); - if (need_release) { - cvReleaseMat(&buff); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return OPENCV_OBJECT(rb_klass, mat_ptr); -} - -/* - * nodoc - */ -VALUE -rb_method_missing(int argc, VALUE *argv, VALUE self) -{ - VALUE name, args, method; - rb_scan_args(argc, argv, "1*", &name, &args); - method = rb_funcall(name, rb_intern("to_s"), 0); - if (RARRAY_LEN(args) != 0 || !rb_respond_to(rb_module_opencv(), rb_intern(StringValuePtr(method)))) - return rb_call_super(argc, argv); - return rb_funcall(rb_module_opencv(), rb_intern(StringValuePtr(method)), 1, self); -} - -/* - * call-seq: - * to_s -> string - * - * Return following string. - * m = CvMat.new(100, 100, :cv8u, 3) - * m.to_s # => - */ -VALUE -rb_to_s(VALUE self) -{ - const int i = 6; - VALUE str[i]; - str[0] = rb_str_new2("<%s:%dx%d,depth=%s,channel=%d>"); - str[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); - str[2] = rb_width(self); - str[3] = rb_height(self); - str[4] = rb_depth(self); - str[5] = rb_channel(self); - return rb_f_sprintf(i, str); -} - -/* - * call-seq: - * inside?(obj) -> true or false - * - * - */ -VALUE -rb_inside_q(VALUE self, VALUE object) -{ - if (cCvPoint::rb_compatible_q(cCvPoint::rb_class(), object)) { - CvMat *mat = CVMAT(self); - int x = NUM2INT(rb_funcall(object, rb_intern("x"), 0)); - int y = NUM2INT(rb_funcall(object, rb_intern("y"), 0)); - if (cCvRect::rb_compatible_q(cCvRect::rb_class(), object)) { - int width = NUM2INT(rb_funcall(object, rb_intern("width"), 0)); - int height = NUM2INT(rb_funcall(object, rb_intern("height"), 0)); - return (x >= 0) && (y >= 0) && (x < mat->width) && ((x + width) < mat->width) - && (y < mat->height) && ((y + height) < mat->height) ? Qtrue : Qfalse; - } - else { - return (x >= 0) && (y >= 0) && (x < mat->width) && (y < mat->height) ? Qtrue : Qfalse; - } - } - rb_raise(rb_eArgError, "argument 1 should have method \"x\", \"y\""); - return Qnil; -} - -/* - * call-seq: - * to_IplConvKernel -> iplconvkernel - * - * Create IplConvKernel from this matrix. - */ -VALUE -rb_to_IplConvKernel(VALUE self, VALUE anchor) -{ - CvMat *src = CVMAT(self); - CvPoint p = VALUE_TO_CVPOINT(anchor); - IplConvKernel *kernel = rb_cvCreateStructuringElementEx(src->cols, src->rows, p.x, p.y, - CV_SHAPE_CUSTOM, src->data.i); - return DEPEND_OBJECT(cIplConvKernel::rb_class(), kernel, self); -} - -/* - * call-seq: - * create_mask -> cvmat(single-channel 8bit unsinged image) - * - * Create single-channel 8bit unsinged image that filled 0. - */ -VALUE -rb_create_mask(VALUE self) -{ - VALUE mask = cCvMat::new_object(cvGetSize(CVARR(self)), CV_8UC1); - try { - cvZero(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return mask; -} - -/* - * call-seq: - * width -> int - * - * Return number of columns. - */ -VALUE -rb_width(VALUE self) -{ - return INT2NUM(CVMAT(self)->width); -} - -/* - * call-seq: - * height -> int - * - * Return number of rows. - */ -VALUE -rb_height(VALUE self) -{ - return INT2NUM(CVMAT(self)->height); -} - -/* - * call-seq: - * depth -> symbol - * - * Return depth symbol. (see OpenCV::DEPTH) - */ -VALUE -rb_depth(VALUE self) -{ - return rb_hash_lookup(rb_funcall(rb_const_get(rb_module_opencv(), rb_intern("DEPTH")), rb_intern("invert"), 0), - INT2FIX(CV_MAT_DEPTH(CVMAT(self)->type))); -} - -/* - * call-seq: - * channel -> int (1 < channel < 4) - * - * Return number of channel. - */ -VALUE -rb_channel(VALUE self) -{ - return INT2FIX(CV_MAT_CN(CVMAT(self)->type)); -} - -/* - * call-seq: - * data -> binary (by String class) - * - * Return raw data of matrix. - */ -VALUE -rb_data(VALUE self) -{ - IplImage *image = IPLIMAGE(self); - return rb_str_new((char *)image->imageData, image->imageSize); -} - -/* - * call-seq: - * clone -> cvmat - * - * Clone matrix. - * Instance-specific method is succeeded. - * - * module M - * def example - * true - * end - * end - * - * mat.extend M - * mat.example #=> true - * clone = mat.clone - * clone.example #=> true - * copy = mat.copy - * copy.example #=> raise NoMethodError - */ -VALUE -rb_clone(VALUE self) -{ - VALUE clone = rb_obj_clone(self); - try { - DATA_PTR(clone) = cvClone(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return clone; -} - -/* - * call-seq: - * copy(dst = nil, mask = nil) -> cvmat - * - * Copies one array to another. - * - * dst - The destination array. - * mask - Operation mask, 8-bit single channel array; specifies elements of the destination array to be changed. - * - * The function copies selected elements from an input array to an output array: - * dst(I) = self(I) if mask(I) != 0 - */ -VALUE -rb_copy(int argc, VALUE *argv, VALUE self) -{ - VALUE _dst, _mask; - rb_scan_args(argc, argv, "02", &_dst, &_mask); - - CvMat* mask = MASK(_mask); - CvArr *src = CVARR(self); - if (NIL_P(_dst)) { - CvSize size = cvGetSize(src); - _dst = new_mat_kind_object(size, self); - } - - try { - cvCopy(src, CVARR_WITH_CHECK(_dst), mask); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return _dst; -} - -VALUE -copy(VALUE mat) -{ - return rb_clone(mat); -} - -inline VALUE -rb_to_X_internal(VALUE self, int depth) -{ - CvMat *src = CVMAT(self); - VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(depth, CV_MAT_CN(src->type))); - try { - cvConvert(src, CVMAT(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * to_8u -> cvmat(depth = CV_8U) - * - * Return the new matrix that elements is converted to unsigned 8bit. - */ -VALUE -rb_to_8u(VALUE self) -{ - return rb_to_X_internal(self, CV_8U); -} - -/* - * call-seq: - * to_8s -> cvmat(depth = CV_8S) - * - * Return the new matrix that elements is converted to signed 8bit. - */ -VALUE -rb_to_8s(VALUE self) -{ - return rb_to_X_internal(self, CV_8S); -} - -/* - * call-seq: - * to_16u -> cvmat(depth = CV_16U) - * - * Return the new matrix that elements is converted to unsigned 16bit. - */ -VALUE rb_to_16u(VALUE self) -{ - return rb_to_X_internal(self, CV_16U); -} - -/* - * call-seq: - * to_16s -> cvmat(depth = CV_16s) - * - * Return the new matrix that elements is converted to signed 16bit. - */ -VALUE -rb_to_16s(VALUE self) -{ - return rb_to_X_internal(self, CV_16S); -} - -/* - * call-seq: - * to_32s -> cvmat(depth = CV_32S) - * - * Return the new matrix that elements is converted to signed 32bit. - */ -VALUE -rb_to_32s(VALUE self) -{ - return rb_to_X_internal(self, CV_32S); -} - -/* - * call-seq: - * to_32f -> cvmat(depth = CV_32F) - * - * Return the new matrix that elements is converted to 32bit floating-point. - */ -VALUE -rb_to_32f(VALUE self) -{ - return rb_to_X_internal(self, CV_32F); -} - -/* - * call-seq: - * to_64F -> cvmat(depth = CV_64F) - * - * Return the new matrix that elements is converted to 64bit floating-point. - */ -VALUE -rb_to_64f(VALUE self) -{ - return rb_to_X_internal(self, CV_64F); -} - -/* - * call-seq: - * vector? -> true or false - * - * If #width or #height is 1, return true. Otherwise return false. - */ -VALUE -rb_vector_q(VALUE self) -{ - CvMat *mat = CVMAT(self); - return (mat->width == 1|| mat->height == 1) ? Qtrue : Qfalse; -} - -/* - * call-seq: - * square? -> true or false - * - * If #width == #height return true. Otherwise return false. - */ -VALUE -rb_square_q(VALUE self) -{ - CvMat *mat = CVMAT(self); - return mat->width == mat->height ? Qtrue : Qfalse; -} - -/************************************************************ - cxcore function -************************************************************/ -/* - * Return CvMat object with reference to caller-object. - * - * src = CvMat.new(10, 10) - * mat = src.to_CvMat - * - * In C, src->data and mat->data are common. Therefore, they cause changes with each other. - */ -VALUE -rb_to_CvMat(VALUE self) -{ - // CvMat#to_CvMat aborts when self's class is CvMat. - if (CLASS_OF(self) == rb_klass) - return self; - - CvMat *mat = NULL; - try { - mat = cvGetMat(CVARR(self), RB_CVALLOC(CvMat)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(rb_klass, mat, self); -} - -/* - * call-seq: - * sub_rect(rect) -> cvmat - * sub_rect(topleft, size) -> cvmat - * sub_rect(x, y, width, height) -> cvmat - * - * Return parts of self as CvMat. - * - * p or x,y mean top-left coordinate. - * size or width,height is size. - * - * link:../images/CvMat_sub_rect.png - */ -VALUE -rb_sub_rect(VALUE self, VALUE args) -{ - CvRect area; - CvPoint topleft; - CvSize size; - switch(RARRAY_LEN(args)) { - case 1: - area = VALUE_TO_CVRECT(RARRAY_PTR(args)[0]); - break; - case 2: - topleft = VALUE_TO_CVPOINT(RARRAY_PTR(args)[0]); - size = VALUE_TO_CVSIZE(RARRAY_PTR(args)[1]); - area.x = topleft.x; - area.y = topleft.y; - area.width = size.width; - area.height = size.height; - break; - case 4: - area.x = NUM2INT(RARRAY_PTR(args)[0]); - area.y = NUM2INT(RARRAY_PTR(args)[1]); - area.width = NUM2INT(RARRAY_PTR(args)[2]); - area.height = NUM2INT(RARRAY_PTR(args)[3]); - break; - default: - rb_raise(rb_eArgError, "wrong number of arguments (%ld of 1 or 2 or 4)", RARRAY_LEN(args)); - } - - CvMat* mat = NULL; - try { - mat = cvGetSubRect(CVARR(self), RB_CVALLOC(CvMat), area); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return DEPEND_OBJECT(rb_klass, mat, self); -} - -void -rb_get_range_index(VALUE index, int* start, int *end) { - if (rb_obj_is_kind_of(index, rb_cRange)) { - *start = NUM2INT(rb_funcall3(index, rb_intern("begin"), 0, NULL)); - *end = NUM2INT(rb_funcall3(index, rb_intern("end"), 0, NULL)); - if (rb_funcall3(index, rb_intern("exclude_end?"), 0, NULL) == Qfalse) { - (*end)++; - } - } - else { - *start = NUM2INT(index); - *end = *start + 1; - } -} - -/* - * call-seq: - * get_rows(row, delta_row = 1) -> cvmat - * - * Return row(or rows) of matrix. - * argument row should be Fixnum or Range object. - */ -VALUE -rb_get_rows(int argc, VALUE* argv, VALUE self) -{ - VALUE row_val, delta_val; - rb_scan_args(argc, argv, "11", &row_val, &delta_val); - - int start, end; - rb_get_range_index(row_val, &start, &end); - int delta = NIL_P(delta_val) ? 1 : NUM2INT(delta_val); - CvMat* submat = RB_CVALLOC(CvMat); - try { - cvGetRows(CVARR(self), submat, start, end, delta); - } - catch (cv::Exception& e) { - cvFree(&submat); - raise_cverror(e); - } - - return DEPEND_OBJECT(rb_klass, submat, self); -} - -/* - * call-seq: - * get_cols(col) -> cvmat - * - * Return column(or columns) of matrix. - * argument col should be Fixnum or Range object. - */ -VALUE -rb_get_cols(VALUE self, VALUE col) -{ - int start, end; - rb_get_range_index(col, &start, &end); - CvMat* submat = RB_CVALLOC(CvMat); - try { - cvGetCols(CVARR(self), submat, start, end); - } - catch (cv::Exception& e) { - cvFree(&submat); - raise_cverror(e); - } - - return DEPEND_OBJECT(rb_klass, submat, self); -} - -/* - * call-seq: - * each_row {|row| ... } -> self - * - * Calls block once for each row in self, passing that element as a parameter. - * - * see also CvMat#each_col - */ -VALUE -rb_each_row(VALUE self) -{ - int rows = CVMAT(self)->rows; - CvMat* row = NULL; - for (int i = 0; i < rows; ++i) { - try { - row = cvGetRow(CVARR(self), RB_CVALLOC(CvMat), i); - } - catch (cv::Exception& e) { - if (row != NULL) - cvReleaseMat(&row); - raise_cverror(e); - } - rb_yield(DEPEND_OBJECT(rb_klass, row, self)); - } - return self; -} - -/* - * call-seq: - * each_col {|col| ... } -> self - * - * Calls block once for each column in self, passing that element as a parameter. - * - * see also CvMat#each_row - */ -VALUE -rb_each_col(VALUE self) -{ - int cols = CVMAT(self)->cols; - CvMat *col = NULL; - for (int i = 0; i < cols; ++i) { - try { - col = cvGetCol(CVARR(self), RB_CVALLOC(CvMat), i); - } - catch (cv::Exception& e) { - if (col != NULL) - cvReleaseMat(&col); - raise_cverror(e); - } - rb_yield(DEPEND_OBJECT(rb_klass, col, self)); - } - return self; -} - -/* - * call-seq: - * diag([val = 0]) -> cvmat - * - * Return one of array diagonals. - * val is zero corresponds to the main diagonal, -1 corresponds to the diagonal above the main etc, 1 corresponds to the diagonal below the main etc. - * - */ -VALUE -rb_diag(int argc, VALUE *argv, VALUE self) -{ - VALUE val; - if (rb_scan_args(argc, argv, "01", &val) < 1) - val = INT2FIX(0); - CvMat* diag = NULL; - try { - diag = cvGetDiag(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(val)); - } - catch (cv::Exception& e) { - cvReleaseMat(&diag); - raise_cverror(e); - } - return DEPEND_OBJECT(rb_klass, diag, self); -} - -/* - * call-seq: - * size -> cvsize - * - * Return size by CvSize - */ -VALUE -rb_size(VALUE self) -{ - CvSize size; - try { - size = cvGetSize(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvSize::new_object(size); -} - -/* - * call-seq: - * dims -> array(int, int, ...) - * - * Return number of array dimensions and their sizes or the size of particular dimension. - * In case of CvMat it always returns 2 regardless of number of matrix rows. - */ -VALUE -rb_dims(VALUE self) -{ - int size[CV_MAX_DIM]; - int dims = 0; - try { - dims = cvGetDims(CVARR(self), size); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - VALUE ary = rb_ary_new2(dims); - for (int i = 0; i < dims; ++i) { - rb_ary_store(ary, i, INT2NUM(size[i])); - } - return ary; -} - -/* - * call-seq: - * dim_size(index) -> int - * - * Return number of dimension. - * almost same as CvMat#dims[index]. - * If the dimension specified with index doesn't exist, CvStatusOutOfRange raise. - */ -VALUE -rb_dim_size(VALUE self, VALUE index) -{ - int dimsize = 0; - try { - dimsize = cvGetDimSize(CVARR(self), NUM2INT(index)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return INT2NUM(dimsize); -} - -/* - * call-seq: - * [idx1[,idx2]...] - * - * Return value of the particular array element as CvScalar. - */ -VALUE -rb_aref(VALUE self, VALUE args) -{ - int index[CV_MAX_DIM]; - for (int i = 0; i < RARRAY_LEN(args); ++i) - index[i] = NUM2INT(rb_ary_entry(args, i)); - - CvScalar scalar = cvScalarAll(0); - try { - switch (RARRAY_LEN(args)) { - case 1: - scalar = cvGet1D(CVARR(self), index[0]); - break; - case 2: - scalar = cvGet2D(CVARR(self), index[0], index[1]); - break; - default: - scalar = cvGetND(CVARR(self), index); - break; - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvScalar::new_object(scalar); -} - -/* - * call-seq: - * [idx1[,idx2]...] = value - * - * Set value of the particular array element to value. - * value should be CvScalar. - */ -VALUE -rb_aset(VALUE self, VALUE args) -{ - CvScalar scalar = VALUE_TO_CVSCALAR(rb_ary_pop(args)); - int index[CV_MAX_DIM]; - for (int i = 0; i < RARRAY_LEN(args); ++i) - index[i] = NUM2INT(rb_ary_entry(args, i)); - - try { - switch (RARRAY_LEN(args)) { - case 1: - cvSet1D(CVARR(self), index[0], scalar); - break; - case 2: - cvSet2D(CVARR(self), index[0], index[1], scalar); - break; - default: - cvSetND(CVARR(self), index, scalar); - break; - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * set_data(data) - * - * Assigns user data to the array header. - * data should be Array which contains numbers. - */ -VALUE -rb_set_data(VALUE self, VALUE data) -{ - data = rb_funcall(data, rb_intern("flatten"), 0); - const int DATA_LEN = RARRAY_LEN(data); - CvMat *self_ptr = CVMAT(self); - int depth = CV_MAT_DEPTH(self_ptr->type); - void* array = NULL; - - switch (depth) { - case CV_8U: - array = rb_cvAlloc(sizeof(uchar) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((uchar*)array)[i] = (uchar)(NUM2INT(rb_ary_entry(data, i))); - break; - case CV_8S: - array = rb_cvAlloc(sizeof(char) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((char*)array)[i] = (char)(NUM2INT(rb_ary_entry(data, i))); - break; - case CV_16U: - array = rb_cvAlloc(sizeof(ushort) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((ushort*)array)[i] = (ushort)(NUM2INT(rb_ary_entry(data, i))); - break; - case CV_16S: - array = rb_cvAlloc(sizeof(short) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((short*)array)[i] = (short)(NUM2INT(rb_ary_entry(data, i))); - break; - case CV_32S: - array = rb_cvAlloc(sizeof(int) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((int*)array)[i] = NUM2INT(rb_ary_entry(data, i)); - break; - case CV_32F: - array = rb_cvAlloc(sizeof(float) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((float*)array)[i] = (float)NUM2DBL(rb_ary_entry(data, i)); - break; - case CV_64F: - array = rb_cvAlloc(sizeof(double) * DATA_LEN); - for (int i = 0; i < DATA_LEN; ++i) - ((double*)array)[i] = NUM2DBL(rb_ary_entry(data, i)); - break; - default: - rb_raise(rb_eArgError, "Invalid CvMat depth"); - break; - } - - try { - cvSetData(self_ptr, array, self_ptr->step); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return self; -} - -/* - * call-seq: - * set(value[, mask]) -> cvmat - * - * Return CvMat copied value to every selected element. value should be CvScalar or compatible object. - * self[I] = value if mask(I)!=0 - * - * note: This method support ROI on IplImage class. but COI not support. COI should not be set. - * image = IplImage.new(10, 20) #=> create 3 channel image. - * image.coi = 1 #=> set COI - * image.set(CvScalar.new(10, 20, 30)) #=> raise CvBadCOI error. - */ -VALUE -rb_set(int argc, VALUE *argv, VALUE self) -{ - return rb_set_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * set!(value[, mask]) -> self - * - * Copie value to every selected element. - * self[I] = value if mask(I)!=0 - * - * see also #set. - */ -VALUE -rb_set_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE value, mask; - rb_scan_args(argc, argv, "11", &value, &mask); - try { - cvSet(CVARR(self), VALUE_TO_CVSCALAR(value), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * save_image(filename, params = nil) -> self - * - * Saves an image to file. The image format is chosen depending on the filename extension. - * Only 8bit single-channel or 3-channel(with 'BGR' channel order) image can be saved. - * - * e.g. - * image = OpenCV::CvMat.new(10, 10, CV_8U, 3) - * image.save_image("image.jpg") #=> save as JPEG format - * image.save_image("image.png") #=> save as PNG format - */ -VALUE -rb_save_image(int argc, VALUE *argv, VALUE self) -{ - VALUE _filename, _params; - rb_scan_args(argc, argv, "11", &_filename, &_params); - Check_Type(_filename, T_STRING); - int *params = NULL; - if (!NIL_P(_params)) { - params = hash_to_format_specific_param(_params); - } - - try { - cvSaveImage(StringValueCStr(_filename), CVARR(self), params); - } - catch (cv::Exception& e) { - if (params != NULL) { - free(params); - params = NULL; - } - raise_cverror(e); - } - if (params != NULL) { - free(params); - params = NULL; - } - - return self; -} - -/* - * call-seq: - * set_zero -> cvmat - * - * Return new matrix all element-value cleared. - */ -VALUE -rb_set_zero(VALUE self) -{ - return rb_set_zero_bang(copy(self)); -} - -/* - * call-seq: - * set_zero! -> self - * - * Clear all element-value. Return self. - */ -VALUE -rb_set_zero_bang(VALUE self) -{ - try { - cvSetZero(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * identity([val = [1]]) -> cvmat - * - * Return initializes scaled identity matrix. - * val should be CvScalar. - * - * arr(i, j) = val if i = j, 0 otherwise - */ -VALUE -rb_set_identity(int argc, VALUE *argv, VALUE self) -{ - return rb_set_identity_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * identity!([val = [1]]) -> self - * - * Initialize scaled identity matrix. - * val should be CvScalar. - * - * arr(i, j) = val if i = j, 0 otherwise - */ -VALUE -rb_set_identity_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE val; - CvScalar value; - if (rb_scan_args(argc, argv, "01", &val) < 1) - value = cvRealScalar(1); - else - value = VALUE_TO_CVSCALAR(val); - - try { - cvSetIdentity(CVARR(self), value); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * range(start, end) -> cvmat - * - * Create and return filled matrix with given range of numbers. - * - * see range! - */ -VALUE -rb_range(VALUE self, VALUE start, VALUE end) -{ - return rb_range_bang(copy(self), start, end); -} - -/* - * call-seq: - * range!(start, end) -> self - * - * Fills matrix with given range of numbers. - * - * initializes the matrix as following: - * arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr)) - * For example, the following code will initilize 1D vector with subsequent integer numbers. - * m = CvMat.new(1, 10, :cv32s) - * m.range!(0, m.cols); // m will be initialized as [0,1,2,3,4,5,6,7,8,9] - */ -VALUE -rb_range_bang(VALUE self, VALUE start, VALUE end) -{ - try { - cvRange(CVARR(self), NUM2DBL(start), NUM2DBL(end)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - - -/* - * call-seq: - * reshape(cn, rows=0) -> cvmat(refer self) - * - * Change shape of matrix/image without copying data. - * - * Parameter: - * * cn - New number of channels. If the parameter is 0, the number of channels remains the same. - * * rows - New number of rows. If the parameter is 0, the number of rows remains the same. - */ -VALUE -rb_reshape(int argc, VALUE *argv, VALUE self) -{ - VALUE cn, rows; - CvMat *mat = NULL; - rb_scan_args(argc, argv, "11", &cn, &rows); - try { - mat = cvReshape(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(cn), IF_INT(rows, 0)); - } - catch (cv::Exception& e) { - if (mat != NULL) - cvReleaseMat(&mat); - raise_cverror(e); - } - return DEPEND_OBJECT(rb_klass, mat, self); -} - -/* - * call-seq: - * repeat(mat) -> cvmat - * - * Tiled mat by self. - */ -VALUE -rb_repeat(VALUE self, VALUE object) -{ - try { - cvRepeat(CVARR(self), CVARR_WITH_CHECK(object)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return object; -} - -/* - * call-seq: - * flip(:x) -> cvmat - * flip(:y) -> cvmat - * flip(:xy) -> cvmat - * flip -> cvmat - * - * Return new flipped 2D array. - * * flip(:x) - flip around horizontal - * * flip(:y) - flip around vertical - * * flip(:xy) - flip around both axises - * * flip - flip around vertical - */ -VALUE -rb_flip(int argc, VALUE *argv, VALUE self) -{ - return rb_flip_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * flip!(:x) -> self - * flip!(:y) -> self - * flip!(:xy) -> self - * flip! -> self - * - * Flip 2D array. Return self. - * - * see also CvMat#flip - */ -VALUE -rb_flip_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE format; - int mode = 1; - if (rb_scan_args(argc, argv, "01", &format) > 0) { - Check_Type(format, T_SYMBOL); - ID flip_mode = rb_to_id(format); - if (flip_mode == rb_intern("x")) { - mode = 1; - } - else if (flip_mode == rb_intern("y")) { - mode = 0; - } - else if (flip_mode == rb_intern("xy")) { - mode = -1; - } - } - try { - cvFlip(CVARR(self), NULL, mode); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * split -> array(include cvmat) - * - * Divides multi-channel array into several single-chanel arrays. - * - * e.g. - * image = CvMat.new 640, 480, CV_8U, 3 #=> 3-channel image - * image.split #=> [image1, image2, image3] : each image have single-channel - * - * e.g. switch red <-> blue channel. - * image = IplImage.load "sample.bmp" - * i = image.split - * new_image = CvMat.merge i[2], i[1], i[0] - */ -VALUE -rb_split(VALUE self) -{ - CvArr* self_ptr = CVARR(self); - int type = cvGetElemType(self_ptr); - int depth = CV_MAT_DEPTH(type), channel = CV_MAT_CN(type); - VALUE dest = rb_ary_new2(channel); - try { - CvArr *dest_ptr[] = { NULL, NULL, NULL, NULL }; - CvSize size = cvGetSize(self_ptr); - for (int i = 0; i < channel; ++i) { - VALUE tmp = new_mat_kind_object(size, self, depth, 1); - rb_ary_store(dest, i, tmp); - dest_ptr[i] = CVARR(tmp); - } - cvSplit(self_ptr, dest_ptr[0], dest_ptr[1], dest_ptr[2], dest_ptr[3]); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dest; -} - -/* - * call-seq: - * CvMat.merge(mat1[,mat2][,mat3][,mat4]) -> cvmat - * - * Composes multi-channel array from several single-channel arrays. - * Each argument should be single-channel image(CvMat or subclass). - * All image should be same size and same depth. - * - * see also CvMat#split - */ -VALUE -rb_merge(VALUE klass, VALUE args) -{ - int len = RARRAY_LEN(args); - if (len <= 0 || len > 4) { - rb_raise(rb_eArgError, "wrong number of argument (%d for 1..4)", len); - } - CvMat *src[] = { NULL, NULL, NULL, NULL }, *prev_src = NULL; - for (int i = 0; i < len; ++i) { - VALUE object = rb_ary_entry(args, i); - if (NIL_P(object)) - src[i] = NULL; - else { - src[i] = CVMAT_WITH_CHECK(object); - if (CV_MAT_CN(src[i]->type) != 1) - rb_raise(rb_eArgError, "image should be single-channel CvMat."); - if (prev_src == NULL) - prev_src = src[i]; - else { - if (!CV_ARE_SIZES_EQ(prev_src, src[i])) - rb_raise(rb_eArgError, "image size should be same."); - if (!CV_ARE_DEPTHS_EQ(prev_src, src[i])) - rb_raise(rb_eArgError, "image depth should be same."); - } - } - } - // TODO: adapt IplImage - VALUE dest = Qnil; - try { - dest = new_object(cvGetSize(src[0]), CV_MAKETYPE(CV_MAT_DEPTH(src[0]->type), len)); - cvMerge(src[0], src[1], src[2], src[3], CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * rand_shuffle([seed = nil][,iter_factor = 1]) -> cvmat - * - * Return shuffled matrix - * - * see rand_shuffle! - */ -VALUE -rb_rand_shuffle(int argc, VALUE *argv, VALUE self) -{ - return rb_rand_shuffle_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * rand_shuffle!([seed = nil][,iter_factor = 1]) -> cvmat - * - * Shuffles the matrix by swapping randomly chosen pairs of the matrix elements on each iteration - * (where each element may contain several components in case of multi-channel arrays). The number of - * iterations (i.e. pairs swapped) is (iter_factor*mat.rows*mat.cols).round, so iter_factor=0 means - * that no shuffling is done, iter_factor=1 means that the function swaps rows(mat)*cols(mat) random - * pairs etc. - */ -VALUE -rb_rand_shuffle_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE seed, iter; - rb_scan_args(argc, argv, "02", &seed, &iter); - try { - if (NIL_P(seed)) - cvRandShuffle(CVARR(self), NULL, IF_INT(iter, 1)); - else { - CvRNG rng = cvRNG(rb_num2ll(seed)); - cvRandShuffle(CVARR(self), &rng, IF_INT(iter, 1)); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * lut(lookup_table) -> cvmat - * - * Return new matrix performed lookup-table transform. - * - * lookup_table should be CvMat that have 256 element (e.g. 1x256 matrix). - * Otherwise, raise CvStatusBadArgument error. - * - * And lookup_table should either have a single-channel, or the same number of channels. - * When single-channel lookup-table given, same table is used for all channels. - */ -VALUE -rb_lut(VALUE self, VALUE lut) -{ - VALUE dest = copy(self); - try { - cvLUT(CVARR(self), CVARR(dest), CVARR_WITH_CHECK(lut)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * convert_scale(:depth => nil, :scale => 1.0, :shift => 0.0) - * - * Return new array with optional linear transformation. - * mat(I) = src(I) * scale + (shift, shift, ...) - */ -VALUE -rb_convert_scale(VALUE self, VALUE hash) -{ - Check_Type(hash, T_HASH); - CvMat* self_ptr = CVMAT(self); - VALUE depth = LOOKUP_HASH(hash, "depth"); - VALUE scale = LOOKUP_HASH(hash, "scale"); - VALUE shift = LOOKUP_HASH(hash, "shift"); - - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self, - CVMETHOD("DEPTH", depth, CV_MAT_DEPTH(self_ptr->type)), - CV_MAT_CN(self_ptr->type)); - cvConvertScale(self_ptr, CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * convert_scale_abs(:scale => 1.0, :shift => 0.0) - * - * Return new array with optional linear transformation. - * It is similar to CvMat#convert_scale, but it stores absolute values of the conversion result - * mat(I) = (src(I) * scale + (shift, shift, ...)).abs - */ -VALUE -rb_convert_scale_abs(VALUE self, VALUE hash) -{ - Check_Type(hash, T_HASH); - CvMat* self_ptr = CVMAT(self); - VALUE scale = LOOKUP_HASH(hash, "scale"); - VALUE shift = LOOKUP_HASH(hash, "shift"); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_8U, CV_MAT_CN(CVMAT(self)->type)); - cvConvertScaleAbs(self_ptr, CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * add(val[,mask]) -> cvmat - * - * Return new matrix computed per-element sum. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * mask should be CvMat(8bit single-channel). - * For each element (I) - * dst(I) = src1(I) + src2(I) if mask(I) != 0 - */ -VALUE -rb_add(int argc, VALUE *argv, VALUE self) -{ - VALUE val, mask, dest; - rb_scan_args(argc, argv, "11", &val, &mask); - dest = copy(self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvAdd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); - else - cvAddS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * sub(val[,mask]) -> cvmat - * - * Return new matrix computed per-element difference. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * mask should be CvMat(8bit single-channel). - * For each element (I) - * dst(I) = src1(I) - src2(I) if mask(I) != 0 - */ -VALUE -rb_sub(int argc, VALUE *argv, VALUE self) -{ - VALUE val, mask, dest; - rb_scan_args(argc, argv, "11", &val, &mask); - dest = copy(self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvSub(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); - else - cvSubS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * mul(val[,scale = 1.0]) -> cvmat - * - * Return new matrix computed per-element product. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * For each element (I) - * dst(I) = scale * src1(I) * src2(I) - */ -VALUE -rb_mul(int argc, VALUE *argv, VALUE self) -{ - VALUE val, scale, dest; - if (rb_scan_args(argc, argv, "11", &val, &scale) < 2) - scale = rb_float_new(1.0); - dest = new_mat_kind_object(cvGetSize(CVARR(self)), self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvMul(CVARR(self), CVARR(val), CVARR(dest), NUM2DBL(scale)); - else { - CvScalar scl = VALUE_TO_CVSCALAR(val); - VALUE mat = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self))); - cvSet(CVARR(mat), scl); - cvMul(CVARR(self), CVARR(mat), CVARR(dest), NUM2DBL(scale)); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * mat_mul(val[,shiftvec]) -> cvmat - * Performs matrix multiplication - * dst = src1 * src2 + shiftvec - * val and shiftvec should be CvMat - * All the matrices should have the same data type and coordinated sizes. - * Real or complex floating-point matrices are supported. - */ -VALUE -rb_mat_mul(int argc, VALUE *argv, VALUE self) -{ - VALUE val, shiftvec, dest; - rb_scan_args(argc, argv, "11", &val, &shiftvec); - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - try { - if (NIL_P(shiftvec)) - cvMatMul(self_ptr, CVARR_WITH_CHECK(val), CVARR(dest)); - else - cvMatMulAdd(self_ptr, CVARR_WITH_CHECK(val), CVARR_WITH_CHECK(shiftvec), CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * div(val[,scale = 1.0]) -> cvmat - * - * Return new matrix computed per-element division. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * For each element (I) - * dst(I) = scale * src1(I) / src2(I) - */ -VALUE -rb_div(int argc, VALUE *argv, VALUE self) -{ - VALUE val, scale; - if (rb_scan_args(argc, argv, "11", &val, &scale) < 2) - scale = rb_float_new(1.0); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - if (rb_obj_is_kind_of(val, rb_klass)) - cvDiv(self_ptr, CVARR(val), CVARR(dest), NUM2DBL(scale)); - else { - CvScalar scl = VALUE_TO_CVSCALAR(val); - VALUE mat = new_mat_kind_object(cvGetSize(self_ptr), self); - CvArr* mat_ptr = CVARR(mat); - cvSet(mat_ptr, scl); - cvDiv(self_ptr, mat_ptr, CVARR(dest), NUM2DBL(scale)); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * add_weighted(src1, alpha, src2, beta, gamma) - * - * Computes the weighted sum of two arrays. - * - * src1 - The first source array - * alpha - Weight for the first array elements - * src2 - The second source array - * beta - Weight for the second array elements - * gamma - Added to each sum - * - * The function calculates the weighted sum of two arrays as follows: - * dst(I)=src1(I)*alpha+src2(I)*beta+gamma - * All the arrays must have the same type and the same size (or ROI size). - * For types that have limited range this operation is saturating. - */ -VALUE -rb_add_weighted(VALUE klass, VALUE src1, VALUE alpha, VALUE src2, VALUE beta, VALUE gamma) -{ - CvArr* src1_ptr = CVARR_WITH_CHECK(src1); - VALUE dst = new_mat_kind_object(cvGetSize(src1_ptr), src1); - try { - cvAddWeighted(src1_ptr, NUM2DBL(alpha), - CVARR_WITH_CHECK(src2), NUM2DBL(beta), - NUM2DBL(gamma), CVARR(dst)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dst; -} - -/* - * call-seq: - * and(val[,mask]) -> cvmat - * - * Return new matrix computed per-element bit-wise conjunction. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * For each element (I) - * dst(I) = src1(I) & src2(I) if mask(I) != 0 - */ -VALUE -rb_and(int argc, VALUE *argv, VALUE self) -{ - VALUE val, mask, dest; - rb_scan_args(argc, argv, "11", &val, &mask); - dest = copy(self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvAnd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); - else - cvAndS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * or(val[,mask]) -> cvmat - * - * Return new matrix computed per-element bit-wise disjunction. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * For each element (I) - * dst(I) = src1(I) | src2(I) if mask(I) != 0 - */ -VALUE -rb_or(int argc, VALUE *argv, VALUE self) -{ - VALUE val, mask, dest; - rb_scan_args(argc, argv, "11", &val, &mask); - dest = copy(self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvOr(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); - else - cvOrS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * xor(val[,mask]) -> cvmat - * - * Return new matrix computed per-element bit-wise "exclusive or" operation. - * val should be CvMat or CvScalar. - * If val is CvMat, it must have same type (depth and channel). - * For each element (I) - * dst(I) = src1(I) ^ src2(I) if mask(I) != 0 - */ -VALUE -rb_xor(int argc, VALUE *argv, VALUE self) -{ - VALUE val, mask, dest; - rb_scan_args(argc, argv, "11", &val, &mask); - dest = copy(self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvXor(CVARR(self), CVARR(val), CVARR(dest), MASK(mask)); - else - cvXorS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * not -> cvmat - * - * Return new matrix performed per-element bit-wise inversion. - * dst(I) =~ src(I) - */ -VALUE -rb_not(VALUE self) -{ - return rb_not_bang(copy(self)); -} - -/* - * call-seq: - * not! -> self - * - * Performe per-element bit-wise inversion. - */ -VALUE -rb_not_bang(VALUE self) -{ - try { - cvNot(CVARR(self), CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -VALUE -rb_cmp_internal(VALUE self, VALUE val, int operand) -{ - CvArr* self_ptr = CVARR(self); - VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_8U, 1); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvCmp(self_ptr, CVARR(val), CVARR(dest), operand); - else if (CV_MAT_CN(cvGetElemType(self_ptr)) == 1 && rb_obj_is_kind_of(val, rb_cNumeric)) - cvCmpS(self_ptr, NUM2DBL(val), CVARR(dest), operand); - else { - VALUE mat = new_mat_kind_object(cvGetSize(CVARR(self)), self); - cvSet(CVARR(mat), VALUE_TO_CVSCALAR(val)); - cvCmp(self_ptr, CVARR(mat), CVARR(dest), operand); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * eq(val) -> cvmat - * - * Return new matrix performed per-element comparision "equal". - * dst(I) = (self(I) == val(I) ? 0xFF : 0) - */ -VALUE -rb_eq(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_EQ); -} - -/* - * call-seq: - * gt(val) -> cvmat - * - * Return new matrix performed per-element comparision "greater than". - * dst(I) = (self(I) > val(I) ? 0xFF : 0) - */ -VALUE -rb_gt(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_GT); -} - -/* - * call-seq: - * ge(val) -> cvmat - * - * Return new matrix performed per-element comparision "greater or equal". - * dst(I) = (self(I) >= val(I) ? 0xFF : 0) - */ -VALUE -rb_ge(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_GE); -} - -/* - * call-seq: - * lt(val) -> cvmat - * - * Return new matrix performed per-element comparision "less than". - * dst(I) = (self(I) < val(I) ? 0xFF : 0) - */ -VALUE -rb_lt(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_LT); -} - -/* - * call-seq: - * le(val) -> cvmat - * - * Return new matrix performed per-element comparision "less or equal". - * dst(I) = (self(I) <= val(I) ? 0xFF : 0) - */ -VALUE -rb_le(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_LE); -} - -/* - * call-seq: - * ne(val) -> cvmat - * - * Return new matrix performed per-element comparision "not equal". - * dst(I) = (self(I) != val(I) ? 0xFF : 0) - */ -VALUE -rb_ne(VALUE self, VALUE val) -{ - return rb_cmp_internal(self, val, CV_CMP_NE); -} - -/* - * call-seq: - * in_range(min, max) -> cvmat - * - * Check that element lie between two object. - * min and max should be CvMat that have same size and type, or CvScalar. - * Return new matrix performed per-element, - * dst(I) = within the range ? 0xFF : 0 - */ -VALUE -rb_in_range(VALUE self, VALUE min, VALUE max) -{ - CvArr* self_ptr = CVARR(self); - CvSize size = cvGetSize(self_ptr); - VALUE dest = new_object(size, CV_8UC1); - try { - if (rb_obj_is_kind_of(min, rb_klass) && rb_obj_is_kind_of(max, rb_klass)) - cvInRange(self_ptr, CVARR(min), CVARR(max), CVARR(dest)); - else if (rb_obj_is_kind_of(min, rb_klass)) { - VALUE tmp = new_object(size, cvGetElemType(self_ptr)); - cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(max)); - cvInRange(self_ptr, CVARR(min), CVARR(tmp), CVARR(dest)); - } - else if (rb_obj_is_kind_of(max, rb_klass)) { - VALUE tmp = new_object(size, cvGetElemType(self_ptr)); - cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(min)); - cvInRange(self_ptr, CVARR(tmp), CVARR(max), CVARR(dest)); - } - else - cvInRangeS(self_ptr, VALUE_TO_CVSCALAR(min), VALUE_TO_CVSCALAR(max), CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * abs_diff(val) -> cvmat - * - * Calculate absolute difference between two. - * val should be CvMat that have same size and same type, or CvScalar. - * dst(I) = (src(I) - val(I)).abs - */ -VALUE -rb_abs_diff(VALUE self, VALUE val) -{ - CvArr* self_ptr = CVARR(self); - VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); - try { - if (rb_obj_is_kind_of(val, rb_klass)) - cvAbsDiff(self_ptr, CVARR(val), CVARR(dest)); - else - cvAbsDiffS(self_ptr, CVARR(dest), VALUE_TO_CVSCALAR(val)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * normalize(alpha=1, beta=0, norm_type=NORM_L2, dtype=-1, mask=nil) -> cvmat - * - * Normalizes the norm or value range of an array. - * - * Parameters: - * * alpha - norm value to normalize to or the lower range boundary in case of the range normalization. - * * beta - upper range boundary in case of the range normalization; it is not used for the norm normalization. - * * norm_type - normalization type. - * * dtype - when negative, the output array has the same type as src; otherwise, it has the same number of channels as src and the depth - * * mask - optional operation mask. - */ -VALUE -rb_normalize(int argc, VALUE *argv, VALUE self) -{ - VALUE alpha_val, beta_val, norm_type_val, dtype_val, mask_val; - rb_scan_args(argc, argv, "05", &alpha_val, &beta_val, &norm_type_val, &dtype_val, &mask_val); - - double alpha = NIL_P(alpha_val) ? 1.0 : NUM2DBL(alpha_val); - double beta = NIL_P(beta_val) ? 0.0 : NUM2DBL(beta_val); - int norm_type = NIL_P(norm_type_val) ? cv::NORM_L2 : NUM2INT(norm_type_val); - int dtype = NIL_P(dtype_val) ? -1 : NUM2INT(dtype_val); - VALUE dst; - - try { - cv::Mat self_mat(CVMAT(self)); - cv::Mat dst_mat; - - if (NIL_P(mask_val)) { - cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype); - } - else { - cv::Mat mask(MASK(mask_val)); - cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype, mask); - } - dst = new_mat_kind_object(cvGetSize(CVARR(self)), self, dst_mat.depth(), dst_mat.channels()); - - CvMat tmp = dst_mat; - cvCopy(&tmp, CVMAT(dst)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dst; -} - -/* - * call-seq: - * count_non_zero -> int - * - * Returns the number of non-zero elements. - * result = sumI arr(I)!=0 - * - * In case of IplImage both ROI and COI are supported. - */ -VALUE -rb_count_non_zero(VALUE self) -{ - int n = 0; - try { - n = cvCountNonZero(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return INT2NUM(n); -} - -/* - * call-seq: - * sum -> scalar - * - * Return summerizes elements as CvScalar. Independently for each channel. - * - * note: If COI is setted in IplImage, the method processes the selected channel only and store the sum to the first component scalar[0]. - */ -VALUE -rb_sum(VALUE self) -{ - CvScalar sum; - try { - sum = cvSum(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvScalar::new_object(sum); -} - -/* - * call-seq: - * avg([mask]) -> mean(as scalar) - * - * Return the average(mean) of elements as CvScalar. Independently for each channel. - */ -VALUE -rb_avg(int argc, VALUE *argv, VALUE self) -{ - VALUE mask; - rb_scan_args(argc, argv, "01", &mask); - CvScalar avg; - try { - avg = cvAvg(CVARR(self), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvScalar::new_object(avg); -} - -/* - * call-seq: - * avg_sdv(mask) -> [mean(as scalar), std_dev(as scalar)] - * - * Calculates the average value and standard deviation of array elements, independently for each channel. - * - * note: same as [CvMat#avg, CvMat#sdv] - */ -VALUE -rb_avg_sdv(int argc, VALUE *argv, VALUE self) -{ - VALUE mask, mean, std_dev; - rb_scan_args(argc, argv, "01", &mask); - mean = cCvScalar::new_object(); - std_dev = cCvScalar::new_object(); - try { - cvAvgSdv(CVARR(self), CVSCALAR(mean), CVSCALAR(std_dev), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, mean, std_dev); -} - -/* - * call-seq: - * sdv([mask]) -> std_dev(as scalar) - * - * Return the standard deviation of elements as CvScalar. Independently for each channel. - */ -VALUE -rb_sdv(int argc, VALUE *argv, VALUE self) -{ - VALUE mask, std_dev; - rb_scan_args(argc, argv, "01", &mask); - std_dev = cCvScalar::new_object(); - try { - cvAvgSdv(CVARR(self), NULL, CVSCALAR(std_dev), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return std_dev; -} - -/* - * call-seq: - * min_max_loc([mask]) -> [min_val, max_val, min_loc(as point), max_loc(as point)] - * - * Finds minimum and maximum element values and their positions. - * The extremums are searched over the whole array, selected ROI(in case of IplImage) or, if mask is not NULL, in the specified array region. - * If the array has more than one channel, it must be IplImage with COI set. - * In case if multi-dimensional arrays min_loc.x and max_loc.x will contain raw (linear) positions of the extremums. - */ -VALUE -rb_min_max_loc(int argc, VALUE *argv, VALUE self) -{ - VALUE mask, min_loc, max_loc; - double min_val = 0.0, max_val = 0.0; - rb_scan_args(argc, argv, "01", &mask); - min_loc = cCvPoint::new_object(); - max_loc = cCvPoint::new_object(); - try { - cvMinMaxLoc(CVARR(self), &min_val, &max_val, CVPOINT(min_loc), CVPOINT(max_loc), MASK(mask)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(4, rb_float_new(min_val), rb_float_new(max_val), min_loc, max_loc); -} - -/* - * call-seq: - * dot_product(mat) -> float - * - * Calculates dot product of two arrays in Euclidian metrics. - * mat should be CvMat have same size and same type. - * - * src1.src2 = sum(src1(I) * src2(I)) - */ -VALUE -rb_dot_product(VALUE self, VALUE mat) -{ - double result = 0.0; - try { - result = cvDotProduct(CVARR(self), CVARR_WITH_CHECK(mat)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_float_new(result); -} - -/* - * call-seq: - * cross_product(mat) -> cvmat - * - * Calculate cross product of two 3D vectors. - * mat should be CvMat have same size and same type. - */ -VALUE -rb_cross_product(VALUE self, VALUE mat) -{ - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvCrossProduct(self_ptr, CVARR_WITH_CHECK(mat), CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * transform(transmat[,shiftvec]) -> cvmat - * - * performs matrix transform of every element. - * dst(I) = transmat * src(I) + shiftvec - */ -VALUE -rb_transform(int argc, VALUE *argv, VALUE self) -{ - VALUE transmat, shiftvec; - rb_scan_args(argc, argv, "11", &transmat, &shiftvec); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvTransform(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(transmat), - NIL_P(shiftvec) ? NULL : CVMAT_WITH_CHECK(shiftvec)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * perspective_transform(mat) -> cvmat - * - * Return performed perspective matrix transform of vector array. - * mat should be 3x3 or 4x4 transform matrix (CvMat). - * Every element (by treating it as 2D or 3D vector) in the following way: - * (x, y, z) -> (x'/w, y'/w, z'/w) or - * (x, y) -> (x'/w, y'/w) - * where - * (x', y', z', w') = mat4x4*(x, y, z, 1) or - * (x', y', w') = mat3x3*(x, y, 1) - * and - * w = w' if w'!=0, inf otherwise. - */ -VALUE -rb_perspective_transform(VALUE self, VALUE mat) -{ - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvPerspectiveTransform(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(mat)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * mul_transposed(:order => 0 or 1, :delta => cvmat, :scale => number) - * - * Calculates the product of self and its transposition. - * - * options - * * :order -> should be 0 or 1 (default is 0) - * see below. - * * :delta -> should be CvMat (default is nil) - * An optional array, subtracted from source before multiplication. - * * :scale -> should be a number (default is 1.0) - * An optional scaling - * - * mul_transposed evaluates: - * :order => 0 - * dst = scale * (self - delta) * (self - delta)T - * :order => 1 - * dst = scale * (self - delta)T * (self - delta) - * - */ -VALUE -rb_mul_transposed(int argc, VALUE *argv, VALUE self) -{ - VALUE options = Qnil; - VALUE _delta = Qnil, _scale = Qnil, _order = Qnil; - - if (rb_scan_args(argc, argv, "01", &options) > 0) { - Check_Type(options, T_HASH); - _delta = LOOKUP_HASH(options, "delta"); - _scale = LOOKUP_HASH(options, "scale"); - _order = LOOKUP_HASH(options, "order"); - } - - CvArr* delta = NIL_P(_delta) ? NULL : CVARR_WITH_CHECK(_delta); - double scale = NIL_P(_scale) ? 1.0 : NUM2DBL(_scale); - int order = NIL_P(_order) ? 0 : NUM2INT(_order); - CvArr* self_ptr = CVARR(self); - VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); - try { - cvMulTransposed(self_ptr, CVARR(dest), order, delta, scale); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dest; -} - - -/* - * call-seq: - * trace -> scalar - * - * Returns trace of matrix. "trace" is sum of diagonal elements of the matrix. - */ -VALUE -rb_trace(VALUE self) -{ - CvScalar scalar; - try { - scalar = cvTrace(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvScalar::new_object(scalar); -} - -/* - * call-seq: - * transpose -> cvmat - * - * Return transposed matrix. - */ -VALUE -rb_transpose(VALUE self) -{ - CvMat* self_ptr = CVMAT(self); - VALUE dest = new_mat_kind_object(cvSize(self_ptr->rows, self_ptr->cols), self); - try { - cvTranspose(self_ptr, CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * det -> float - * - * Return determinant of matrix. - * self should be single-channel and floating-point depth. - */ -VALUE -rb_det(VALUE self) -{ - double det = 0.0; - try { - det = cvDet(CVARR(self)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_float_new(det); -} - -/* - * call-seq: - * invert(inversion_method=:lu[,delta]) -> float - * - * Finds inverse or pseudo-inverse of matrix. - * inversion_method should be following symbol. - * * :lu - * Gaussian elimincation with optimal pivot element chose. - * Return self determinant (self must be square). - * * :svd - * Singular value decomposition(SVD) method. - * Return the inversed condition number of self(ratio of the smallest singular value to the largest singular value) - * and 0 if self is all zeros. The SVD method calculate a pseudo-inverse matrix if self is singular. - * * :svd_sym or :svd_symmetric - * SVD method for a symmetric positively-defined matrix. - * - * self type should be single-channel and floating-point matrix. - */ -VALUE -rb_invert(int argc, VALUE *argv, VALUE self) -{ - VALUE symbol; - rb_scan_args(argc, argv, "01", &symbol); - int method = CVMETHOD("INVERSION_METHOD", symbol, CV_LU); - VALUE dest = Qnil; - CvArr* self_ptr = CVARR(self); - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvInvert(self_ptr, CVARR(dest), method); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * solve(src1, src2, inversion_method=:lu) - * - * Solves linear system or least-squares problem (the latter is possible with SVD method). - * - * inversion_method should be following symbol. - * * :lu - * Gaussian elimincation with optimal pivot element chose. - * Return self determinant (self must be square). - * * :svd - * Singular value decomposition(SVD) method. - * Return the inversed condition number of self(ratio of the smallest singular value to the largest singular value) - * and 0 if self is all zeros. The SVD method calculate a pseudo-inverse matrix if self is singular. - * * :svd_sym or :svd_symmetric - * SVD method for a symmetric positively-defined matrix. - */ -VALUE -rb_solve(int argc, VALUE *argv, VALUE self) -{ - VALUE src1, src2, symbol; - rb_scan_args(argc, argv, "21", &src1, &src2, &symbol); - VALUE dest = Qnil; - CvArr* src2_ptr = CVARR_WITH_CHECK(src2); - try { - dest = new_mat_kind_object(cvGetSize(src2_ptr), src2); - cvSolve(CVARR_WITH_CHECK(src1), src2_ptr, CVARR(dest), CVMETHOD("INVERSION_METHOD", symbol, CV_LU)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * svd(l[flag=0]) - * - * Performs singular value decomposition of real floating-point matrix. - */ -VALUE -rb_svd(int argc, VALUE *argv, VALUE self) -{ - VALUE _flag = Qnil; - int flag = 0; - if (rb_scan_args(argc, argv, "01", &_flag) > 0) { - flag = NUM2INT(_flag); - } - - CvMat* self_ptr = CVMAT(self); - VALUE w = new_mat_kind_object(cvSize(self_ptr->cols, self_ptr->rows), self); - - int rows = 0; - int cols = 0; - if (flag & CV_SVD_U_T) { - rows = MIN(self_ptr->rows, self_ptr->cols); - cols = self_ptr->rows; - } - else { - rows = self_ptr->rows; - cols = MIN(self_ptr->rows, self_ptr->cols); - } - VALUE u = new_mat_kind_object(cvSize(cols, rows), self); - - if (flag & CV_SVD_V_T) { - rows = MIN(self_ptr->rows, self_ptr->cols); - cols = self_ptr->cols; - } - else { - rows = self_ptr->cols; - cols = MIN(self_ptr->rows, self_ptr->cols); - } - VALUE v = new_mat_kind_object(cvSize(cols, rows), self); - - cvSVD(self_ptr, CVARR(w), CVARR(u), CVARR(v), flag); - - return rb_ary_new3(3, w, u, v); -} - -/* - * call-seq: - * eigenvv!([eps = 0.0]) -> [eigen_vectors(cvmat), eigen_values(cvmat)] - * - * Computes eigenvalues and eigenvectors of symmetric matrix. - * self should be symmetric square matrix. self is modified during the processing. - * - * self * eigen_vectors(i,:)' = eigen_values(i) * eigen_vectors(i,:)' - * - * Currently the function is slower than #svd yet less accurate, so if self is known to be positively-defined - * (e.g., it is a convariation matrix), it is recommanded to use #svd to find eigenvalues and eigenvectors of self, - * especially if eigenvectors are not required. - */ -VALUE -rb_eigenvv(int argc, VALUE *argv, VALUE self) -{ - VALUE epsilon, lowindex, highindex; - rb_scan_args(argc, argv, "03", &epsilon, &lowindex, &highindex); - double eps = (NIL_P(epsilon)) ? 0.0 : NUM2DBL(epsilon); - int lowidx = (NIL_P(lowindex)) ? -1 : NUM2INT(lowindex); - int highidx = (NIL_P(highindex)) ? -1 : NUM2INT(highindex); - VALUE eigen_vectors = Qnil, eigen_values = Qnil; - CvArr* self_ptr = CVARR(self); - try { - CvSize size = cvGetSize(self_ptr); - int type = cvGetElemType(self_ptr); - eigen_vectors = new_object(size, type); - eigen_values = new_object(size.height, 1, type); - cvEigenVV(self_ptr, CVARR(eigen_vectors), CVARR(eigen_values), eps, lowidx, highidx); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, eigen_vectors, eigen_values); -} - - -/* - * call-seq: - * dft(flags = CV_DXT_FORWARD, nonzero_rows = 0) -> cvmat - * - * Performs forward or inverse Discrete Fourier Transform(DFT) of 1D or 2D floating-point array. - * - * Params: - * * flags - transformation flags - * * nonzero_rows - when the parameter is not zero, the function assumes that only - * the first nonzero_rows rows of the input array (CV_DXT_INVERSE is not set) - * or only the first nonzero_rows of the output array (CV_DXT_INVERSE is set) contain non-zeros. - */ -VALUE -rb_dft(int argc, VALUE *argv, VALUE self) -{ - VALUE flag_value, nonzero_row_value; - rb_scan_args(argc, argv, "02", &flag_value, &nonzero_row_value); - - int flags = NIL_P(flag_value) ? CV_DXT_FORWARD : NUM2INT(flag_value); - int nonzero_rows = NIL_P(nonzero_row_value) ? 0 : NUM2INT(nonzero_row_value); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvDFT(self_ptr, CVARR(dest), flags, nonzero_rows); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * dct(flags = CV_DXT_FORWARD) -> cvmat - * - * Performs forward or inverse Discrete Cosine Transform(DCT) of 1D or 2D floating-point array. - * - * Params: - * * flags - transformation flags - */ -VALUE -rb_dct(int argc, VALUE *argv, VALUE self) -{ - VALUE flag_value; - rb_scan_args(argc, argv, "01", &flag_value); - - int flags = NIL_P(flag_value) ? CV_DXT_FORWARD : NUM2INT(flag_value); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvDCT(self_ptr, CVARR(dest), flags); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * line(p1, p2[, drawing_option]) -> mat - * - * Return image is drawn a line segment connecting two points. - * - * drawing_option should be Hash include these keys. - * :color - * Line color. - * :thickness - * Line Thickness. - * :line_type - * Type of the line: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the point coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - * - * for example - * mat = CvMat.new(100, 100) - * mat.line(CvPoint.new(10, 10), CvPoint.new(90, 90), :thickness => 3, :line_type => :aa) - */ -VALUE -rb_line(int argc, VALUE *argv, VALUE self) -{ - return rb_line_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * line!(p1, p2[, drawing_option]) -> self - * - * Draws a line segment connecting two points. - * Same as CvMat#line, but modifies the receiver in place. - * see CvMat#line - */ -VALUE -rb_line_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, drawing_option; - rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option); - drawing_option = DRAWING_OPTION(drawing_option); - try { - cvLine(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * rectangle(p1, p2[, drawing_option]) -> mat - * - * Return image is drawn a rectangle with two opposite corners p1 and p2. - * - * drawing_options should be Hash include these keys. - * :color - * Line color. - * :thickness - * Thickness of lines that make up the rectangle. - * Negative values make the function to draw a filled rectangle. - * :line_type - * Type of the line: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the point coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_rectangle(int argc, VALUE *argv, VALUE self) -{ - return rb_rectangle_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * rectangle!(p1, p2[, drawing_option]) -> self - * - * Draws simple, thick or filled rectangle. - * Same as CvMat#rectangle, but modifies the receiver in place. - * see CvMat#rectangle - */ -VALUE -rb_rectangle_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, drawing_option; - rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option); - drawing_option = DRAWING_OPTION(drawing_option); - try { - cvRectangle(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * circle(center, radius[,drawing_option]) -> cvmat - * - * Return image is drawn a simple or filled circle with given center and radius. - * - * drawing_options should be Hash include these keys. - * :color - * Circle color. - * :thickness - * Thickness of the circle outline if positive, otherwise that a filled circle has to be drawn. - * :line_type - * Type of the circle boundary: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the center coordinates and radius value. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_circle(int argc, VALUE *argv, VALUE self) -{ - return rb_circle_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * circle!(center, radius[,drawing_option]) -> cvmat - * - * Draw a circle. - * Same as CvMat#circle, but modifies the receiver in place. - * - * see CvMat#circle - */ -VALUE -rb_circle_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE center, radius, drawing_option; - rb_scan_args(argc, argv, "21", ¢er, &radius, &drawing_option); - drawing_option = DRAWING_OPTION(drawing_option); - try { - cvCircle(CVARR(self), VALUE_TO_CVPOINT(center), NUM2INT(radius), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * ellipse(center, axis, angle, start_angle, end_angle[,drawing_option]) -> mat - * - * Return image is drawn a simple or thick elliptic arc or fills an ellipse sector. - * - * drawing_options should be Hash include these keys. - * :color - * Ellipse color. - * :thickness - * Thickness of the ellipse arc. - * :line_type - * Type of the ellipse boundary: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the center coordinates and axes' value. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_ellipse(int argc, VALUE *argv, VALUE self) -{ - return rb_ellipse_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * ellipse!(center, axis, angle, start_angle, end_angle[,drawing_option]) -> self - * - * Draws simple or thick elliptic arc or fills ellipse sector. - * Same as CvMat#ellipse, but modifies the receiver in place. - * - * see CvMat#ellipse - */ -VALUE -rb_ellipse_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE center, axis, angle, start_angle, end_angle, drawing_option; - rb_scan_args(argc, argv, "51", ¢er, &axis, &angle, &start_angle, &end_angle, &drawing_option); - drawing_option = DRAWING_OPTION(drawing_option); - try { - cvEllipse(CVARR(self), VALUE_TO_CVPOINT(center), - VALUE_TO_CVSIZE(axis), - NUM2DBL(angle), NUM2DBL(start_angle), NUM2DBL(end_angle), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * ellipse_box(box[, drawing_option]) -> mat - * - * Return image is drawn a simple or thick ellipse outline, or fills an ellipse. - * The method provides a convenient way to draw an ellipse approximating some shape. - * - * drawing_options should be Hash include these keys. - * :color - * Ellipse color. - * :thickness - * Thickness of the ellipse drawn. - * :line_type - * Type of the ellipse boundary: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the box vertex coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_ellipse_box(int argc, VALUE *argv, VALUE self) -{ - return rb_ellipse_box_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * ellipse_box!(box[, drawing_option]) -> self - * - * Draws simple or thick elliptic arc or fills ellipse sector. - * Same as CvMat#ellipse_box, but modifies the receiver in place. - * - * see CvMat#ellipse_box - */ -VALUE -rb_ellipse_box_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE box, drawing_option; - rb_scan_args(argc, argv, "11", &box, &drawing_option); - drawing_option = DRAWING_OPTION(drawing_option); - try { - cvEllipseBox(CVARR(self), VALUE_TO_CVBOX2D(box), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * fill_poly(points[,drawing_option]) -> mat - * - * Return image is filled an area bounded by several polygonal contours. - * The method fills complex areas, for example, areas with holes, contour self-intersection, etc. - */ -VALUE -rb_fill_poly(int argc, VALUE *argv, VALUE self) -{ - return rb_fill_poly_bang(argc, argv, self); -} - -/* - * call-seq: - * fill_poly!(points[,drawing_option]) -> self - * - * Fills polygons interior. - * Same as CvMat#fill_poly, but modifies the receiver in place. - * - * drawing_options should be Hash include these keys. - * :color - * Polygon color. - * :line_type - * Type of the polygon boundaries: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the vertex coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_fill_poly_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE polygons, drawing_option; - VALUE points; - int i, j; - int num_polygons; - int *num_points; - CvPoint **p; - - rb_scan_args(argc, argv, "11", &polygons, &drawing_option); - Check_Type(polygons, T_ARRAY); - drawing_option = DRAWING_OPTION(drawing_option); - num_polygons = RARRAY_LEN(polygons); - num_points = ALLOCA_N(int, num_polygons); - - p = ALLOCA_N(CvPoint*, num_polygons); - for (j = 0; j < num_polygons; ++j) { - points = rb_ary_entry(polygons, j); - Check_Type(points, T_ARRAY); - num_points[j] = RARRAY_LEN(points); - p[j] = ALLOCA_N(CvPoint, num_points[j]); - for (i = 0; i < num_points[j]; ++i) { - p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); - } - } - try { - cvFillPoly(CVARR(self), p, num_points, num_polygons, - DO_COLOR(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * fill_convex_poly(points[,drawing_option]) -> mat - * - * Return image is filled convex polygon interior. - * This method is much faster than The function CvMat#fill_poly - * and can fill not only the convex polygons but any monotonic polygon, - * i.e. a polygon whose contour intersects every horizontal line (scan line) - * twice at the most. - * - * drawing_options should be Hash include these keys. - * :color - * Polygon color. - * :line_type - * Type of the polygon boundaries: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the vertex coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_fill_convex_poly(int argc, VALUE *argv, VALUE self) -{ - return rb_fill_convex_poly_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * fill_convex_poly!(points[,drawing_option]) -> self - * - * Fills convex polygon. - * Same as CvMat#fill_convex_poly, but modifies the receiver in place. - * - * see CvMat#fill_convex_poly - */ -VALUE -rb_fill_convex_poly_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE points, drawing_option; - int i, num_points; - CvPoint *p; - - rb_scan_args(argc, argv, "11", &points, &drawing_option); - Check_Type(points, T_ARRAY); - drawing_option = DRAWING_OPTION(drawing_option); - num_points = RARRAY_LEN(points); - p = ALLOCA_N(CvPoint, num_points); - for (i = 0; i < num_points; ++i) - p[i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); - - try { - cvFillConvexPoly(CVARR(self), p, num_points, - DO_COLOR(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * poly_line(points[,drawing_option]) -> mat - * - * Return image drawed a single or multiple polygonal curves. - * - * drawing_option should be Hash include these keys. - * :is_closed - * Indicates whether the polylines must be drawn closed. - * If closed, the method draws the line from the last vertex - * of every contour to the first vertex. - * :color - * Polyline color. - * :thickness - * Thickness of the polyline edges - * :line_type - * Type of line segments: - * * 0 or 8 - 8-connected line(default). - * * 4 - 4-connected line. - * * negative-value - antialiased line. - * :shift - * Number of fractional bits in the vertex coordinates. - * - * note: drawing_option's default value is CvMat::DRAWING_OPTION. - */ -VALUE -rb_poly_line(int argc, VALUE *argv, VALUE self) -{ - return rb_poly_line_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * poly_line!(points[,drawing_option]) -> self - * - * Draws simple or thick polygons. - * - * Same as CvMat#poly_line, but modifies the receiver in place. - * - * see CvMat#poly_line - */ -VALUE -rb_poly_line_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE polygons, drawing_option; - VALUE points; - int i, j; - int num_polygons; - int *num_points; - CvPoint **p; - - rb_scan_args(argc, argv, "11", &polygons, &drawing_option); - Check_Type(polygons, T_ARRAY); - drawing_option = DRAWING_OPTION(drawing_option); - num_polygons = RARRAY_LEN(polygons); - num_points = ALLOCA_N(int, num_polygons); - p = ALLOCA_N(CvPoint*, num_polygons); - - for (j = 0; j < num_polygons; ++j) { - points = rb_ary_entry(polygons, j); - Check_Type(points, T_ARRAY); - num_points[j] = RARRAY_LEN(points); - p[j] = ALLOCA_N(CvPoint, num_points[j]); - for (i = 0; i < num_points[j]; ++i) { - p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i)); - } - } - - try { - cvPolyLine(CVARR(self), p, num_points, num_polygons, - DO_IS_CLOSED(drawing_option), - DO_COLOR(drawing_option), - DO_THICKNESS(drawing_option), - DO_LINE_TYPE(drawing_option), - DO_SHIFT(drawing_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return self; -} - - -/* - * call-seq: - * put_text(str, point, font[,color]) -> cvmat - * - * Return image is drawn text string. - * font should be CvFont object. - */ -VALUE -rb_put_text(int argc, VALUE* argv, VALUE self) -{ - return rb_put_text_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * put_text!(str, point, font[,color]) -> self - * - * Draws text string. Return self. - */ -VALUE -rb_put_text_bang(int argc, VALUE* argv, VALUE self) -{ - VALUE _text, _point, _font, _color; - rb_scan_args(argc, argv, "31", &_text, &_point, &_font, &_color); - CvScalar color = NIL_P(_color) ? CV_RGB(0, 0, 0) : VALUE_TO_CVSCALAR(_color); - try { - cvPutText(CVARR(self), StringValueCStr(_text), VALUE_TO_CVPOINT(_point), - CVFONT_WITH_CHECK(_font), color); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * sobel(xorder,yorder[,aperture_size=3]) -> cvmat - * - * Calculates first, second, third or mixed image derivatives using extended Sobel operator. - * self should be single-channel 8bit unsigned or 32bit floating-point. - * - * link:../images/CvMat_sobel.png - */ -VALUE -rb_sobel(int argc, VALUE *argv, VALUE self) -{ - VALUE xorder, yorder, aperture_size, dest; - if (rb_scan_args(argc, argv, "21", &xorder, &yorder, &aperture_size) < 3) - aperture_size = INT2FIX(3); - CvMat* self_ptr = CVMAT(self); - switch(CV_MAT_DEPTH(self_ptr->type)) { - case CV_8U: - dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_16S, 1); - break; - case CV_32F: - dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_32F, 1); - break; - default: - rb_raise(rb_eArgError, "source depth should be CV_8U or CV_32F."); - break; - } - - try { - cvSobel(self_ptr, CVARR(dest), NUM2INT(xorder), NUM2INT(yorder), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * laplace([aperture_size = 3]) -> cvmat - * - * Calculates Laplacian of the image. - * self should be single-channel 8bit unsigned or 32bit floating-point. - */ -VALUE -rb_laplace(int argc, VALUE *argv, VALUE self) -{ - VALUE aperture_size, dest; - if (rb_scan_args(argc, argv, "01", &aperture_size) < 1) - aperture_size = INT2FIX(3); - CvMat* self_ptr = CVMAT(self); - switch(CV_MAT_DEPTH(self_ptr->type)) { - case CV_8U: - dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_16S, 1); - break; - case CV_32F: - dest = new_mat_kind_object(cvGetSize(self_ptr), self, CV_32F, 1); - break; - default: - rb_raise(rb_eArgError, "source depth should be CV_8U or CV_32F."); - } - - try { - cvLaplace(self_ptr, CVARR(dest), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * canny(thresh1,thresh2[,aperture_size = 3]) -> cvmat - * - * Canny algorithm for edge detection. - */ -VALUE -rb_canny(int argc, VALUE *argv, VALUE self) -{ - VALUE thresh1, thresh2, aperture_size; - if (rb_scan_args(argc, argv, "21", &thresh1, &thresh2, &aperture_size) < 3) - aperture_size = INT2FIX(3); - CvArr* self_ptr = CVARR(self); - VALUE dest = new_mat_kind_object(cvGetSize(self_ptr), self); - - try { - cvCanny(self_ptr, CVARR(dest), NUM2INT(thresh1), NUM2INT(thresh2), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * pre_corner_detect([aperture_size = 3]) -> cvmat - * - * Calculates feature map for corner detection. - * aperture_size is parameter for sobel operator(see #sobel). - * - * The corners can be found as local maximums of the function. - */ -VALUE -rb_pre_corner_detect(int argc, VALUE *argv, VALUE self) -{ - VALUE aperture_size, dest = Qnil; - if (rb_scan_args(argc, argv, "01", &aperture_size) < 1) - aperture_size = INT2FIX(3); - - CvArr *self_ptr = CVARR(self); - try { - dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); - cvPreCornerDetect(self_ptr, CVARR(dest), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * corner_eigenvv(block_size[,aperture_size]) -> cvmat - * - * For every pixel considers block_size x block_size neighborhood S(p). - * It calculates convariation matrix of derivatives over the neighborhood. - */ -VALUE -rb_corner_eigenvv(int argc, VALUE *argv, VALUE self) -{ - VALUE block_size, aperture_size, dest; - if (rb_scan_args(argc, argv, "11", &block_size, &aperture_size) < 2) - aperture_size = INT2FIX(3); - CvMat* self_ptr = CVMAT(self); - dest = new_object(cvSize(self_ptr->cols * 6, self_ptr->rows), CV_MAKETYPE(CV_32F, 1)); - try { - cvCornerEigenValsAndVecs(self_ptr, CVARR(dest), NUM2INT(block_size), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * corner_min_eigen_val(block_size[,aperture_size = 3]) -> cvmat - * - * Calculates minimal eigenvalue of gradient matrices for corner detection. - */ -VALUE -rb_corner_min_eigen_val(int argc, VALUE *argv, VALUE self) -{ - VALUE block_size, aperture_size, dest; - if (rb_scan_args(argc, argv, "11", &block_size, &aperture_size) < 2) - aperture_size = INT2FIX(3); - CvArr* self_ptr = CVARR(self); - dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); - try { - cvCornerMinEigenVal(self_ptr, CVARR(dest), NUM2INT(block_size), NUM2INT(aperture_size)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * corner_harris(block_size[,aperture_size = 3][,k = 0.04]) -> cvmat - * - * Return image Applied Harris edge detector. - */ -VALUE -rb_corner_harris(int argc, VALUE *argv, VALUE self) -{ - VALUE block_size, aperture_size, k, dest; - rb_scan_args(argc, argv, "12", &block_size, &aperture_size, &k); - CvArr* self_ptr = CVARR(self); - dest = new_object(cvGetSize(self_ptr), CV_MAKETYPE(CV_32F, 1)); - try { - cvCornerHarris(self_ptr, CVARR(dest), NUM2INT(block_size), IF_INT(aperture_size, 3), IF_DBL(k, 0.04)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * find_chessboard_corners(pattern_size, flag = CV_CALIB_CB_ADAPTIVE_THRESH) -> Array, Boolean> - * - * Returns an array which includes the positions of internal corners of the chessboard, and - * a parameter indicating whether the complete board was found or not. - * - * pattern_size (CvSize) - Number of inner corners per a chessboard row and column. - * flags (Integer) - Various operation flags that can be zero or a combination of the following values - * * CV_CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image to black and white, - * rather than a fixed threshold level (computed from the average image brightness). - * * CV_CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with CvMat#equalize_hist() before applying fixed - * or adaptive thresholding. - * * CV_CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter, square-like shape) - * to filter out false quads extracted at the contour retrieval stage. - * * CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard corners, and shortcut - * the call if none is found. This can drastically speed up the call in the degenerate condition - * when no chessboard is observed. - */ -VALUE -rb_find_chessboard_corners(int argc, VALUE *argv, VALUE self) -{ - VALUE pattern_size_val, flag_val; - rb_scan_args(argc, argv, "11", &pattern_size_val, &flag_val); - - int flag = NIL_P(flag_val) ? CV_CALIB_CB_ADAPTIVE_THRESH : NUM2INT(flag_val); - CvSize pattern_size = VALUE_TO_CVSIZE(pattern_size_val); - CvPoint2D32f* corners = ALLOCA_N(CvPoint2D32f, pattern_size.width * pattern_size.height); - int num_found_corners = 0; - int pattern_was_found = 0; - try { - pattern_was_found = cvFindChessboardCorners(CVARR(self), pattern_size, corners, &num_found_corners, flag); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - VALUE found_corners = rb_ary_new2(num_found_corners); - for (int i = 0; i < num_found_corners; i++) { - rb_ary_store(found_corners, i, cCvPoint2D32f::new_object(corners[i])); - } - - VALUE found = (pattern_was_found > 0) ? Qtrue : Qfalse; - return rb_assoc_new(found_corners, found); -} - -/* - * call-seq: - * find_corner_sub_pix(corners, win_size, zero_zone, criteria) -> Array - * - * Returns refined corner locations. - * - * corners - Initial coordinates of the input corners and refined coordinates provided for output. - * win_size - Half of the side length of the search window. - * zero_zone - Half of the size of the dead region in the middle of the search zone over - * which the summation in the formula below is not done. - * criteria - Criteria for termination of the iterative process of corner refinement. - */ -VALUE -rb_find_corner_sub_pix(VALUE self, VALUE corners, VALUE win_size, VALUE zero_zone, VALUE criteria) -{ - Check_Type(corners, T_ARRAY); - int count = RARRAY_LEN(corners); - CvPoint2D32f* corners_buff = ALLOCA_N(CvPoint2D32f, count); - VALUE* corners_ptr = RARRAY_PTR(corners); - - for (int i = 0; i < count; i++) { - corners_buff[i] = *(CVPOINT2D32F(corners_ptr[i])); - } - - try { - cvFindCornerSubPix(CVARR(self), corners_buff, count, VALUE_TO_CVSIZE(win_size), - VALUE_TO_CVSIZE(zero_zone), VALUE_TO_CVTERMCRITERIA(criteria)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - VALUE refined_corners = rb_ary_new2(count); - for (int i = 0; i < count; i++) { - rb_ary_store(refined_corners, i, cCvPoint2D32f::new_object(corners_buff[i])); - } - - return refined_corners; -} - -/* - * call-seq: - * good_features_to_track(quality_level, min_distance[, good_features_to_track_option]) - * -> array (include CvPoint2D32f) - * Determines strong corners on an image. - * - * quality_level – Multiplier for the max/min eigenvalue; specifies the minimal accepted quality of image corners - * min_distance – Limit, specifying the minimum possible distance between the returned corners; Euclidian distance is used - * good_features_to_track_option should be Hash include these keys. - * :mask - * Region of interest. The function selects points either in the specified region or in the whole image - * if the mask is nil. - * :block_size - * Size of the averaging block, passed to the underlying CornerMinEigenVal or CornerHarris used by the function. - * :use_harris - * If true, Harris operator ( CornerHarris ) is used instead of default CornerMinEigenVal - * :k - * Free parameter of Harris detector; used only if ( :use_harris => true ) - * note: good_features_to_track_option's default value is CvMat::GOOD_FEATURES_TO_TRACK_OPTION - */ -VALUE -rb_good_features_to_track(int argc, VALUE *argv, VALUE self) -{ - VALUE quality_level, min_distance, good_features_to_track_option; - rb_scan_args(argc, argv, "21", &quality_level, &min_distance, &good_features_to_track_option); - good_features_to_track_option = GOOD_FEATURES_TO_TRACK_OPTION(good_features_to_track_option); - int np = GF_MAX(good_features_to_track_option); - if (np <= 0) - rb_raise(rb_eArgError, "option :max should be positive value."); - - CvMat *self_ptr = CVMAT(self); - CvPoint2D32f *p32 = (CvPoint2D32f*)rb_cvAlloc(sizeof(CvPoint2D32f) * np); - int type = CV_MAKETYPE(CV_32F, 1); - CvMat* eigen = rb_cvCreateMat(self_ptr->rows, self_ptr->cols, type); - CvMat* tmp = rb_cvCreateMat(self_ptr->rows, self_ptr->cols, type); - try { - cvGoodFeaturesToTrack(self_ptr, &eigen, &tmp, p32, &np, NUM2DBL(quality_level), NUM2DBL(min_distance), - GF_MASK(good_features_to_track_option), - GF_BLOCK_SIZE(good_features_to_track_option), - GF_USE_HARRIS(good_features_to_track_option), - GF_K(good_features_to_track_option)); - } - catch (cv::Exception& e) { - if (eigen != NULL) - cvReleaseMat(&eigen); - if (tmp != NULL) - cvReleaseMat(&tmp); - if (p32 != NULL) - cvFree(&p32); - raise_cverror(e); - } - VALUE corners = rb_ary_new2(np); - for (int i = 0; i < np; ++i) - rb_ary_store(corners, i, cCvPoint2D32f::new_object(p32[i])); - cvFree(&p32); - cvReleaseMat(&eigen); - cvReleaseMat(&tmp); - return corners; -} - - -/* - * call-seq: - * rect_sub_pix(center[, size = self.size]) -> cvmat - * - * Retrieves pixel rectangle from image with sub-pixel accuracy. - * Extracts pixels from self. - * dst(x,y) = self(x + center.x - (size.width - 1) * 0.5, y + center.y - (size.height - 1) * 0.5) - * where the values of pixels at non-integer coordinates are retrived using bilinear iterpolation. - * Every channel of multiple-channel images is processed independently. - * Whereas the rectangle center must be inside the image, the whole rectangle may be partially occludedl. - * In this case, the replication border mode is used to get pixel values beyond the image boundaries. - */ -VALUE -rb_rect_sub_pix(int argc, VALUE *argv, VALUE self) -{ - VALUE center, size; - VALUE dest = Qnil; - CvSize _size; - CvArr* self_ptr = CVARR(self); - try { - if (rb_scan_args(argc, argv, "11", ¢er, &size) < 2) - _size = cvGetSize(self_ptr); - else - _size = VALUE_TO_CVSIZE(size); - dest = new_mat_kind_object(_size, self); - cvGetRectSubPix(self_ptr, CVARR(dest), VALUE_TO_CVPOINT2D32F(center)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * quandrangle_sub_pix(map_matrix[, size = self.size]) -> cvmat - * - * Retrives pixel quadrangle from image with sub-pixel accuracy. - * Extracts pixel from self at sub-pixel accuracy and store them: - */ -VALUE -rb_quadrangle_sub_pix(int argc, VALUE *argv, VALUE self) -{ - VALUE map_matrix, size; - VALUE dest = Qnil; - CvSize _size; - CvArr* self_ptr = CVARR(self); - try { - if (rb_scan_args(argc, argv, "11", &map_matrix, &size) < 2) - _size = cvGetSize(self_ptr); - else - _size = VALUE_TO_CVSIZE(size); - dest = new_mat_kind_object(_size, self); - cvGetQuadrangleSubPix(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * resize(size[,interpolation = :linear]) -> cvmat - * - * Resize image. - * interpolation is interpolation method: - * * CV_INTER_NN - * nearest-neighbor interpolation. - * * CV_INTER_LINEAR - * bilinear interpolation (used by default) - * * CV_INTER_AREA - * resampling using pixel area relation. It is preferred method for image decimation that give moire-free results. - * In case of zooming it is similar to NN method. - * * CV_INTER_CUBIC - * bicubic interpolation. - * Return self resized image that it fits exactly to size. If ROI is set, the method consideres the ROI as supported as usual. - */ -VALUE -rb_resize(int argc, VALUE *argv, VALUE self) -{ - VALUE size, interpolation; - rb_scan_args(argc, argv, "11", &size, &interpolation); - VALUE dest = new_mat_kind_object(VALUE_TO_CVSIZE(size), self); - int method = NIL_P(interpolation) ? CV_INTER_LINEAR : NUM2INT(interpolation); - - try { - cvResize(CVARR(self), CVARR(dest), method); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * warp_affine(map_matrix[,flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS][,fillval = 0]) -> cvmat - * - * Applies affine transformation to the image. - */ -VALUE -rb_warp_affine(int argc, VALUE *argv, VALUE self) -{ - VALUE map_matrix, flags_val, fill_value; - VALUE dest = Qnil; - if (rb_scan_args(argc, argv, "12", &map_matrix, &flags_val, &fill_value) < 3) - fill_value = INT2FIX(0); - CvArr* self_ptr = CVARR(self); - int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvWarpAffine(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix), - flags, VALUE_TO_CVSCALAR(fill_value)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - - -/* - * call-seq: - * CvMat.find_homograpy(src_points, dst_points[,method = :all][,ransac_reproj_threshold = 0][,get_status = nil]) -> cvmat - * - * Finds the perspective transformation between two planes. - * src_points: 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. - * dst_points: Point coordinates in the destination plane, 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 2- or 3-channel array. - * method: 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 - * ransac_reproj_threshold: 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. - * get_status 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_WITH_CHECK(src_points); - int num_points = MAX(src->rows, src->cols); - VALUE status = new_object(cvSize(num_points, 1), CV_8UC1); - try { - cvFindHomography(src, CVMAT_WITH_CHECK(dst_points), CVMAT(homography), - _method, _ransac_reproj_threshold, CVMAT(status)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_assoc_new(homography, status); - } - else { - try { - cvFindHomography(CVMAT(src_points), CVMAT(dst_points), CVMAT(homography), - _method, _ransac_reproj_threshold, NULL); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return homography; - } -} - -/* - * call-seq: - * CvMat.rotation_matrix2D(center,angle,scale) -> cvmat - * - * Create new affine matrix of 2D rotation (2x3 32bit floating-point matrix). - * center is center of rotation (x, y). - * angle is rotation angle in degrees. - * Positive values mean counter-clockwise rotation - * (the coordinate origin is assumed at top-left corner). - * scale is isotropic scale factor. - * - * [ a b | (1 - a) * center.x - b * center.y ] - * [-b a | (b * center.x + (1 + a) * center.y ] - * where a = scale * cos(angle), b = scale * sin(angle) - */ -VALUE -rb_rotation_matrix2D(VALUE self, VALUE center, VALUE angle, VALUE scale) -{ - VALUE map_matrix = new_object(cvSize(3, 2), CV_MAKETYPE(CV_32F, 1)); - try { - cv2DRotationMatrix(VALUE_TO_CVPOINT2D32F(center), NUM2DBL(angle), NUM2DBL(scale), CVMAT(map_matrix)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return map_matrix; -} - -/* - * call-seq: - * CvMat.get_perspective_transform(from_points,to_points) -> cvmat - * - * Calculates a perspective transform from four pairs of the corresponding points. - * Returns a matrix suitable for use with warp_perspective - */ -VALUE -rb_get_perspective_transform(VALUE self, VALUE source, VALUE dest) -{ - Check_Type(source, T_ARRAY); - Check_Type(dest, T_ARRAY); - - int count = RARRAY_LEN(source); - - CvPoint2D32f* source_buff = ALLOCA_N(CvPoint2D32f, count); - CvPoint2D32f* dest_buff = ALLOCA_N(CvPoint2D32f, count); - - for (int i = 0; i < count; i++) { - source_buff[i] = *(CVPOINT2D32F(RARRAY_PTR(source)[i])); - dest_buff[i] = *(CVPOINT2D32F(RARRAY_PTR(dest)[i])); - } - - VALUE map_matrix = new_object(cvSize(3, 3), CV_MAKETYPE(CV_32F, 1)); - - try { - cvGetPerspectiveTransform(source_buff, dest_buff, CVMAT(map_matrix)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return map_matrix; -} - -/* - * call-seq: - * warp_perspective(map_matrix[,flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS][,fillval=0])) -> cvmat - * - * Applies perspective transformation to the image. - */ -VALUE -rb_warp_perspective(int argc, VALUE *argv, VALUE self) -{ - VALUE map_matrix, flags_val, option, fillval; - if (rb_scan_args(argc, argv, "13", &map_matrix, &flags_val, &option, &fillval) < 4) - fillval = INT2FIX(0); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvWarpPerspective(self_ptr, CVARR(dest), CVMAT_WITH_CHECK(map_matrix), - flags, VALUE_TO_CVSCALAR(fillval)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * remap(mapx,mapy[,flags = CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS][,fillval=0]) -> cvmat - * - * Applies generic geometrical transformation to the image. - * Transforms source image using the specified map: - * dst(x,y)<-src(mapx(x,y),mapy(x,y)) - * Similar to other geometrical transformations, some interpolation method (specified by user) is used to - * extract pixels with non-integer coordinates. - */ -VALUE -rb_remap(int argc, VALUE *argv, VALUE self) -{ - VALUE mapx, mapy, flags_val, option, fillval; - if (rb_scan_args(argc, argv, "23", &mapx, &mapy, &flags_val, &option, &fillval) < 5) - fillval = INT2FIX(0); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - int flags = NIL_P(flags_val) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags_val); - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvRemap(self_ptr, CVARR(dest), CVARR_WITH_CHECK(mapx), CVARR_WITH_CHECK(mapy), - flags, VALUE_TO_CVSCALAR(fillval)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * log_polar(size, center, magnitude[ ,flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS]) - * - * Remaps image to log-polar space. - */ -VALUE -rb_log_polar(int argc, VALUE *argv, VALUE self) -{ - VALUE dst_size, center, m, flags; - rb_scan_args(argc, argv, "31", &dst_size, ¢er, &m, &flags); - int _flags = NIL_P(flags) ? (CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS) : NUM2INT(flags); - VALUE dest = new_mat_kind_object(VALUE_TO_CVSIZE(dst_size), self); - try { - cvLogPolar(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT2D32F(center), NUM2DBL(m), _flags); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * erode([element = nil, iteration = 1]) -> cvmat - * - * Create erodes image by using arbitrary structuring element. - * element is structuring element used for erosion. - * element should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used. - * iterations is number of times erosion is applied. - */ -VALUE -rb_erode(int argc, VALUE *argv, VALUE self) -{ - return rb_erode_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * erode!([element = nil][,iteration = 1]) -> self - * - * Erodes image by using arbitrary structuring element. - * see also #erode. - */ -VALUE -rb_erode_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE element, iteration; - rb_scan_args(argc, argv, "02", &element, &iteration); - IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); - try { - cvErode(CVARR(self), CVARR(self), kernel, IF_INT(iteration, 1)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * dilate([element = nil][,iteration = 1]) -> cvmat - * - * Create dilates image by using arbitrary structuring element. - * element is structuring element used for erosion. - * element should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used. - * iterations is number of times erosion is applied. - */ -VALUE -rb_dilate(int argc, VALUE *argv, VALUE self) -{ - return rb_dilate_bang(argc, argv, rb_clone(self)); -} - -/* - * call-seq: - * dilate!([element = nil][,iteration = 1]) -> self - * - * Dilate image by using arbitrary structuring element. - * see also #dilate. - */ -VALUE -rb_dilate_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE element, iteration; - rb_scan_args(argc, argv, "02", &element, &iteration); - IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); - try { - cvDilate(CVARR(self), CVARR(self), kernel, IF_INT(iteration, 1)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * morpholohy(operation[,element = nil][,iteration = 1]) -> cvmat - * - * Performs advanced morphological transformations. - * operation - * Type of morphological operation, one of: - * CV_MOP_OPEN - opening - * CV_MOP_CLOSE - closing - * CV_MOP_GRADIENT - morphological gradient - * CV_MOP_TOPHAT - top hat - * CV_MOP_BLACKHAT - black hat - */ -VALUE -rb_morphology(int argc, VALUE *argv, VALUE self) -{ - VALUE element, iteration, operation_val; - rb_scan_args(argc, argv, "12", &operation_val, &element, &iteration); - - int operation = CVMETHOD("MORPHOLOGICAL_OPERATION", operation_val, -1); - CvArr* self_ptr = CVARR(self); - CvSize size = cvGetSize(self_ptr); - VALUE dest = new_mat_kind_object(size, self); - IplConvKernel* kernel = NIL_P(element) ? NULL : IPLCONVKERNEL_WITH_CHECK(element); - try { - if (operation == CV_MOP_GRADIENT) { - CvMat* temp = rb_cvCreateMat(size.height, size.width, cvGetElemType(self_ptr)); - cvMorphologyEx(self_ptr, CVARR(dest), temp, kernel, CV_MOP_GRADIENT, IF_INT(iteration, 1)); - cvReleaseMat(&temp); - } - else { - cvMorphologyEx(self_ptr, CVARR(dest), 0, kernel, operation, IF_INT(iteration, 1)); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dest; -} - -/* - * call-seq: - * smooth_blur_no_scale([p1 = 3, p2 = 3]) -> cvmat - * - * Smooths the image by simple blur with no scaling. - * * 8bit unsigned -> return 16bit unsigned - * * 32bit floating point -> return 32bit floating point - * support single-channel image only. - */ -VALUE -rb_smooth_blur_no_scale(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, dest; - rb_scan_args(argc, argv, "02", &p1, &p2); - CvArr* self_ptr = CVARR(self); - int type = cvGetElemType(self_ptr), dest_type; - switch (CV_MAT_DEPTH(type)) { - case CV_8U: - dest_type = CV_16U; - break; - case CV_32F: - dest_type = CV_32F; - break; - default: - rb_raise(rb_eNotImpError, "unsupport format. (support 8bit unsigned/signed or 32bit floating point only)"); - } - dest = new_mat_kind_object(cvGetSize(self_ptr), self, dest_type, CV_MAT_CN(type)); - cvSmooth(self_ptr, CVARR(dest), CV_BLUR_NO_SCALE, IF_INT(p1, 3), IF_INT(p2, 3)); - return dest; -} - -/* - * call-seq: - * smooth_blur([p1 = 3, p2 = 3]) -> cvmat - * - * Smooths the image by simple blur. - * Summation over a pixel p1 x p2 neighborhood with subsequent scaling by 1 / (p1*p2). - */ -VALUE -rb_smooth_blur(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, dest; - rb_scan_args(argc, argv, "02", &p1, &p2); - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvSmooth(self_ptr, CVARR(dest), CV_BLUR, IF_INT(p1, 3), IF_INT(p2, 3)); - return dest; -} - -/* - * call-seq: - * smooth_gaussian([p1 = 3, p2 = 3, p3 = 0.0, p4 = 0.0]) -> cvmat - * - * Smooths the image by gaussian blur. - * Convolving image with p1 x p2 Gaussian kernel. - * - * p3 may specify Gaussian sigma (standard deviation). - * If it is zero, it is calculated from the kernel size: - * sigma = (n/2 - 1)*0.3 + 0.8, where n = p1 for horizontal kernel, - * n = p2 for vertical kernel. - * - * p4 is in case of non-square Gaussian kernel the parameter. - * It may be used to specify a different (from p3) sigma in the vertical direction. - */ -VALUE -rb_smooth_gaussian(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, p3, p4, dest; - rb_scan_args(argc, argv, "04", &p1, &p2, &p3, &p4); - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvSmooth(self_ptr, CVARR(dest), CV_GAUSSIAN, IF_INT(p1, 3), IF_INT(p2, 3), IF_DBL(p3, 0.0), IF_DBL(p4, 0.0)); - return dest; -} - -/* - * call-seq: - * smooth_median([p1 = 3]) -> cvmat - * - * Smooths the image by median blur. - * Finding median of p1 x p1 neighborhood (i.e. the neighborhood is square). - */ -VALUE -rb_smooth_median(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, dest; - rb_scan_args(argc, argv, "01", &p1); - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvSmooth(self_ptr, CVARR(dest), CV_MEDIAN, IF_INT(p1, 3)); - return dest; -} - -/* - * call-seq: - * smooth_bilateral([p1 = 3][p2 = 3]) -> cvmat - * - * Smooths the image by bilateral filter. - * Applying bilateral 3x3 filtering with color sigma=p1 and space sigma=p2. - */ -VALUE -rb_smooth_bilateral(int argc, VALUE *argv, VALUE self) -{ - VALUE p1, p2, dest; - rb_scan_args(argc, argv, "02", &p1, &p2); - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvSmooth(self_ptr, CVARR(dest), CV_BILATERAL, IF_INT(p1, 3), IF_INT(p2, 3)); - return dest; -} - -VALUE -rb_smooth(int argc, VALUE *argv, VALUE self) -{ - VALUE smoothtype, p1, p2, p3, p4; - rb_scan_args(argc, argv, "14", &smoothtype, &p1, &p2, &p3, &p4); - int _smoothtype = CVMETHOD("SMOOTHING_TYPE", smoothtype, -1); - - VALUE (*smooth_func)(int c, VALUE* v, VALUE s); - argc--; - switch (_smoothtype) { - case CV_BLUR_NO_SCALE: - smooth_func = rb_smooth_blur_no_scale; - argc = (argc > 2) ? 2 : argc; - break; - case CV_BLUR: - smooth_func = rb_smooth_blur; - argc = (argc > 2) ? 2 : argc; - break; - case CV_GAUSSIAN: - smooth_func = rb_smooth_gaussian; - break; - case CV_MEDIAN: - smooth_func = rb_smooth_median; - argc = (argc > 1) ? 1 : argc; - break; - case CV_BILATERAL: - smooth_func = rb_smooth_bilateral; - argc = (argc > 2) ? 2 : argc; - break; - default: - smooth_func = rb_smooth_gaussian; - break; - } - VALUE result = Qnil; - try { - result = (*smooth_func)(argc, argv + 1, self); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return result; -} - -/* - * call-seq: - * filter2d(kernel[,anchor]) -> cvmat - * - * Convolves image with the kernel. - * Convolution kernel, single-channel floating point matrix (or same depth of self's). - * If you want to apply different kernels to different channels, - * split the image using CvMat#split into separate color planes and process them individually. - */ -VALUE -rb_filter2d(int argc, VALUE *argv, VALUE self) -{ - VALUE _kernel, _anchor; - rb_scan_args(argc, argv, "11", &_kernel, &_anchor); - CvMat* kernel = CVMAT_WITH_CHECK(_kernel); - CvArr* self_ptr = CVARR(self); - VALUE _dest = Qnil; - try { - _dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvFilter2D(self_ptr, CVARR(_dest), kernel, NIL_P(_anchor) ? cvPoint(-1,-1) : VALUE_TO_CVPOINT(_anchor)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return _dest; -} - -/* - * call-seq: - * copy_make_border(border_type, size, offset[,value = CvScalar.new(0)]) - * - * Copies image and makes border around it. - * border_type: - * - IPL_BORDER_CONSTANT, :constant - * border is filled with the fixed value, passed as last parameter of the function. - * - IPL_BORDER_REPLICATE, :replicate - * the pixels from the top and bottom rows, the left-most and right-most columns are replicated to fill the border - * size: The destination image size - * offset: Coordinates of the top-left corner (or bottom-left in the case of images with bottom-left origin) of the destination image rectangle. - * value: Value of the border pixels if bordertype is IPL_BORDER_CONSTANT or :constant. - */ -VALUE -rb_copy_make_border(int argc, VALUE *argv, VALUE self) -{ - VALUE border_type, size, offset, value, dest; - rb_scan_args(argc, argv, "31", &border_type, &size, &offset, &value); - dest = new_mat_kind_object(VALUE_TO_CVSIZE(size), self); - - int type = 0; - if (SYMBOL_P(border_type)) { - ID type_id = rb_to_id(border_type); - if (type_id == rb_intern("constant")) - type = IPL_BORDER_CONSTANT; - else if (type_id == rb_intern("replicate")) - type = IPL_BORDER_REPLICATE; - else - rb_raise(rb_eArgError, "Invalid border_type (should be :constant or :replicate)"); - } - else - type = NUM2INT(border_type); - - try { - cvCopyMakeBorder(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT(offset), type, - NIL_P(value) ? cvScalar(0) : VALUE_TO_CVSCALAR(value)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * integral(need_sqsum = false, need_tilted_sum = false) -> [cvmat, cvmat or nil, cvmat or nil] - * - * Calculates integral images. - * If need_sqsum = true, calculate the integral image for squared pixel values. - * If need_tilted_sum = true, calculate the integral for the image rotated by 45 degrees. - * - * sum(X,Y)=sumxthreshold, max_value, threshold_type[,use_otsu = false]) - * - * Applies fixed-level threshold to array elements. - * - */ -VALUE -rb_threshold(int argc, VALUE *argv, VALUE self) -{ - VALUE threshold, max_value, threshold_type, use_otsu; - rb_scan_args(argc, argv, "31", &threshold, &max_value, &threshold_type, &use_otsu); - const int INVALID_TYPE = -1; - int type = CVMETHOD("THRESHOLD_TYPE", threshold_type, INVALID_TYPE); - if (type == INVALID_TYPE) - rb_raise(rb_eArgError, "Invalid threshold type."); - - return rb_threshold_internal(type, threshold, max_value, use_otsu, self); -} - - -/* - * call-seq: - * adaptive_threshold(max_value[, options]) -> cvmat - * - * Applies an adaptive threshold to an array. - * - * ==== params: - * - * * max_value (Number) - Maximum value that is used with +CV_THRESH_BINARY+ and +CV_THRESH_BINARY_INV+ - * * options (Hash) - threshold option - * * :threshold_type (Integer or Symbol) - Thresholding type; must be one of +CV_THRESH_BINARY+ or +:binary+, +CV_THRESH_BINARY_INV+ or +:binary_inv+ (default: +CV_THRESH_BINARY+) - * * :adaptive_method (Integer or Symbol) - Adaptive thresholding algorithm to use: +CV_ADAPTIVE_THRESH_MEAN_C+ or +:mean_c+, +CV_ADAPTIVE_THRESH_GAUSSIAN_C+ or +:gaussian_c+ (default: +CV_ADAPTIVE_THRESH_MEAN_C+) - * * :block_size (Integer) - The size of a pixel neighborhood that is used to calculate a threshold value for the pixel: 3, 5, 7, and so on (default: 3) - * * :param1 (Number) - The method-dependent parameter. For the methods +CV_ADAPTIVE_THRESH_MEAN_C+ and +CV_ADAPTIVE_THRESH_GAUSSIAN_C+ it is a constant subtracted from the mean or weighted mean, though it may be negative (default: 5) - */ -VALUE -rb_adaptive_threshold(int argc, VALUE *argv, VALUE self) -{ - VALUE max_value, options; - rb_scan_args(argc, argv, "11", &max_value, &options); - - int threshold_type = CV_THRESH_BINARY; - int adaptive_method = CV_ADAPTIVE_THRESH_MEAN_C; - int block_size = 3; - double param1 = 5; - if (!NIL_P(options)) { - Check_Type(options, T_HASH); - threshold_type = CVMETHOD("THRESHOLD_TYPE", LOOKUP_HASH(options, "threshold_type"), - CV_THRESH_BINARY); - adaptive_method = CVMETHOD("ADAPTIVE_METHOD", LOOKUP_HASH(options, "adaptive_method"), - CV_ADAPTIVE_THRESH_MEAN_C); - VALUE _block_size = LOOKUP_HASH(options, "block_size"); - if (!NIL_P(_block_size)) { - block_size = NUM2INT(_block_size); - } - VALUE _param1 = LOOKUP_HASH(options, "param1"); - if (!NIL_P(_param1)) { - param1 = NUM2INT(_param1); - } - } - CvArr* self_ptr = CVARR(self); - VALUE dst = new_mat_kind_object(cvGetSize(self_ptr), self); - try { - cvAdaptiveThreshold(self_ptr, CVARR(dst), NUM2DBL(max_value), adaptive_method, threshold_type, - block_size, param1); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dst; -} - -/* - * call-seq: - * pyr_down([filter = :gaussian_5x5]) -> cvmat - * - * Return downsamples image. - * - * This operation performs downsampling step of Gaussian pyramid decomposition. - * First it convolves source image with the specified filter and then downsamples the image by rejecting even rows and columns. - * - * note: filter - only :gaussian_5x5 is currently supported. - */ -VALUE -rb_pyr_down(int argc, VALUE *argv, VALUE self) -{ - int filter = CV_GAUSSIAN_5x5; - if (argc > 0) { - VALUE filter_type = argv[0]; - switch (TYPE(filter_type)) { - case T_SYMBOL: - // currently suport CV_GAUSSIAN_5x5 only. - break; - default: - raise_typeerror(filter_type, rb_cSymbol); - } - } - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - CvSize original_size = cvGetSize(self_ptr); - CvSize size = { original_size.width >> 1, original_size.height >> 1 }; - dest = new_mat_kind_object(size, self); - cvPyrDown(self_ptr, CVARR(dest), filter); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * pyr_up([filter = :gaussian_5x5]) -> cvmat - * - * Return upsamples image. - * - * This operation performs up-sampling step of Gaussian pyramid decomposition. - * First it upsamples the source image by injecting even zero rows and columns and then convolves result with the specified filter multiplied by 4 for interpolation. - * So the destination image is four times larger than the source image. - * - * note: filter - only :gaussian_5x5 is currently supported. - */ -VALUE -rb_pyr_up(int argc, VALUE *argv, VALUE self) -{ - VALUE filter_type; - rb_scan_args(argc, argv, "01", &filter_type); - int filter = CV_GAUSSIAN_5x5; - if (argc > 0) { - switch (TYPE(filter_type)) { - case T_SYMBOL: - // currently suport CV_GAUSSIAN_5x5 only. - break; - default: - raise_typeerror(filter_type, rb_cSymbol); - } - } - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - CvSize original_size = cvGetSize(self_ptr); - CvSize size = { original_size.width << 1, original_size.height << 1 }; - dest = new_mat_kind_object(size, self); - cvPyrUp(self_ptr, CVARR(dest), filter); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * flood_fill(seed_point, new_val, lo_diff, up_diff[,flood_fill_option]) -> [cvmat, cvconnectedcomp, iplimage(mask)] - * - * Return image filled a connnected compoment with given color. - * This operation fills a connected component starting from the seed point with the specified color. - * The connectivity is determined by the closeness of pixel values. - * The pixel at (x, y) is considered to belong to the repainted domain if: - * - * src(x',y')-lo_diff<=src(x,y)<=src(x',y')+up_diff, grayscale image, floating range - * src(seed.x,seed.y)-lo<=src(x,y)<=src(seed.x,seed.y)+up_diff, grayscale image, fixed range - * src(x',y')r-lo_diffr<=src(x,y)r<=src(x',y')r+up_diffr and - * src(x',y')g-lo_diffg<=src(x,y)g<=src(x',y')g+up_diffg and - * src(x',y')b-lo_diffb<=src(x,y)b<=src(x',y')b+up_diffb, color image, floating range - * src(seed.x,seed.y)r-lo_diffr<=src(x,y)r<=src(seed.x,seed.y)r+up_diffr and - * src(seed.x,seed.y)g-lo_diffg<=src(x,y)g<=src(seed.x,seed.y)g+up_diffg and - * src(seed.x,seed.y)b-lo_diffb<=src(x,y)b<=src(seed.x,seed.y)b+up_diffb, color image, fixed range - * - * where src(x',y') is value of one of pixel neighbors. - * That is, to be added to the connected component, a pixel's color/brightness should be close enough to: - * * color/brightness of one of its neighbors that are already referred to the connected component in case of floating range - * * color/brightness of the seed point in case of fixed range. - * - * arguments - * * seed_point -The starting point. - * * new_val - New value of repainted domain pixels. - * * lo_diff - Maximal lower brightness/color difference between the currently observed pixel and one of its neighbor belong to the component or seed pixel to add the pixel to component. In case of 8-bit color images it is packed value. - * * up_diff - Maximal upper brightness/color difference between the currently observed pixel and one of its neighbor belong to the component or seed pixel to add the pixel to component. In case of 8-bit color images it is packed value. - * - * and flood_fill_option - * :connectivity => 4 or 8, 4 default - * Connectivity determines which neighbors of a pixel are considered. - * :fixed_range => true or false, false default - * If set the difference between the current pixel and seed pixel is considered, otherwise difference between neighbor pixels is considered (the range is floating). - * :mask_only => true or false, false default - * If set, the function does not fill the image(new_val is ignored), but the fills mask. - * - * note: flood_fill_option's default value is CvMat::FLOOD_FILL_OPTION. - */ -VALUE -rb_flood_fill(int argc, VALUE *argv, VALUE self) -{ - return rb_flood_fill_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * flood_fill!(seed_point, new_val, lo_diff, up_diff[,flood_fill_option]) -> [self, cvconnectedcomp, iplimage(mask)] - * - * Fills a connected component with given color. - * see CvMat#flood_fill - */ -VALUE -rb_flood_fill_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE seed_point, new_val, lo_diff, up_diff, flood_fill_option; - rb_scan_args(argc, argv, "23", &seed_point, &new_val, &lo_diff, &up_diff, &flood_fill_option); - flood_fill_option = FLOOD_FILL_OPTION(flood_fill_option); - int flags = FF_CONNECTIVITY(flood_fill_option); - if (FF_FIXED_RANGE(flood_fill_option)) { - flags |= CV_FLOODFILL_FIXED_RANGE; - } - if (FF_MASK_ONLY(flood_fill_option)) { - flags |= CV_FLOODFILL_MASK_ONLY; - } - CvArr* self_ptr = CVARR(self); - VALUE comp = cCvConnectedComp::new_object(); - VALUE mask = Qnil; - try { - CvSize size = cvGetSize(self_ptr); - // TODO: Change argument format to set mask - mask = new_object(size.height + 2, size.width + 2, CV_MAKETYPE(CV_8U, 1)); - CvMat* mask_ptr = CVMAT(mask); - cvSetZero(mask_ptr); - cvFloodFill(self_ptr, - VALUE_TO_CVPOINT(seed_point), - VALUE_TO_CVSCALAR(new_val), - NIL_P(lo_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(lo_diff), - NIL_P(up_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(up_diff), - CVCONNECTEDCOMP(comp), - flags, - mask_ptr); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(3, self, comp, mask); -} - -/* - * call-seq: - * find_contours([find_contours_options]) -> cvchain or cvcontour or nil - * - * Finds contours in binary image, and return contours as CvContour or CvChain. - * If contours not found, return nil. - * - * flood_fill_option should be Hash include these keys. - * :mode - Retrieval mode. - * :external - retrive only the extreme outer contours - * :list - retrieve all the contours and puts them in the list.(default) - * :ccomp - retrieve all the contours and organizes them into two-level hierarchy: - * top level are external boundaries of the components, second level are bounda boundaries of the holes - * :tree - retrieve all the contours and reconstructs the full hierarchy of nested contours - * Connectivity determines which neighbors of a pixel are considered. - * :method - Approximation method. - * :code - output contours in the Freeman chain code. All other methods output polygons (sequences of vertices). - * :approx_none - translate all the points from the chain code into points; - * :approx_simple - compress horizontal, vertical, and diagonal segments, that is, the function leaves only their ending points;(default) - * :approx_tc89_l1 - * :approx_tc89_kcos - apply one of the flavors of Teh-Chin chain approximation algorithm. - * If set the difference between the current pixel and seed pixel is considered, - * otherwise difference between neighbor pixels is considered (the range is floating). - * :offset - Offset, by which every contour point is shifted. - * This is useful if the contours are extracted from the image ROI - * and then they should be analyzed in the whole image context. Should be CvPoint. - * - * note: find_contours_option's default value is CvMat::FIND_CONTOURS_OPTION. - * - * support single-channel 8bit unsigned image only. - * - * note: Non-zero pixels are treated as 1's, zero pixels remain 0's - * that is image treated as binary. To get such a binary image from grayscale, - * one may use threshold, adaptive_threshold or canny. - */ -VALUE -rb_find_contours(int argc, VALUE *argv, VALUE self) -{ - return rb_find_contours_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * find_contours!([find_contours_options]) -> cvchain or chcontour or nil - * - * Finds contours in binary image. - * The function modifies the source image content. - * (Because the copy is not made, it is slightly faster than find_contours.) - * - * see find_contours - * - * support single-channel 8bit unsigned image only. - */ -VALUE -rb_find_contours_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE find_contours_option, klass, element_klass, storage; - rb_scan_args(argc, argv, "01", &find_contours_option); - CvSeq *contour = NULL; - find_contours_option = FIND_CONTOURS_OPTION(find_contours_option); - int mode = FC_MODE(find_contours_option); - int method = FC_METHOD(find_contours_option); - int header_size; - if (method == CV_CHAIN_CODE) { - klass = cCvChain::rb_class(); - element_klass = T_FIXNUM; - header_size = sizeof(CvChain); - } - else { - klass = cCvContour::rb_class(); - element_klass = cCvPoint::rb_class(); - header_size = sizeof(CvContour); - } - storage = cCvMemStorage::new_object(); - - int count = 0; - try { - count = cvFindContours(CVARR(self), CVMEMSTORAGE(storage), &contour, header_size, - mode, method, FC_OFFSET(find_contours_option)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - if (count == 0) - return Qnil; - else - return cCvSeq::new_sequence(klass, contour, element_klass, storage); -} - -/* - * call-seq: - * draw_contours(contour, external_color, hole_color, max_level, options) -> cvmat - * - * Draws contour outlines or interiors in an image. - * - * * contour (CvContour) - Pointer to the first contour - * * external_color (CvScalar) - Color of the external contours - * * hole_color (CvScalar) - Color of internal contours (holes) - * * max_level (Integer) - Maximal level for drawn contours. If 0, only contour is drawn. If 1, the contour and all contours following it on the same level are drawn. If 2, all contours following and all contours one level below the contours are drawn, and so forth. If the value is negative, the function does not draw the contours following after contour but draws the child contours of contour up to the |max_level| - 1 level. - * * options (Hash) - Drawing options. - * * :thickness (Integer) - Thickness of lines the contours are drawn with. If it is negative, the contour interiors are drawn (default: 1). - * * :line_type (Integer or Symbol) - Type of the contour segments, see CvMat#line description (default: 8). - */ -VALUE -rb_draw_contours(int argc, VALUE *argv, VALUE self) -{ - return rb_draw_contours_bang(argc, argv, copy(self)); -} - -/* - * call-seq: - * draw_contours!(contour, external_color, hole_color, max_level, options) -> cvmat - * - * Draws contour outlines or interiors in an image. - * - * see CvMat#draw_contours - */ -VALUE -rb_draw_contours_bang(int argc, VALUE *argv, VALUE self) -{ - VALUE contour, external_color, hole_color, max_level, options; - rb_scan_args(argc, argv, "41", &contour, &external_color, &hole_color, &max_level, &options); - options = DRAWING_OPTION(options); - try { - cvDrawContours(CVARR(self), CVSEQ_WITH_CHECK(contour), VALUE_TO_CVSCALAR(external_color), - VALUE_TO_CVSCALAR(hole_color), NUM2INT(max_level), - DO_THICKNESS(options), DO_LINE_TYPE(options)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return self; -} - -/* - * call-seq: - * draw_chessboard_corners(pattern_size, corners, pattern_was_found) -> nil - * - * Returns an image which is rendered the detected chessboard corners. - * - * pattern_size (CvSize) - Number of inner corners per a chessboard row and column. - * corners (Array) - Array of detected corners, the output of CvMat#find_chessboard_corners. - * pattern_was_found (Boolean)- Parameter indicating whether the complete board was found or not. - */ -VALUE -rb_draw_chessboard_corners(VALUE self, VALUE pattern_size, VALUE corners, VALUE pattern_was_found) -{ - return rb_draw_chessboard_corners_bang(copy(self), pattern_size, corners, pattern_was_found); -} - -/* - * call-seq: - * draw_chessboard_corners!(pattern_size, corners, pattern_was_found) -> self - * - * Renders the detected chessboard corners. - * - * pattern_size (CvSize) - Number of inner corners per a chessboard row and column. - * corners (Array) - Array of detected corners, the output of CvMat#find_chessboard_corners. - * pattern_was_found (Boolean)- Parameter indicating whether the complete board was found or not. - */ -VALUE -rb_draw_chessboard_corners_bang(VALUE self, VALUE pattern_size, VALUE corners, VALUE pattern_was_found) -{ - Check_Type(corners, T_ARRAY); - int count = RARRAY_LEN(corners); - CvPoint2D32f* corners_buff = ALLOCA_N(CvPoint2D32f, count); - VALUE* corners_ptr = RARRAY_PTR(corners); - for (int i = 0; i < count; i++) { - corners_buff[i] = *(CVPOINT2D32F(corners_ptr[i])); - } - - try { - int found = (pattern_was_found == Qtrue); - cvDrawChessboardCorners(CVARR(self), VALUE_TO_CVSIZE(pattern_size), corners_buff, count, found); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return self; -} - -/* - * call-seq: - * pyr_mean_shift_filtering(sp, sr[,max_level = 1][termcrit = CvTermCriteria.new(5,1)]) -> cvmat - * - * Does meanshift image segmentation. - * - * sp - The spatial window radius. - * sr - The color window radius. - * max_level - Maximum level of the pyramid for the segmentation. - * termcrit - Termination criteria: when to stop meanshift iterations. - * - * This method is implements the filtering stage of meanshift segmentation, - * that is, the output of the function is the filtered "posterized" image with color gradients and fine-grain texture flattened. - * At every pixel (X,Y) of the input image (or down-sized input image, see below) - * the function executes meanshift iterations, that is, the pixel (X,Y) neighborhood in the joint space-color hyperspace is considered: - * {(x,y): X-sp≤x≤X+sp && Y-sp≤y≤Y+sp && ||(R,G,B)-(r,g,b)|| ≤ sr}, - * where (R,G,B) and (r,g,b) are the vectors of color components at (X,Y) and (x,y), - * respectively (though, the algorithm does not depend on the color space used, - * so any 3-component color space can be used instead). - * Over the neighborhood the average spatial value (X',Y') - * and average color vector (R',G',B') are found and they act as the neighborhood center on the next iteration: - * (X,Y)~(X',Y'), (R,G,B)~(R',G',B'). - * After the iterations over, the color components of the initial pixel (that is, the pixel from where the iterations started) - * are set to the final value (average color at the last iteration): - * I(X,Y) <- (R*,G*,B*). - * Then max_level > 0, the gaussian pyramid of max_level+1 levels is built, - * and the above procedure is run on the smallest layer. - * After that, the results are propagated to the larger layer and the iterations are run again - * only on those pixels where the layer colors differ much (>sr) from the lower-resolution layer, - * that is, the boundaries of the color regions are clarified. - * - * Note, that the results will be actually different from the ones obtained by running the meanshift procedure on the whole original image (i.e. when max_level==0). - */ -VALUE -rb_pyr_mean_shift_filtering(int argc, VALUE *argv, VALUE self) -{ - VALUE spatial_window_radius, color_window_radius, max_level, termcrit; - rb_scan_args(argc, argv, "22", &spatial_window_radius, &color_window_radius, &max_level, &termcrit); - CvArr* self_ptr = CVARR(self); - VALUE dest = Qnil; - try { - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvPyrMeanShiftFiltering(self_ptr, CVARR(dest), - NUM2DBL(spatial_window_radius), - NUM2DBL(color_window_radius), - IF_INT(max_level, 1), - NIL_P(termcrit) ? cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 5, 1) - : VALUE_TO_CVTERMCRITERIA(termcrit)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * watershed -> cvmat(mean markers:cv32s) - * - * Does watershed segmentation. - */ -VALUE -rb_watershed(VALUE self, VALUE markers) -{ - try { - cvWatershed(CVARR(self), CVARR_WITH_CHECK(markers)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return markers; -} - -/* - * call-seq: - * moments -> cvmoments - * - * Calculates moments. - */ -VALUE -rb_moments(int argc, VALUE *argv, VALUE self) -{ - VALUE is_binary; - rb_scan_args(argc, argv, "01", &is_binary); - CvArr *self_ptr = CVARR(self); - VALUE moments = Qnil; - try { - moments = cCvMoments::new_object(self_ptr, TRUE_OR_FALSE(is_binary, 0)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return moments; -} - -/* - * call-seq: - * hough_lines(method, rho, theta, threshold, param1, param2) -> cvseq(include CvLine or CvTwoPoints) - * - * Finds lines in binary image using a Hough transform. - * * method – - - * * The Hough transform variant, one of the following: - * * - CV_HOUGH_STANDARD - classical or standard Hough transform. - * * - CV_HOUGH_PROBABILISTIC - probabilistic Hough transform (more efficient in case if picture contains a few long linear segments). - * * - CV_HOUGH_MULTI_SCALE - multi-scale variant of the classical Hough transform. The lines are encoded the same way as CV_HOUGH_STANDARD. - * * rho - Distance resolution in pixel-related units. - * * theta - Angle resolution measured in radians. - * * threshold - Threshold parameter. A line is returned by the function if the corresponding accumulator value is greater than threshold. - * * param1 – - - * * The first method-dependent parameter: - * * For the classical Hough transform it is not used (0). - * * For the probabilistic Hough transform it is the minimum line length. - * * For the multi-scale Hough transform it is the divisor for the distance resolution . (The coarse distance resolution will be rho and the accurate resolution will be (rho / param1)). - * * param2 – - - * * The second method-dependent parameter: - * * For the classical Hough transform it is not used (0). - * * For the probabilistic Hough transform it is the maximum gap between line segments lying on the same line to treat them as a single line segment (i.e. to join them). - * * For the multi-scale Hough transform it is the divisor for the angle resolution. (The coarse angle resolution will be theta and the accurate resolution will be (theta / param2).) - */ -VALUE -rb_hough_lines(int argc, VALUE *argv, VALUE self) -{ - const int INVALID_TYPE = -1; - VALUE method, rho, theta, threshold, p1, p2; - rb_scan_args(argc, argv, "42", &method, &rho, &theta, &threshold, &p1, &p2); - int method_flag = CVMETHOD("HOUGH_TRANSFORM_METHOD", method, INVALID_TYPE); - if (method_flag == INVALID_TYPE) - rb_raise(rb_eArgError, "Invalid method: %d", method_flag); - VALUE storage = cCvMemStorage::new_object(); - CvSeq *seq = NULL; - try { - seq = cvHoughLines2(CVARR(copy(self)), CVMEMSTORAGE(storage), - method_flag, NUM2DBL(rho), NUM2DBL(theta), NUM2INT(threshold), - IF_DBL(p1, 0), IF_DBL(p2, 0)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - switch (method_flag) { - case CV_HOUGH_STANDARD: - case CV_HOUGH_MULTI_SCALE: - return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvLine::rb_class(), storage); - break; - case CV_HOUGH_PROBABILISTIC: - return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvTwoPoints::rb_class(), storage); - break; - default: - break; - } - - return Qnil; -} - -/* - * call-seq: - * hough_circles(method, dp, min_dist, param1, param2, min_radius = 0, max_radius = max(width,height)) -> cvseq(include CvCircle32f) - * - * Finds circles in grayscale image using Hough transform. - */ -VALUE -rb_hough_circles(int argc, VALUE *argv, VALUE self) -{ - const int INVALID_TYPE = -1; - VALUE method, dp, min_dist, param1, param2, min_radius, max_radius, storage; - rb_scan_args(argc, argv, "52", &method, &dp, &min_dist, ¶m1, ¶m2, - &min_radius, &max_radius); - storage = cCvMemStorage::new_object(); - int method_flag = CVMETHOD("HOUGH_TRANSFORM_METHOD", method, INVALID_TYPE); - if (method_flag == INVALID_TYPE) - rb_raise(rb_eArgError, "Invalid method: %d", method_flag); - CvSeq *seq = NULL; - try { - seq = cvHoughCircles(CVARR(self), CVMEMSTORAGE(storage), - method_flag, NUM2DBL(dp), NUM2DBL(min_dist), - NUM2DBL(param1), NUM2DBL(param2), - IF_INT(min_radius, 0), IF_INT(max_radius, 0)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvCircle32f::rb_class(), storage); -} - -/* - * call-seq: - * inpaint(inpaint_method, mask, radius) -> cvmat - * - * Inpaints the selected region in the image - * The radius of circlular neighborhood of each point inpainted that is considered by the algorithm. - */ -VALUE -rb_inpaint(VALUE self, VALUE inpaint_method, VALUE mask, VALUE radius) -{ - const int INVALID_TYPE = -1; - VALUE dest = Qnil; - int method = CVMETHOD("INPAINT_METHOD", inpaint_method, INVALID_TYPE); - if (method == INVALID_TYPE) - rb_raise(rb_eArgError, "Invalid method"); - try { - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvInpaint(self_ptr, MASK(mask), CVARR(dest), NUM2DBL(radius), method); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * equalize_hist - cvmat - * - * Equalize histgram of grayscale of image. - * - * equalizes histogram of the input image using the following algorithm: - * 1. calculate histogram H for src. - * 2. normalize histogram, so that the sum of histogram bins is 255. - * 3. compute integral of the histogram: - * H’(i) = sum0≤j≤iH(j) - * 4. transform the image using H’ as a look-up table: dst(x,y)=H’(src(x,y)) - * The algorithm normalizes brightness and increases contrast of the image. - * - * support single-channel 8bit image (grayscale) only. - */ -VALUE -rb_equalize_hist(VALUE self) -{ - VALUE dest = Qnil; - try { - CvArr* self_ptr = CVARR(self); - dest = new_mat_kind_object(cvGetSize(self_ptr), self); - cvEqualizeHist(self_ptr, CVARR(dest)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return dest; -} - -/* - * call-seq: - * apply_color_map(colormap) -> cvmat - * - * Applies a GNU Octave/MATLAB equivalent colormap on a given image. - * - * Parameters: - * colormap - The colormap to apply. - */ -VALUE -rb_apply_color_map(VALUE self, VALUE colormap) -{ - VALUE dst; - try { - cv::Mat dst_mat; - cv::Mat self_mat(CVMAT(self)); - - cv::applyColorMap(self_mat, dst_mat, NUM2INT(colormap)); - CvMat tmp = dst_mat; - dst = new_object(tmp.rows, tmp.cols, tmp.type); - cvCopy(&tmp, CVMAT(dst)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return dst; -} - -/* - * call-seq: - * match_template(template[,method = :sqdiff]) -> cvmat(result) - * - * Compares template against overlapped image regions. - - * method is specifies the way the template must be compared with image regions. - * method should be following symbol. (see OpenCV::MATCH_TEMPLATE_METHOD 's key and value.) - * - * * :sqdiff - * R(x,y)=sumx',y'[T(x',y')-I(x+x',y+y')]2 - * * :sqdiff_normed - * R(x,y)=sumx',y'[T(x',y')-I(x+x',y+y')]2/sqrt[sumx',y'T(x',y')2*sumx',y'I(x+x',y+y')2] - * * :ccorr - * R(x,y)=sumx',y'[T(x',y')*I(x+x',y+y')] - * * :ccorr_normed - * R(x,y)=sumx',y'[T(x',y')*I(x+x',y+y')]/sqrt[sumx',y'T(x',y')2*sumx',y'I(x+x',y+y')2] - * * :ccoeff - * R(x,y)=sumx',y'[T'(x',y')*I'(x+x',y+y')], - * where T'(x',y')=T(x',y') - 1/(w*h)*sumx",y"T(x",y") - * I'(x+x',y+y')=I(x+x',y+y') - 1/(w*h)*sumx",y"I(x+x",y+y") - * * :ccoeff_normed - * R(x,y)=sumx',y'[T'(x',y')*I'(x+x',y+y')]/sqrt[sumx',y'T'(x',y')2*sumx',y'I'(x+x',y+y')2] - * - * After the match_template finishes comparison, the best matches can be found as global - * minimums (:sqdiff*) or maximums(:ccorr* or :ccoeff*) using minmax function. - * In case of color image and template summation in both numerator and each sum in denominator - * is done over all the channels (and separate mean values are used for each channel). - */ -VALUE -rb_match_template(int argc, VALUE *argv, VALUE self) -{ - VALUE templ, method; - int method_flag; - if (rb_scan_args(argc, argv, "11", &templ, &method) == 1) - method_flag = CV_TM_SQDIFF; - else - method_flag = CVMETHOD("MATCH_TEMPLATE_METHOD", method); - - CvArr* self_ptr = CVARR(self); - CvArr* templ_ptr = CVARR_WITH_CHECK(templ); - VALUE result = Qnil; - try { - CvSize src_size = cvGetSize(self_ptr); - CvSize template_size = cvGetSize(templ_ptr); - result = cCvMat::new_object(src_size.height - template_size.height + 1, - src_size.width - template_size.width + 1, - CV_32FC1); - cvMatchTemplate(self_ptr, templ_ptr, CVARR(result), method_flag); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return result; -} - -/* - * call-seq: - * match_shapes(object, method) -> float - * - * Compares two shapes(self and object). object should be CvMat or CvContour. - * - * A - object1, B - object2: - * * method=CV_CONTOURS_MATCH_I1 - * I1(A,B)=sumi=1..7abs(1/mAi - 1/mBi) - * * method=CV_CONTOURS_MATCH_I2 - * I2(A,B)=sumi=1..7abs(mAi - mBi) - * * method=CV_CONTOURS_MATCH_I3 - * I3(A,B)=sumi=1..7abs(mAi - mBi)/abs(mAi) - */ -VALUE -rb_match_shapes(int argc, VALUE *argv, VALUE self) -{ - VALUE object, method, param; - rb_scan_args(argc, argv, "21", &object, &method, ¶m); - int method_flag = CVMETHOD("COMPARISON_METHOD", method); - if (!(rb_obj_is_kind_of(object, cCvMat::rb_class()) || rb_obj_is_kind_of(object, cCvContour::rb_class()))) - rb_raise(rb_eTypeError, "argument 1 (shape) should be %s or %s", - rb_class2name(cCvMat::rb_class()), rb_class2name(cCvContour::rb_class())); - double result = 0; - try { - result = cvMatchShapes(CVARR(self), CVARR(object), method_flag); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_float_new(result); -} - - -/** - * Port from OpenCV sample: matching_to_many_images.cpp - * call-seq: - * match_descriptors(images[, detector_type="SURF"][, descriptor_type="SURF"][, matcher_type="FlannBased"]) -> Hash - * - * Matching descriptors detected on one image to descriptors detected in image array. - * Returns a Hash contains match count of each image index. - * For example, a Hash {0 => 5, 2 => 10} means the images[0] has 5 key points matched, images[2] has 10 key points matched, - * and all of other images in the images array have no key point matched. - * Hence images[2] is the best match in general. - * - * images is an array of CvMat objects. - * detector_type is a string, default is "SURF", options: "SURF", "FAST", "SIFT", "STAR" - * descriptor_type is a string, default is "SURF", options: "SURF", "SIFT", "BRIEF" - * matcher_type is a string, default is "FlannBased", options: "FlannBased", "BruteForce" - */ -VALUE -rb_match_descriptors(int argc, VALUE *argv, VALUE self) -{ - VALUE images, detector_type, descriptor_type, matcher_type; - rb_scan_args(argc, argv, "13", &images, &detector_type, &descriptor_type, &matcher_type); - if (RARRAY_LEN(images) == 0) { - return rb_hash_new(); - } - if (NIL_P(detector_type)) { - detector_type = rb_str_new2("SURF"); - } - if (NIL_P(descriptor_type)) { - descriptor_type = rb_str_new2("SURF"); - } - if (NIL_P(matcher_type)) { - matcher_type = rb_str_new2("FlannBased"); - } - - VALUE _matches = rb_hash_new(); - try { - cv::Mat queryImage(CVMAT(self)); - std::vector trainImages; - for(int i = 0, n = RARRAY_LEN(images); i < n; i++) { - trainImages.push_back(CVMAT_WITH_CHECK(RARRAY_PTR(images)[i])); - } - - cv::Ptr featureDetector = cv::FeatureDetector::create(StringValueCStr(detector_type)); - if (featureDetector.empty()) { - rb_raise(rb_eArgError, "Could not create feature detector by given detector type: %s", StringValueCStr(detector_type)); - } - cv::Ptr descriptorExtractor = cv::DescriptorExtractor::create(StringValueCStr(descriptor_type)); - if (descriptorExtractor.empty()) { - rb_raise(rb_eArgError, "Could not create descriptor extractor by given descriptor type: %s", StringValueCStr(descriptor_type)); - } - cv::Ptr descriptorMatcher; - try { - descriptorMatcher = cv::DescriptorMatcher::create(StringValueCStr(matcher_type)); - } - catch(cv::Exception& e) { - rb_raise(rb_eArgError, "Could not create descriptor matcher by given matcher type: %s", StringValueCStr(matcher_type)); - } - - std::vector queryKeypoints; - std::vector > trainKeypoints; - featureDetector->detect(queryImage, queryKeypoints); - featureDetector->detect(trainImages, trainKeypoints); - cv::Mat queryDescriptors; - std::vector trainDescriptors; - descriptorExtractor->compute(queryImage, queryKeypoints, queryDescriptors); - descriptorExtractor->compute(trainImages, trainKeypoints, trainDescriptors); - std::vector matches; - descriptorMatcher->add(trainDescriptors); - descriptorMatcher->train(); - descriptorMatcher->match(queryDescriptors, matches); - - for (size_t i = 0, n = matches.size(); i < n; i++) { - VALUE match = INT2FIX(matches[i].imgIdx); - VALUE count = rb_hash_lookup(_matches, match); - if (NIL_P(count)) { - count = INT2FIX(1); - } else { - count = INT2FIX(FIX2INT(count) + 1); - } - rb_hash_aset(_matches, match, count); - } - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return _matches; -} - -/* - * call-seq: - * mean_shift(window, criteria) -> comp - * - * Implements CAMSHIFT object tracking algrorithm. - * First, it finds an object center using mean_shift and, after that, - * calculates the object size and orientation. - */ -VALUE -rb_mean_shift(VALUE self, VALUE window, VALUE criteria) -{ - VALUE comp = cCvConnectedComp::new_object(); - try { - cvMeanShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), CVCONNECTEDCOMP(comp)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return comp; -} - -/* - * call-seq: - * cam_shift(window, criteria) -> [comp, box] - * - * Implements CAMSHIFT object tracking algrorithm. First, it finds an object center using cvMeanShift and, - * after that, calculates the object size and orientation. The function returns number of iterations made - * within cvMeanShift. - */ -VALUE -rb_cam_shift(VALUE self, VALUE window, VALUE criteria) -{ - VALUE comp = cCvConnectedComp::new_object(); - VALUE box = cCvBox2D::new_object(); - try { - cvCamShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), - CVCONNECTEDCOMP(comp), CVBOX2D(box)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, comp, box); -} - -/* - * 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) -{ - 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; -} - -/* - * call-seq: - * optical_flow_hs(prev[,velx = nil][,vely = nil][,options]) -> [cvmat, cvmat] - * - * Calculates optical flow for two images (previous -> self) using Horn & Schunck algorithm. - * Return horizontal component of the optical flow and vertical component of the optical flow. - * prev is previous image - * velx is previous velocity field of x-axis, and vely is previous velocity field of y-axis. - * - * options - * * :lambda -> should be Float (default is 0.0005) - * Lagrangian multiplier. - * * :criteria -> should be CvTermCriteria object (default is CvTermCriteria(1, 0.001)) - * Criteria of termination of velocity computing. - * note: option's default value is CvMat::OPTICAL_FLOW_HS_OPTION. - * - * sample code - * velx, vely = nil, nil - * while true - * current = capture.query - * velx, vely = current.optical_flow_hs(prev, velx, vely) if prev - * prev = current - * end - */ -VALUE -rb_optical_flow_hs(int argc, VALUE *argv, VALUE self) -{ - VALUE prev, velx, vely, options; - int use_previous = 0; - rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options); - options = OPTICAL_FLOW_HS_OPTION(options); - CvMat *velx_ptr, *vely_ptr; - CvArr* self_ptr = CVARR(self); - try { - if (NIL_P(velx) && NIL_P(vely)) { - CvSize size = cvGetSize(self_ptr); - int type = CV_MAKETYPE(CV_32F, 1); - velx = cCvMat::new_object(size, type); - vely = cCvMat::new_object(size, type); - velx_ptr = CVMAT(velx); - vely_ptr = CVMAT(vely); - } - else { - use_previous = 1; - velx_ptr = CVMAT_WITH_CHECK(velx); - vely_ptr = CVMAT_WITH_CHECK(vely); - } - cvCalcOpticalFlowHS(CVMAT_WITH_CHECK(prev), self_ptr, use_previous, velx_ptr, vely_ptr, - HS_LAMBDA(options), HS_CRITERIA(options)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, velx, vely); -} - -/* - * call-seq: - * optical_flow_lk(prev, win_size) -> [cvmat, cvmat] - * - * Calculates optical flow for two images (previous -> self) using Lucas & Kanade algorithm - * Return horizontal component of the optical flow and vertical component of the optical flow. - * - * win_size is size of the averaging window used for grouping pixels. - */ -VALUE -rb_optical_flow_lk(VALUE self, VALUE prev, VALUE win_size) -{ - VALUE velx = Qnil; - VALUE vely = Qnil; - try { - CvArr* self_ptr = CVARR(self); - CvSize size = cvGetSize(self_ptr); - int type = CV_MAKETYPE(CV_32F, 1); - velx = cCvMat::new_object(size, type); - vely = cCvMat::new_object(size, type); - cvCalcOpticalFlowLK(CVMAT_WITH_CHECK(prev), self_ptr, VALUE_TO_CVSIZE(win_size), - CVARR(velx), CVARR(vely)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, velx, vely); -} - -/* - * call-seq: - * optical_flow_bm(prev[,velx = nil][,vely = nil][,option]) -> [cvmat, cvmat] - * - * Calculates optical flow for two images (previous -> self) using block matching method. - * Return horizontal component of the optical flow and vertical component of the optical flow. - * prev is previous image. - * velx is previous velocity field of x-axis, and vely is previous velocity field of y-axis. - * - * options - * * :block_size -> should be CvSize (default is CvSize(4,4)) - * Size of basic blocks that are compared. - * * :shift_size -> should be CvSize (default is CvSize(1,1)) - * Block coordinate increments. - * * :max_range -> should be CvSize (default is CVSize(4,4)) - * Size of the scanned neighborhood in pixels around block. - * note: option's default value is CvMat::OPTICAL_FLOW_BM_OPTION. - * - * Velocity is computed for every block, but not for every pixel, - * so velocity image pixels correspond to input image blocks. - * input/output velocity field's size should be (self.width / block_size.width)x(self.height / block_size.height). - * e.g. image.size is 320x240 and block_size is 4x4, velocity field's size is 80x60. - * - */ -VALUE -rb_optical_flow_bm(int argc, VALUE *argv, VALUE self) -{ - VALUE prev, velx, vely, options; - rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options); - options = OPTICAL_FLOW_BM_OPTION(options); - CvArr* self_ptr = CVARR(self); - CvSize block_size = BM_BLOCK_SIZE(options); - CvSize shift_size = BM_SHIFT_SIZE(options); - CvSize max_range = BM_MAX_RANGE(options); - - int use_previous = 0; - try { - CvSize image_size = cvGetSize(self_ptr); - CvSize velocity_size = cvSize((image_size.width - block_size.width + shift_size.width) / shift_size.width, - (image_size.height - block_size.height + shift_size.height) / shift_size.height); - CvMat *velx_ptr, *vely_ptr; - if (NIL_P(velx) && NIL_P(vely)) { - int type = CV_MAKETYPE(CV_32F, 1); - velx = cCvMat::new_object(velocity_size, type); - vely = cCvMat::new_object(velocity_size, type); - velx_ptr = CVMAT(velx); - vely_ptr = CVMAT(vely); - } - else { - use_previous = 1; - velx_ptr = CVMAT_WITH_CHECK(velx); - vely_ptr = CVMAT_WITH_CHECK(vely); - } - cvCalcOpticalFlowBM(CVMAT_WITH_CHECK(prev), self_ptr, - block_size, shift_size, max_range, use_previous, - velx_ptr, vely_ptr); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return rb_ary_new3(2, velx, vely); -} - -/* - * call-seq: - * CvMat.find_fundamental_mat(points1, points2[,options = {}]) -> fundamental_matrix(cvmat) or nil - * - * Calculates fundamental matrix from corresponding points. - * Size of the output fundamental matrix is 3x3 or 9x3 (7-point method may return up to 3 matrices) - * - * points1 and points2 should be 2xN, Nx2, 3xN or Nx3 1-channel, or 1xN or Nx1 multi-channel matrix. - * method is method for computing the fundamental matrix - * - CV_FM_7POINT for a 7-point algorithm. (N = 7) - * - CV_FM_8POINT for an 8-point algorithm. (N >= 8) - * - CV_FM_RANSAC for the RANSAC algorithm. (N >= 8) - * - CV_FM_LMEDS for the LMedS algorithm. (N >= 8) - * option should be Hash include these keys. - * :with_status (true or false) - * If set true, return fundamental_matrix and status. [fundamental_matrix, status] - * Otherwise return fundamental matrix only(default). - * :maximum_distance - * The parameter is used for RANSAC. It is the maximum distance from point to epipolar line in pixels, beyond which the point is considered an outlier and is not used for computing the final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the point localization, image resolution and the image noise. - * :desirable_level - * The optional output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in RANSAC and LMedS methods. For other methods it is set to all 1's. - * - * note: option's default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION. - */ -VALUE -rb_find_fundamental_mat(int argc, VALUE *argv, VALUE klass) -{ - VALUE points1, points2, method, option, fundamental_matrix, status; - int num = 0; - rb_scan_args(argc, argv, "31", &points1, &points2, &method, &option); - option = FIND_FUNDAMENTAL_MAT_OPTION(option); - int fm_method = FIX2INT(method); - CvMat *points1_ptr = CVMAT_WITH_CHECK(points1); - if (fm_method == CV_FM_7POINT) - fundamental_matrix = cCvMat::new_object(9, 3, CV_MAT_DEPTH(points1_ptr->type)); - else - fundamental_matrix = cCvMat::new_object(3, 3, CV_MAT_DEPTH(points1_ptr->type)); - - if (FFM_WITH_STATUS(option)) { - int status_len = (points1_ptr->rows > points1_ptr->cols) ? points1_ptr->rows : points1_ptr->cols; - status = cCvMat::new_object(1, status_len, CV_8UC1); - try { - num = cvFindFundamentalMat(points1_ptr, CVMAT_WITH_CHECK(points2), CVMAT(fundamental_matrix), fm_method, - FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), CVMAT(status)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status); - } - else { - try { - num = cvFindFundamentalMat(points1_ptr, CVMAT_WITH_CHECK(points2), CVMAT(fundamental_matrix), fm_method, - FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return num == 0 ? Qnil : fundamental_matrix; - } -} - - -/* - * call-seq: - * CvMat.compute_correspond_epilines(points, which_image, fundamental_matrix) -> correspondent_lines(cvmat) - * - * For points in one image of stereo pair computes the corresponding epilines in the other image. - * Finds equation of a line that contains the corresponding point (i.e. projection of the same 3D point) - * in the other image. Each line is encoded by a vector of 3 elements l=[a,b,c]T, so that: - * lT*[x, y, 1]T=0, - * or - * a*x + b*y + c = 0 - * From the fundamental matrix definition (see cvFindFundamentalMatrix discussion), line l2 for a point p1 in the first image (which_image=1) can be computed as: - * l2=F*p1 - * and the line l1 for a point p2 in the second image (which_image=1) can be computed as: - * l1=FT*p2 - * Line coefficients are defined up to a scale. They are normalized (a2+b2=1) are stored into correspondent_lines. - */ -VALUE -rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_image, VALUE fundamental_matrix) -{ - VALUE correspondent_lines; - CvMat* points_ptr = CVMAT_WITH_CHECK(points); - int n; - if (points_ptr->cols <= 3 && points_ptr->rows >= 7) - n = points_ptr->rows; - else if (points_ptr->rows <= 3 && points_ptr->cols >= 7) - n = points_ptr->cols; - else - rb_raise(rb_eArgError, "input points should 2xN, Nx2 or 3xN, Nx3 matrix(N >= 7)."); - - correspondent_lines = cCvMat::new_object(n, 3, CV_MAT_DEPTH(points_ptr->type)); - try { - cvComputeCorrespondEpilines(points_ptr, NUM2INT(which_image), CVMAT_WITH_CHECK(fundamental_matrix), - CVMAT(correspondent_lines)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - return correspondent_lines; -} - -/* - * call-seq: - * extract_surf(params[,mask]) -> [cvseq(cvsurfpoint), array(float)] - * Extracts Speeded Up Robust Features from an image - * - * params (CvSURFParams) - Various algorithm parameters put to the structure CvSURFParams. - * mask (CvMat) - The optional input 8-bit mask. The features are only found in the areas that contain more than 50% of non-zero mask pixels. - */ -VALUE -rb_extract_surf(int argc, VALUE *argv, VALUE self) -{ - VALUE _params, _mask; - rb_scan_args(argc, argv, "11", &_params, &_mask); - - // Prepare arguments - CvSURFParams params = *CVSURFPARAMS_WITH_CHECK(_params); - CvMat* mask = MASK(_mask); - VALUE storage = cCvMemStorage::new_object(); - CvSeq* keypoints = NULL; - CvSeq* descriptors = NULL; - - // Compute SURF keypoints and descriptors - try { - cvExtractSURF(CVARR(self), mask, &keypoints, &descriptors, CVMEMSTORAGE(storage), - params, 0); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - VALUE _keypoints = cCvSeq::new_sequence(cCvSeq::rb_class(), keypoints, cCvSURFPoint::rb_class(), storage); - - // Create descriptor array - const int DIM_SIZE = (params.extended) ? 128 : 64; - const int NUM_KEYPOINTS = keypoints->total; - VALUE _descriptors = rb_ary_new2(NUM_KEYPOINTS); - for (int m = 0; m < NUM_KEYPOINTS; ++m) { - VALUE elem = rb_ary_new2(DIM_SIZE); - float *descriptor = (float*)cvGetSeqElem(descriptors, m); - for (int n = 0; n < DIM_SIZE; ++n) { - rb_ary_store(elem, n, rb_float_new(descriptor[n])); - } - rb_ary_store(_descriptors, m, elem); - } - - return rb_assoc_new(_keypoints, _descriptors); -} - - -/* - * call-seq: - * subspace_project(w, mean) -> cvmat - */ -VALUE -rb_subspace_project(VALUE self, VALUE w, VALUE mean) -{ - VALUE projection; - try { - cv::Mat w_mat(CVMAT_WITH_CHECK(w)); - cv::Mat mean_mat(CVMAT_WITH_CHECK(mean)); - cv::Mat self_mat(CVMAT(self)); - cv::Mat pmat = cv::subspaceProject(w_mat, mean_mat, self_mat); - projection = new_object(pmat.rows, pmat.cols, pmat.type()); - CvMat tmp = pmat; - cvCopy(&tmp, CVMAT(projection)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return projection; -} - -/* - * call-seq: - * subspace_reconstruct(w, mean) -> cvmat - */ -VALUE -rb_subspace_reconstruct(VALUE self, VALUE w, VALUE mean) -{ - VALUE result; - try { - cv::Mat w_mat(CVMAT_WITH_CHECK(w)); - cv::Mat mean_mat(CVMAT_WITH_CHECK(mean)); - cv::Mat self_mat(CVMAT(self)); - cv::Mat rmat = cv::subspaceReconstruct(w_mat, mean_mat, self_mat); - result = new_object(rmat.rows, rmat.cols, rmat.type()); - CvMat tmp = rmat; - cvCopy(&tmp, CVMAT(result)); - } - catch (cv::Exception& e) { - raise_cverror(e); - } - - return result; -} - -VALUE -new_object(int rows, int cols, int type) -{ - return OPENCV_OBJECT(rb_klass, rb_cvCreateMat(rows, cols, type)); -} - -VALUE -new_object(CvSize size, int type) -{ - return OPENCV_OBJECT(rb_klass, rb_cvCreateMat(size.height, size.width, type)); -} - -VALUE -new_mat_kind_object(CvSize size, VALUE ref_obj) -{ - VALUE return_type = CLASS_OF(ref_obj); - if (rb_obj_is_kind_of(ref_obj, cIplImage::rb_class())) { - IplImage* img = IPLIMAGE(ref_obj); - return OPENCV_OBJECT(return_type, rb_cvCreateImage(size, img->depth, img->nChannels)); - } - else if (rb_obj_is_kind_of(ref_obj, rb_klass)) // CvMat - return OPENCV_OBJECT(return_type, rb_cvCreateMat(size.height, size.width, cvGetElemType(CVMAT(ref_obj)))); - else - rb_raise(rb_eNotImpError, "Only CvMat or IplImage are supported"); - - return Qnil; -} - -VALUE -new_mat_kind_object(CvSize size, VALUE ref_obj, int cvmat_depth, int channel) -{ - VALUE return_type = CLASS_OF(ref_obj); - if (rb_obj_is_kind_of(ref_obj, cIplImage::rb_class())) { - return OPENCV_OBJECT(return_type, rb_cvCreateImage(size, CV2IPL_DEPTH(cvmat_depth), channel)); - } - else if (rb_obj_is_kind_of(ref_obj, rb_klass)) // CvMat - return OPENCV_OBJECT(return_type, rb_cvCreateMat(size.height, size.width, - CV_MAKETYPE(cvmat_depth, channel))); - else - rb_raise(rb_eNotImpError, "Only CvMat or IplImage are supported"); - - return Qnil; -} - __NAMESPACE_END_OPENCV __NAMESPACE_END_CVMAT + diff --git a/ext/opencv/cvmat.h b/ext/opencv/cvmat.h index 900be16..2046040 100644 --- a/ext/opencv/cvmat.h +++ b/ext/opencv/cvmat.h @@ -21,7 +21,7 @@ __NAMESPACE_BEGIN_CVMAT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); @@ -177,7 +177,7 @@ VALUE rb_warp_affine(int argc, VALUE *argv, VALUE self); VALUE rb_rotation_matrix2D(VALUE self, VALUE center, VALUE angle, VALUE scale); VALUE rb_get_perspective_transform(VALUE self, VALUE source, VALUE dest); VALUE rb_warp_perspective(int argc, VALUE *argv, VALUE self); -VALUE rb_find_homograpy(int argc, VALUE *argv, VALUE self); +VALUE rb_find_homography(int argc, VALUE *argv, VALUE self); VALUE rb_remap(int argc, VALUE *argv, VALUE self); VALUE rb_log_polar(int argc, VALUE *argv, VALUE self); @@ -221,7 +221,6 @@ VALUE rb_apply_color_map(VALUE self, VALUE colormap); /* Matching*/ VALUE rb_match_template(int argc, VALUE *argv, VALUE self); VALUE rb_match_shapes(int argc, VALUE *argv, VALUE self); -VALUE rb_match_descriptors(int argc, VALUE *argv, VALUE self); /* Object Tracking */ VALUE rb_mean_shift(VALUE self, VALUE window, VALUE criteria); diff --git a/ext/opencv/cvmatnd.cpp b/ext/opencv/cvmatnd.cpp deleted file mode 100644 index 6a2d310..0000000 --- a/ext/opencv/cvmatnd.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************** - - cvmatnd.cpp - - - $Author: lsxi $ - - Copyright (C) 2007 Masakazu Yonekura - -************************************************************/ -#include "cvmatnd.h" -/* - * Document-class: OpenCV::CvMatND - * - */ -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVMATND - -VALUE rb_klass; - -VALUE -rb_class() -{ - return rb_klass; -} - -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvmat = rb_define_class_under(opencv, "CvMat", rb_cObject); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(), cvmat = cCvMat::rb_class(); - - rb_klass = rb_define_class_under(opencv, "CvMatND", cvmat); -} - -__NAMESPACE_END_CVMATND -__NAMESPACE_END_OPENCV - diff --git a/ext/opencv/cvmatnd.h b/ext/opencv/cvmatnd.h deleted file mode 100644 index a50a872..0000000 --- a/ext/opencv/cvmatnd.h +++ /dev/null @@ -1,28 +0,0 @@ -/************************************************************ - - cvmatnd.h - - - $Author: lsxi $ - - Copyright (C) 2007 Masakazu Yonekura - -************************************************************/ -#ifndef RUBY_OPENCV_CVMATND_H -#define RUBY_OPENCV_CVMATND_H - -#include "opencv.h" - -#define __NAMESPACE_BEGIN_CVMATND namespace cCvMatND { -#define __NAMESPACE_END_CVMATND } - -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVMATND - -VALUE rb_class(); - -void define_ruby_class(); - -__NAMESPACE_END_CVMATND -__NAMESPACE_END_OPENCV - -#endif // RUBY_OPENCV_CVMATND_H diff --git a/ext/opencv/cvmemstorage.cpp b/ext/opencv/cvmemstorage.cpp index 3623f2b..79c0afa 100644 --- a/ext/opencv/cvmemstorage.cpp +++ b/ext/opencv/cvmemstorage.cpp @@ -24,20 +24,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvMemStorage", rb_cObject); -} - VALUE rb_allocate(VALUE klass) { @@ -63,6 +49,25 @@ new_object(int blocksize) return Data_Wrap_Struct(rb_klass, 0, cvmemstorage_free, storage); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvMemStorage", rb_cObject); +} __NAMESPACE_END_CVMEMSTORAGE __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvmemstorage.h b/ext/opencv/cvmemstorage.h index fa147b5..7dcefe6 100644 --- a/ext/opencv/cvmemstorage.h +++ b/ext/opencv/cvmemstorage.h @@ -18,7 +18,7 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVMEMSTORAGE -void define_ruby_class(); +void init_ruby_class(); VALUE rb_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvmoments.cpp b/ext/opencv/cvmoments.cpp index 2e4a2e8..8ac2c96 100644 --- a/ext/opencv/cvmoments.cpp +++ b/ext/opencv/cvmoments.cpp @@ -30,50 +30,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvMoments", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "spatial", RUBY_METHOD_FUNC(rb_spatial), 2); - rb_define_method(rb_klass, "central", RUBY_METHOD_FUNC(rb_central), 2); - rb_define_method(rb_klass, "normalized_central", RUBY_METHOD_FUNC(rb_normalized_central), 2); - rb_define_method(rb_klass, "hu", RUBY_METHOD_FUNC(rb_hu), 0); - rb_define_method(rb_klass, "gravity_center", RUBY_METHOD_FUNC(rb_gravity_center), 0); - rb_define_method(rb_klass, "angle", RUBY_METHOD_FUNC(rb_angle), 0); - - DEFINE_CVMOMENTS_ACCESSOR(m00); - DEFINE_CVMOMENTS_ACCESSOR(m10); - DEFINE_CVMOMENTS_ACCESSOR(m01); - DEFINE_CVMOMENTS_ACCESSOR(m20); - DEFINE_CVMOMENTS_ACCESSOR(m11); - DEFINE_CVMOMENTS_ACCESSOR(m02); - DEFINE_CVMOMENTS_ACCESSOR(m30); - DEFINE_CVMOMENTS_ACCESSOR(m21); - DEFINE_CVMOMENTS_ACCESSOR(m12); - DEFINE_CVMOMENTS_ACCESSOR(m03); - - DEFINE_CVMOMENTS_ACCESSOR(mu20); - DEFINE_CVMOMENTS_ACCESSOR(mu11); - DEFINE_CVMOMENTS_ACCESSOR(mu02); - DEFINE_CVMOMENTS_ACCESSOR(mu30); - DEFINE_CVMOMENTS_ACCESSOR(mu21); - DEFINE_CVMOMENTS_ACCESSOR(mu12); - DEFINE_CVMOMENTS_ACCESSOR(mu03); - - DEFINE_CVMOMENTS_ACCESSOR(inv_sqrt_m00); -} - VALUE rb_allocate(VALUE klass) { @@ -82,7 +38,7 @@ rb_allocate(VALUE klass) } /* * call-seq: - * CvMoments.new(src[,is_binary = nil]) + * CvMoments.new(src[,is_binary = nil]) * * Calculates all moments up to third order of a polygon or rasterized shape. * src should be CvMat or CvPolygon. @@ -283,5 +239,55 @@ new_object(CvArr *arr, int is_binary = 0) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvMoments", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "spatial", RUBY_METHOD_FUNC(rb_spatial), 2); + rb_define_method(rb_klass, "central", RUBY_METHOD_FUNC(rb_central), 2); + rb_define_method(rb_klass, "normalized_central", RUBY_METHOD_FUNC(rb_normalized_central), 2); + rb_define_method(rb_klass, "hu", RUBY_METHOD_FUNC(rb_hu), 0); + rb_define_method(rb_klass, "gravity_center", RUBY_METHOD_FUNC(rb_gravity_center), 0); + rb_define_method(rb_klass, "angle", RUBY_METHOD_FUNC(rb_angle), 0); + + DEFINE_CVMOMENTS_ACCESSOR(m00); + DEFINE_CVMOMENTS_ACCESSOR(m10); + DEFINE_CVMOMENTS_ACCESSOR(m01); + DEFINE_CVMOMENTS_ACCESSOR(m20); + DEFINE_CVMOMENTS_ACCESSOR(m11); + DEFINE_CVMOMENTS_ACCESSOR(m02); + DEFINE_CVMOMENTS_ACCESSOR(m30); + DEFINE_CVMOMENTS_ACCESSOR(m21); + DEFINE_CVMOMENTS_ACCESSOR(m12); + DEFINE_CVMOMENTS_ACCESSOR(m03); + + DEFINE_CVMOMENTS_ACCESSOR(mu20); + DEFINE_CVMOMENTS_ACCESSOR(mu11); + DEFINE_CVMOMENTS_ACCESSOR(mu02); + DEFINE_CVMOMENTS_ACCESSOR(mu30); + DEFINE_CVMOMENTS_ACCESSOR(mu21); + DEFINE_CVMOMENTS_ACCESSOR(mu12); + DEFINE_CVMOMENTS_ACCESSOR(mu03); + + DEFINE_CVMOMENTS_ACCESSOR(inv_sqrt_m00); +} + __NAMESPACE_END_CVMOMENTS __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvmoments.h b/ext/opencv/cvmoments.h index 809c953..700a248 100644 --- a/ext/opencv/cvmoments.h +++ b/ext/opencv/cvmoments.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVMOMENTS VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvpoint.cpp b/ext/opencv/cvpoint.cpp index 511c427..99fe431 100644 --- a/ext/opencv/cvpoint.cpp +++ b/ext/opencv/cvpoint.cpp @@ -31,32 +31,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvPoint", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); - rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); - rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); - rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); - - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - /* * call-seq: * combatible?(obj) @@ -224,5 +198,37 @@ new_object(CvPoint point) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvPoint", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); + rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); + rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); + rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVPOINT __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvpoint.h b/ext/opencv/cvpoint.h index e11ca45..d72d43f 100644 --- a/ext/opencv/cvpoint.h +++ b/ext/opencv/cvpoint.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVPOINT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvpoint2d32f.cpp b/ext/opencv/cvpoint2d32f.cpp index b2ce550..836e6ad 100644 --- a/ext/opencv/cvpoint2d32f.cpp +++ b/ext/opencv/cvpoint2d32f.cpp @@ -31,32 +31,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvPoint2D32f", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); - rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); - rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); - rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); - - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - /* * call-seq: * combatible?(obj) @@ -207,5 +181,36 @@ new_object(CvPoint2D32f point) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvPoint2D32f", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); + rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); + rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); + rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVPOINT2D32F __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvpoint2d32f.h b/ext/opencv/cvpoint2d32f.h index 00ad613..7635c1f 100644 --- a/ext/opencv/cvpoint2d32f.h +++ b/ext/opencv/cvpoint2d32f.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVPOINT2D32F VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvpoint3d32f.cpp b/ext/opencv/cvpoint3d32f.cpp index f24e0f4..5a3f646 100644 --- a/ext/opencv/cvpoint3d32f.cpp +++ b/ext/opencv/cvpoint3d32f.cpp @@ -32,35 +32,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvpoint2d32f = rb_define_class_under(opencv, "CvPoint2D32f", rb_cObject); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - VALUE cvpoint2d32f = cCvPoint2D32f::rb_class(); - rb_klass = rb_define_class_under(opencv, "CvPoint3D32f", cvpoint2d32f); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); - rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); - rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); - rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); - rb_define_method(rb_klass, "z", RUBY_METHOD_FUNC(rb_z), 0); - rb_define_method(rb_klass, "z=", RUBY_METHOD_FUNC(rb_set_z), 1); - - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - /* * call-seq: * combatible?(obj) @@ -241,5 +212,41 @@ new_object(CvPoint3D32f point) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvpoint2d32f = rb_define_class_under(opencv, "CvPoint2D32f", rb_cObject); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * cvpoint2d32f = rb_define_class_under(opencv, "CvPoint2D32f", rb_cObject); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + VALUE cvpoint2d32f = cCvPoint2D32f::rb_class(); + rb_klass = rb_define_class_under(opencv, "CvPoint3D32f", cvpoint2d32f); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); + rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); + rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); + rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); + rb_define_method(rb_klass, "z", RUBY_METHOD_FUNC(rb_z), 0); + rb_define_method(rb_klass, "z=", RUBY_METHOD_FUNC(rb_set_z), 1); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVPOINT3D32F __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvpoint3d32f.h b/ext/opencv/cvpoint3d32f.h index d80c64a..3d225cf 100644 --- a/ext/opencv/cvpoint3d32f.h +++ b/ext/opencv/cvpoint3d32f.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVPOINT3D32F VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvrect.cpp b/ext/opencv/cvrect.cpp index 9dfc106..47846b0 100644 --- a/ext/opencv/cvrect.cpp +++ b/ext/opencv/cvrect.cpp @@ -34,39 +34,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvRect", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_singleton_method(rb_klass, "max_rect", RUBY_METHOD_FUNC(rb_max_rect), 2); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - - rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); - rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); - rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); - rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); - rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); - rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); - rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); - rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); - rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); - rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); - rb_define_method(rb_klass, "top_left", RUBY_METHOD_FUNC(rb_top_left), 0); - rb_define_method(rb_klass, "top_right", RUBY_METHOD_FUNC(rb_top_right), 0); - rb_define_method(rb_klass, "bottom_left", RUBY_METHOD_FUNC(rb_bottom_left), 0); - rb_define_method(rb_klass, "bottom_right", RUBY_METHOD_FUNC(rb_bottom_right), 0); -} - /* * call-seq: * combatible?(obj) @@ -329,5 +296,43 @@ new_object(CvRect rect) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvRect", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_singleton_method(rb_klass, "max_rect", RUBY_METHOD_FUNC(rb_max_rect), 2); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + + rb_define_method(rb_klass, "x", RUBY_METHOD_FUNC(rb_x), 0); + rb_define_method(rb_klass, "x=", RUBY_METHOD_FUNC(rb_set_x), 1); + rb_define_method(rb_klass, "y", RUBY_METHOD_FUNC(rb_y), 0); + rb_define_method(rb_klass, "y=", RUBY_METHOD_FUNC(rb_set_y), 1); + rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); + rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); + rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); + rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); + rb_define_method(rb_klass, "center", RUBY_METHOD_FUNC(rb_center), 0); + rb_define_method(rb_klass, "points", RUBY_METHOD_FUNC(rb_points), 0); + rb_define_method(rb_klass, "top_left", RUBY_METHOD_FUNC(rb_top_left), 0); + rb_define_method(rb_klass, "top_right", RUBY_METHOD_FUNC(rb_top_right), 0); + rb_define_method(rb_klass, "bottom_left", RUBY_METHOD_FUNC(rb_bottom_left), 0); + rb_define_method(rb_klass, "bottom_right", RUBY_METHOD_FUNC(rb_bottom_right), 0); +} + __NAMESPACE_END_CVRECT __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvrect.h b/ext/opencv/cvrect.h index 01f6a6c..8f54b2c 100644 --- a/ext/opencv/cvrect.h +++ b/ext/opencv/cvrect.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVRECT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); VALUE rb_max_rect(VALUE klass, VALUE rect1, VALUE rect2); diff --git a/ext/opencv/cvscalar.cpp b/ext/opencv/cvscalar.cpp index f81910b..55565a5 100644 --- a/ext/opencv/cvscalar.cpp +++ b/ext/opencv/cvscalar.cpp @@ -42,50 +42,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvScalar", rb_cObject); - /* CvScalar: class */ - rb_define_const(opencv, "CvColor", rb_klass); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); - rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); - rb_define_method(rb_klass, "sub", RUBY_METHOD_FUNC(rb_sub), -1); - rb_define_alias(rb_klass, "-", "sub"); - - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); - - rb_define_const(rb_klass, "Black", cCvScalar::new_object(cvScalar(0x0,0x0,0x0))); - rb_define_const(rb_klass, "Silver", cCvScalar::new_object(cvScalar(0x0c,0x0c,0x0c))); - rb_define_const(rb_klass, "Gray", cCvScalar::new_object(cvScalar(0x80,0x80,0x80))); - rb_define_const(rb_klass, "White", cCvScalar::new_object(cvScalar(0xff,0xff,0xff))); - rb_define_const(rb_klass, "Maroon", cCvScalar::new_object(cvScalar(0x0,0x0,0x80))); - rb_define_const(rb_klass, "Red", cCvScalar::new_object(cvScalar(0x0,0x0,0xff))); - rb_define_const(rb_klass, "Purple", cCvScalar::new_object(cvScalar(0x80,0x0,0x80))); - rb_define_const(rb_klass, "Fuchsia", cCvScalar::new_object(cvScalar(0xff,0x0,0xff))); - rb_define_const(rb_klass, "Green", cCvScalar::new_object(cvScalar(0x0,0x80,0x0))); - rb_define_const(rb_klass, "Lime", cCvScalar::new_object(cvScalar(0x0,0xff,0x0))); - rb_define_const(rb_klass, "Olive", cCvScalar::new_object(cvScalar(0x0,0x80,0x80))); - rb_define_const(rb_klass, "Yellow", cCvScalar::new_object(cvScalar(0x0,0xff,0xff))); - rb_define_const(rb_klass, "Navy", cCvScalar::new_object(cvScalar(0x80,0x0,0x0))); - rb_define_const(rb_klass, "Blue", cCvScalar::new_object(cvScalar(0xff,0x0,0x0))); - rb_define_const(rb_klass, "Teal", cCvScalar::new_object(cvScalar(0x80,0x80,0x0))); - rb_define_const(rb_klass, "Aqua", cCvScalar::new_object(cvScalar(0xff,0xff,0x0))); -} - VALUE rb_allocate(VALUE klass) { @@ -95,7 +51,7 @@ rb_allocate(VALUE klass) /* * call-seq: - * new([d1][,d2][,d3][,d4]) + * new([d1][,d2][,d3][,d4]) * * Create new Scalar. Argument should be Fixnum (or nil as 0). */ @@ -231,6 +187,55 @@ new_object(CvScalar scalar) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvScalar", rb_cObject); + /* CvScalar: class */ + rb_define_const(opencv, "CvColor", rb_klass); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); + rb_define_method(rb_klass, "sub", RUBY_METHOD_FUNC(rb_sub), -1); + rb_define_alias(rb_klass, "-", "sub"); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); + + rb_define_const(rb_klass, "Black", cCvScalar::new_object(cvScalar(0x0,0x0,0x0))); + rb_define_const(rb_klass, "Silver", cCvScalar::new_object(cvScalar(0x0c,0x0c,0x0c))); + rb_define_const(rb_klass, "Gray", cCvScalar::new_object(cvScalar(0x80,0x80,0x80))); + rb_define_const(rb_klass, "White", cCvScalar::new_object(cvScalar(0xff,0xff,0xff))); + rb_define_const(rb_klass, "Maroon", cCvScalar::new_object(cvScalar(0x0,0x0,0x80))); + rb_define_const(rb_klass, "Red", cCvScalar::new_object(cvScalar(0x0,0x0,0xff))); + rb_define_const(rb_klass, "Purple", cCvScalar::new_object(cvScalar(0x80,0x0,0x80))); + rb_define_const(rb_klass, "Fuchsia", cCvScalar::new_object(cvScalar(0xff,0x0,0xff))); + rb_define_const(rb_klass, "Green", cCvScalar::new_object(cvScalar(0x0,0x80,0x0))); + rb_define_const(rb_klass, "Lime", cCvScalar::new_object(cvScalar(0x0,0xff,0x0))); + rb_define_const(rb_klass, "Olive", cCvScalar::new_object(cvScalar(0x0,0x80,0x80))); + rb_define_const(rb_klass, "Yellow", cCvScalar::new_object(cvScalar(0x0,0xff,0xff))); + rb_define_const(rb_klass, "Navy", cCvScalar::new_object(cvScalar(0x80,0x0,0x0))); + rb_define_const(rb_klass, "Blue", cCvScalar::new_object(cvScalar(0xff,0x0,0x0))); + rb_define_const(rb_klass, "Teal", cCvScalar::new_object(cvScalar(0x80,0x80,0x0))); + rb_define_const(rb_klass, "Aqua", cCvScalar::new_object(cvScalar(0xff,0xff,0x0))); +} + __NAMESPACE_END_CVSCALAR __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvscalar.h b/ext/opencv/cvscalar.h index 42638d1..fcdcc81 100644 --- a/ext/opencv/cvscalar.h +++ b/ext/opencv/cvscalar.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSCALAR VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvseq.cpp b/ext/opencv/cvseq.cpp index 11865a3..a9da209 100644 --- a/ext/opencv/cvseq.cpp +++ b/ext/opencv/cvseq.cpp @@ -73,49 +73,6 @@ unregister_elem_class(void *ptr) } } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvSeq", rb_cObject); - rb_include_module(rb_klass, rb_mEnumerable); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "total", RUBY_METHOD_FUNC(rb_total), 0); - rb_define_alias(rb_klass, "length", "total"); - rb_define_alias(rb_klass, "size", "total"); - rb_define_method(rb_klass, "empty?", RUBY_METHOD_FUNC(rb_empty_q), 0); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); - rb_define_method(rb_klass, "first", RUBY_METHOD_FUNC(rb_first), 0); - rb_define_method(rb_klass, "last", RUBY_METHOD_FUNC(rb_last), 0); - - rb_define_method(rb_klass, "h_prev", RUBY_METHOD_FUNC(rb_h_prev), 0); - rb_define_method(rb_klass, "h_next", RUBY_METHOD_FUNC(rb_h_next), 0); - rb_define_method(rb_klass, "v_prev", RUBY_METHOD_FUNC(rb_v_prev), 0); - rb_define_method(rb_klass, "v_next", RUBY_METHOD_FUNC(rb_v_next), 0); - - rb_define_method(rb_klass, "push", RUBY_METHOD_FUNC(rb_push), -2); - rb_define_alias(rb_klass, "<<", "push"); - rb_define_method(rb_klass, "pop", RUBY_METHOD_FUNC(rb_pop), 0); - rb_define_method(rb_klass, "unshift", RUBY_METHOD_FUNC(rb_unshift), -2); - rb_define_alias(rb_klass, "push_front", "unshift"); - rb_define_method(rb_klass, "shift", RUBY_METHOD_FUNC(rb_shift), 0); - rb_define_alias(rb_klass, "pop_front", "shift"); - rb_define_method(rb_klass, "each", RUBY_METHOD_FUNC(rb_each), 0); - rb_define_method(rb_klass, "each_index", RUBY_METHOD_FUNC(rb_each_index), 0); - rb_define_method(rb_klass, "insert", RUBY_METHOD_FUNC(rb_insert), 2); - rb_define_method(rb_klass, "remove", RUBY_METHOD_FUNC(rb_remove), 1); - rb_define_alias(rb_klass, "delete_at", "remove"); - rb_define_method(rb_klass, "clear", RUBY_METHOD_FUNC(rb_clear), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -125,7 +82,7 @@ rb_allocate(VALUE klass) /* * call-seq: - * CvSeq.new(type[,storage]) + * CvSeq.new(type[,storage]) * * Return a new CvSeq. type should be following classes. * @@ -378,7 +335,7 @@ rb_seq_push(VALUE self, VALUE args, int flag) /* * call-seq: - * push(obj, ...) -> self + * push(obj, ...) -> self * * Append - Pushes the given object(s) on the end of this sequence. This expression return the sequence itself, * so several append may be chained together. @@ -542,7 +499,7 @@ rb_each_index(VALUE self) /* * call-seq: - * insert(index,obj) -> self + * insert(index,obj) -> self * * Inserts the given values before element with the given index (which may be negative). */ @@ -570,7 +527,7 @@ rb_insert(VALUE self, VALUE index, VALUE object) /* * call-seq: - * remove(index) -> obj or nil + * remove(index) -> obj or nil * * Deletes the elements at the specified index. */ @@ -595,5 +552,54 @@ new_sequence(VALUE klass, CvSeq *seq, VALUE element_klass, VALUE storage) return Data_Wrap_Struct(klass, mark_root_object, unregister_elem_class, seq); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvSeq", rb_cObject); + rb_include_module(rb_klass, rb_mEnumerable); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "total", RUBY_METHOD_FUNC(rb_total), 0); + rb_define_alias(rb_klass, "length", "total"); + rb_define_alias(rb_klass, "size", "total"); + rb_define_method(rb_klass, "empty?", RUBY_METHOD_FUNC(rb_empty_q), 0); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "first", RUBY_METHOD_FUNC(rb_first), 0); + rb_define_method(rb_klass, "last", RUBY_METHOD_FUNC(rb_last), 0); + + rb_define_method(rb_klass, "h_prev", RUBY_METHOD_FUNC(rb_h_prev), 0); + rb_define_method(rb_klass, "h_next", RUBY_METHOD_FUNC(rb_h_next), 0); + rb_define_method(rb_klass, "v_prev", RUBY_METHOD_FUNC(rb_v_prev), 0); + rb_define_method(rb_klass, "v_next", RUBY_METHOD_FUNC(rb_v_next), 0); + + rb_define_method(rb_klass, "push", RUBY_METHOD_FUNC(rb_push), -2); + rb_define_alias(rb_klass, "<<", "push"); + rb_define_method(rb_klass, "pop", RUBY_METHOD_FUNC(rb_pop), 0); + rb_define_method(rb_klass, "unshift", RUBY_METHOD_FUNC(rb_unshift), -2); + rb_define_alias(rb_klass, "push_front", "unshift"); + rb_define_method(rb_klass, "shift", RUBY_METHOD_FUNC(rb_shift), 0); + rb_define_alias(rb_klass, "pop_front", "shift"); + rb_define_method(rb_klass, "each", RUBY_METHOD_FUNC(rb_each), 0); + rb_define_method(rb_klass, "each_index", RUBY_METHOD_FUNC(rb_each_index), 0); + rb_define_method(rb_klass, "insert", RUBY_METHOD_FUNC(rb_insert), 2); + rb_define_method(rb_klass, "remove", RUBY_METHOD_FUNC(rb_remove), 1); + rb_define_alias(rb_klass, "delete_at", "remove"); + rb_define_method(rb_klass, "clear", RUBY_METHOD_FUNC(rb_clear), 0); +} + __NAMESPACE_END_CVSEQ __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvseq.h b/ext/opencv/cvseq.h index 9e58173..218ae5e 100644 --- a/ext/opencv/cvseq.h +++ b/ext/opencv/cvseq.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_CVSEQ VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE seqblock_class(void *ptr); void register_elem_class(CvSeq *seq, VALUE klass); diff --git a/ext/opencv/cvsize.cpp b/ext/opencv/cvsize.cpp index eb8e217..bf88a77 100644 --- a/ext/opencv/cvsize.cpp +++ b/ext/opencv/cvsize.cpp @@ -31,32 +31,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvSize", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); - rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); - rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); - rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); - - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - /* * call-seq: * compatible?(obj) @@ -217,5 +191,37 @@ new_object(CvSize size) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvSize", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); + rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); + rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); + rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVSIZE __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvsize.h b/ext/opencv/cvsize.h index 69fe820..a0b0c76 100644 --- a/ext/opencv/cvsize.h +++ b/ext/opencv/cvsize.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSIZE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvsize2d32f.cpp b/ext/opencv/cvsize2d32f.cpp index 1e1c70b..5b7a327 100644 --- a/ext/opencv/cvsize2d32f.cpp +++ b/ext/opencv/cvsize2d32f.cpp @@ -31,31 +31,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvSize2D32f", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); - rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); - rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); - rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); - rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - /* * call-seq: * compatible?(obj) @@ -205,5 +180,36 @@ new_object(CvSize2D32f size) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvSize2D32f", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "compatible?", RUBY_METHOD_FUNC(rb_compatible_q), 1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0); + rb_define_method(rb_klass, "width=", RUBY_METHOD_FUNC(rb_set_width), 1); + rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0); + rb_define_method(rb_klass, "height=", RUBY_METHOD_FUNC(rb_set_height), 1); + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVSIZE2D32F __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvsize2d32f.h b/ext/opencv/cvsize2d32f.h index 679e282..d025e89 100644 --- a/ext/opencv/cvsize2d32f.h +++ b/ext/opencv/cvsize2d32f.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSIZE2D32F VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_compatible_q(VALUE klass, VALUE object); diff --git a/ext/opencv/cvslice.cpp b/ext/opencv/cvslice.cpp index 8e9088c..29e85b8 100644 --- a/ext/opencv/cvslice.cpp +++ b/ext/opencv/cvslice.cpp @@ -9,7 +9,7 @@ ************************************************************/ #include "cvslice.h" /* - * Document-class: OpenCV::CvClice + * Document-class: OpenCV::CvSlice * * C structure is here, very simple. * typdef struct CvSlice { @@ -28,26 +28,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvSlice", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 2); - rb_define_method(rb_klass, "start_index", RUBY_METHOD_FUNC(rb_start_index_aref), 0); - rb_define_method(rb_klass, "end_index", RUBY_METHOD_FUNC(rb_end_index_aref), 0); - rb_define_method(rb_klass, "start_index=", RUBY_METHOD_FUNC(rb_start_index_aset), 1); - rb_define_method(rb_klass, "end_index=", RUBY_METHOD_FUNC(rb_end_index_aset), 1); -} - VALUE rb_allocate(VALUE klass) { @@ -57,7 +37,7 @@ rb_allocate(VALUE klass) /* * call-seq: - * new(start, end) + * new(start, end) * * Create new slice object. */ @@ -116,5 +96,31 @@ rb_end_index_aset(VALUE self, VALUE index) return self; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvSlice", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 2); + rb_define_method(rb_klass, "start_index", RUBY_METHOD_FUNC(rb_start_index_aref), 0); + rb_define_method(rb_klass, "end_index", RUBY_METHOD_FUNC(rb_end_index_aref), 0); + rb_define_method(rb_klass, "start_index=", RUBY_METHOD_FUNC(rb_start_index_aset), 1); + rb_define_method(rb_klass, "end_index=", RUBY_METHOD_FUNC(rb_end_index_aset), 1); +} + __NAMESPACE_END_CVSLICE __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvslice.h b/ext/opencv/cvslice.h index 5f89d97..f4851ec 100644 --- a/ext/opencv/cvslice.h +++ b/ext/opencv/cvslice.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSLICE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(VALUE self, VALUE start, VALUE end); diff --git a/ext/opencv/cvsparsemat.cpp b/ext/opencv/cvsparsemat.cpp deleted file mode 100644 index 5b9ab0f..0000000 --- a/ext/opencv/cvsparsemat.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************** - - cvsparse.cpp - - - $Author: lsxi $ - - Copyright (C) 2007 Masakazu Yonekura - -************************************************************/ -#include "cvsparsemat.h" -/* - * Document-class: OpenCV::CvSparseMat - * - */ -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVSPARSEMAT - -VALUE rb_klass; - -VALUE -rb_class() -{ - return rb_klass; -} - -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvmat = rb_define_class_under(opencv, "CvMat", rb_cObject); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(), cvmat = cCvMat::rb_class(); - - rb_klass = rb_define_class_under(opencv, "CvSparseMat", cvmat); -} - -__NAMESPACE_END_CVSPARSEMAT -__NAMESPACE_END_OPENCV - diff --git a/ext/opencv/cvsparsemat.h b/ext/opencv/cvsparsemat.h deleted file mode 100644 index 982fa12..0000000 --- a/ext/opencv/cvsparsemat.h +++ /dev/null @@ -1,28 +0,0 @@ -/************************************************************ - - cvsparsemat.h - - - $Author: lsxi $ - - Copyright (C) 2005-2006 Masakazu Yonekura - -************************************************************/ -#ifndef RUBY_OPENCV_CVSPARSEMAT_H -#define RUBY_OPENCV_CVSPARSEMAT_H - -#include "opencv.h" - -#define __NAMESPACE_BEGIN_CVSPARSEMAT namespace cCvSparseMat { -#define __NAMESPACE_END_CVSPARSEMAT } - -__NAMESPACE_BEGIN_OPENCV -__NAMESPACE_BEGIN_CVSPARSEMAT - -VALUE rb_class(); - -void define_ruby_class(); - -__NAMESPACE_END_CVSPARSEMAT -__NAMESPACE_END_OPENCV - -#endif // RUBY_OPENCV_CVSPARSEMAT_H diff --git a/ext/opencv/cvsurfparams.cpp b/ext/opencv/cvsurfparams.cpp index a493d54..3101789 100644 --- a/ext/opencv/cvsurfparams.cpp +++ b/ext/opencv/cvsurfparams.cpp @@ -30,30 +30,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvSURFParams", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "hessian_threshold", RUBY_METHOD_FUNC(rb_get_hessian_threshold), 0); - rb_define_method(rb_klass, "hessian_threshold=", RUBY_METHOD_FUNC(rb_set_hessian_threshold), 1); - rb_define_method(rb_klass, "extended", RUBY_METHOD_FUNC(rb_get_extended), 0); - rb_define_method(rb_klass, "extended=", RUBY_METHOD_FUNC(rb_set_extended), 1); - rb_define_method(rb_klass, "n_octaves", RUBY_METHOD_FUNC(rb_get_n_octaves), 0); - rb_define_method(rb_klass, "n_octaves=", RUBY_METHOD_FUNC(rb_set_n_octaves), 1); - rb_define_method(rb_klass, "n_octave_layers", RUBY_METHOD_FUNC(rb_get_n_octave_layers), 0); - rb_define_method(rb_klass, "n_octave_layers=", RUBY_METHOD_FUNC(rb_set_n_octave_layers), 1); -} - VALUE rb_allocate(VALUE klass) { @@ -61,11 +37,15 @@ rb_allocate(VALUE klass) return Data_Make_Struct(klass, CvSURFParams, 0, -1, ptr); } -/* - * call-seq: - * CvSURFParams.new(hessian_threshold[,extended=false,n_octaves=3,n_octave_layers=4]) -> cvsurfparams - * +/* * Create a CvSURFParams + * + * @overload CvSURFParams.new(hessian_threshold, extended = false, n_octaves = 3, n_octave_layers = 4) + * @param hessian_threshold [Number] + * @param extended [Boolean] If true, exteneded descriptors (128 elements each), + * otherwise basic descriptors (64 elements each) + * @param n_octaves [Integer] Number of octaves to be used for extraction + * @param n_octave_layers [Integer] Number of layers within each octave */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) @@ -194,6 +174,35 @@ new_object(CvSURFParams* cvsurfparams) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvSURFParams", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "hessian_threshold", RUBY_METHOD_FUNC(rb_get_hessian_threshold), 0); + rb_define_method(rb_klass, "hessian_threshold=", RUBY_METHOD_FUNC(rb_set_hessian_threshold), 1); + rb_define_method(rb_klass, "extended", RUBY_METHOD_FUNC(rb_get_extended), 0); + rb_define_method(rb_klass, "extended=", RUBY_METHOD_FUNC(rb_set_extended), 1); + rb_define_method(rb_klass, "n_octaves", RUBY_METHOD_FUNC(rb_get_n_octaves), 0); + rb_define_method(rb_klass, "n_octaves=", RUBY_METHOD_FUNC(rb_set_n_octaves), 1); + rb_define_method(rb_klass, "n_octave_layers", RUBY_METHOD_FUNC(rb_get_n_octave_layers), 0); + rb_define_method(rb_klass, "n_octave_layers=", RUBY_METHOD_FUNC(rb_set_n_octave_layers), 1); +} + __NAMESPACE_END_CVSURFPARAMS __NAMESPACE_END_OPENCV diff --git a/ext/opencv/cvsurfparams.h b/ext/opencv/cvsurfparams.h index d6772e1..ae4d008 100644 --- a/ext/opencv/cvsurfparams.h +++ b/ext/opencv/cvsurfparams.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSURFPARAMS VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvsurfpoint.cpp b/ext/opencv/cvsurfpoint.cpp index 84bca7e..4564270 100644 --- a/ext/opencv/cvsurfpoint.cpp +++ b/ext/opencv/cvsurfpoint.cpp @@ -35,32 +35,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvSURFPoint", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 5); - rb_define_method(rb_klass, "pt", RUBY_METHOD_FUNC(rb_get_pt), 0); - rb_define_method(rb_klass, "pt=", RUBY_METHOD_FUNC(rb_set_pt), 1); - rb_define_method(rb_klass, "laplacian", RUBY_METHOD_FUNC(rb_get_laplacian), 0); - rb_define_method(rb_klass, "laplacian=", RUBY_METHOD_FUNC(rb_set_laplacian), 1); - rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_get_size), 0); - rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); - rb_define_method(rb_klass, "dir", RUBY_METHOD_FUNC(rb_get_dir), 0); - rb_define_method(rb_klass, "dir=", RUBY_METHOD_FUNC(rb_set_dir), 1); - rb_define_method(rb_klass, "hessian", RUBY_METHOD_FUNC(rb_get_hessian), 0); - rb_define_method(rb_klass, "hessian=", RUBY_METHOD_FUNC(rb_set_hessian), 1); -} - VALUE rb_allocate(VALUE klass) { @@ -69,10 +43,18 @@ rb_allocate(VALUE klass) } /* - * call-seq: - * CvSURFPoint.new(pt,laplacian,size,dir,hessian) -> cvsurfpoint - * * Create a CvSURFPoint + * + * @overload new(pt, laplacian, size, dir, hessian) + * @param pt [CvPoint2D32f] Position of the feature within the image + * @param laplacian [Integer] -1, 0 or +1. sign of the laplacian at the point. + * Can be used to speedup feature comparison + * (normally features with laplacians of different signs can not match) + * @param size [Integer] Size of the feature + * @param dir [Number] Orientation of the feature: 0..360 degrees + * @param hessian [Number] Value of the hessian (can be used to + * approximately estimate the feature strengths) + * @return [CvSURFPoint] self */ VALUE rb_initialize(VALUE self, VALUE pt, VALUE laplacian, VALUE size, VALUE dir, VALUE hessian) @@ -88,9 +70,10 @@ rb_initialize(VALUE self, VALUE pt, VALUE laplacian, VALUE size, VALUE dir, VALU } /* - * call-seq: - * pt -> cvpoint2d32f * Return position of the feature as CvPoint2D32f. + * + * @overload pt + * @return [CvPoint2D32f] Position of the feature. */ VALUE rb_get_pt(VALUE self) @@ -99,10 +82,10 @@ rb_get_pt(VALUE self) } /* - * call-seq: - * pt = value - * - * Set position of the feature to value + * Set position of the feature. + * + * @overload pt=(value) + * @param value [CvPoint2D32f] Valuet to set. */ VALUE rb_set_pt(VALUE self, VALUE value) @@ -112,9 +95,10 @@ rb_set_pt(VALUE self, VALUE value) } /* - * call-seq: - * laplacian -> number * Return sign of the laplacian at the point (-1, 0 or +1) + * + * @overload laplacian + * @return [Integer] Sign of the laplacian at the point. */ VALUE rb_get_laplacian(VALUE self) @@ -123,9 +107,10 @@ rb_get_laplacian(VALUE self) } /* - * call-seq: - * laplacian = value (-1, 0 or +1) * Set sign of the laplacian at the point + * + * @overload laplacian=(value) + * @param value [Integer] Value to set. */ VALUE rb_set_laplacian(VALUE self, VALUE value) @@ -136,9 +121,10 @@ rb_set_laplacian(VALUE self, VALUE value) } /* - * call-seq: - * size -> number - * Return size of feature + * Returns size of feature. + * + * @overload size + * @return [Integer] Size of feature. */ VALUE rb_get_size(VALUE self) @@ -147,9 +133,10 @@ rb_get_size(VALUE self) } /* - * call-seq: - * size = value * Return size of feature + * + * @overload size=(value) + * @param [Integer] Value to set. */ VALUE rb_set_size(VALUE self, VALUE value) @@ -159,9 +146,10 @@ rb_set_size(VALUE self, VALUE value) } /* - * call-seq: - * dir -> number * Return orientation of the feature: 0..360 degrees + * + * @overload dir + * @return [Number] Orientation of the feature. */ VALUE rb_get_dir(VALUE self) @@ -170,9 +158,10 @@ rb_get_dir(VALUE self) } /* - * call-seq: - * dir = value - * Set orientation of the feature: 0..360 degrees + * Set orientation of the feature: 0..360 degrees. + * + * @overload dir=(value) + * @param [Number] Value to set. */ VALUE rb_set_dir(VALUE self, VALUE value) @@ -182,9 +171,10 @@ rb_set_dir(VALUE self, VALUE value) } /* - * call-seq: - * hessian -> number * Return value of the hessian + * + * @overload hessian + * @return [Number] Hessian */ VALUE rb_get_hessian(VALUE self) @@ -193,9 +183,10 @@ rb_get_hessian(VALUE self) } /* - * call-seq: - * hessian = value * Set value of the hessian + * + * @overload hessian=(value) + * @param [Number] Value to set. */ VALUE rb_set_hessian(VALUE self, VALUE value) @@ -219,5 +210,37 @@ new_object(CvSURFPoint* cvsurfpoint) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvSURFPoint", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 5); + rb_define_method(rb_klass, "pt", RUBY_METHOD_FUNC(rb_get_pt), 0); + rb_define_method(rb_klass, "pt=", RUBY_METHOD_FUNC(rb_set_pt), 1); + rb_define_method(rb_klass, "laplacian", RUBY_METHOD_FUNC(rb_get_laplacian), 0); + rb_define_method(rb_klass, "laplacian=", RUBY_METHOD_FUNC(rb_set_laplacian), 1); + rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_get_size), 0); + rb_define_method(rb_klass, "size=", RUBY_METHOD_FUNC(rb_set_size), 1); + rb_define_method(rb_klass, "dir", RUBY_METHOD_FUNC(rb_get_dir), 0); + rb_define_method(rb_klass, "dir=", RUBY_METHOD_FUNC(rb_set_dir), 1); + rb_define_method(rb_klass, "hessian", RUBY_METHOD_FUNC(rb_get_hessian), 0); + rb_define_method(rb_klass, "hessian=", RUBY_METHOD_FUNC(rb_set_hessian), 1); +} + __NAMESPACE_END_CVSURFPOINT __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvsurfpoint.h b/ext/opencv/cvsurfpoint.h index ce02f64..b652ae3 100644 --- a/ext/opencv/cvsurfpoint.h +++ b/ext/opencv/cvsurfpoint.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVSURFPOINT VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(VALUE self, VALUE pt, VALUE laplacian, VALUE size, VALUE dir, VALUE hessian); diff --git a/ext/opencv/cvtermcriteria.cpp b/ext/opencv/cvtermcriteria.cpp index 60fa83b..ef2e02a 100644 --- a/ext/opencv/cvtermcriteria.cpp +++ b/ext/opencv/cvtermcriteria.cpp @@ -29,32 +29,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvTermCriteria", rb_cObject); - /* CvTermCriteria: class */ - rb_define_const(opencv, "CvTerm", rb_klass); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "type", RUBY_METHOD_FUNC(rb_type), 0); - rb_define_method(rb_klass, "max", RUBY_METHOD_FUNC(rb_max), 0); - rb_define_method(rb_klass, "max=", RUBY_METHOD_FUNC(rb_set_max), 1); - rb_define_method(rb_klass, "eps", RUBY_METHOD_FUNC(rb_eps), 0); - rb_define_method(rb_klass, "eps=", RUBY_METHOD_FUNC(rb_set_eps), 1); - rb_define_alias(rb_klass, "epsilon", "eps"); - rb_define_alias(rb_klass, "epsilon=", "eps="); -} - VALUE rb_allocate(VALUE klass) { @@ -188,5 +162,37 @@ new_object(CvTermCriteria criteria) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvTermCriteria", rb_cObject); + /* CvTermCriteria: class */ + rb_define_const(opencv, "CvTerm", rb_klass); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "type", RUBY_METHOD_FUNC(rb_type), 0); + rb_define_method(rb_klass, "max", RUBY_METHOD_FUNC(rb_max), 0); + rb_define_method(rb_klass, "max=", RUBY_METHOD_FUNC(rb_set_max), 1); + rb_define_method(rb_klass, "eps", RUBY_METHOD_FUNC(rb_eps), 0); + rb_define_method(rb_klass, "eps=", RUBY_METHOD_FUNC(rb_set_eps), 1); + rb_define_alias(rb_klass, "epsilon", "eps"); + rb_define_alias(rb_klass, "epsilon=", "eps="); +} + __NAMESPACE_END_CVTERMCRITERIA __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvtermcriteria.h b/ext/opencv/cvtermcriteria.h index 0e74755..b780168 100644 --- a/ext/opencv/cvtermcriteria.h +++ b/ext/opencv/cvtermcriteria.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVTERMCRITERIA VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/cvtwopoints.cpp b/ext/opencv/cvtwopoints.cpp index 1be5c33..cc70201 100644 --- a/ext/opencv/cvtwopoints.cpp +++ b/ext/opencv/cvtwopoints.cpp @@ -9,7 +9,7 @@ ************************************************************/ #include "cvtwopoints.h" /* - * Document-class: OpenCV::CvTwopoints + * Document-class: OpenCV::CvTwoPoints * * This class means one twopoints on X axis Y axis. * X and Y takes the value of the Fixnum. see also CvTwopoints2D32F @@ -31,27 +31,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - - rb_klass = rb_define_class_under(opencv, "CvTwoPoints", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_method(rb_klass, "point1", RUBY_METHOD_FUNC(rb_point1), 0); - rb_define_method(rb_klass, "point2", RUBY_METHOD_FUNC(rb_point2), 0); - rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); - rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); - rb_define_alias(rb_klass, "to_a", "to_ary"); -} - VALUE rb_allocate(VALUE klass) { @@ -112,5 +91,32 @@ rb_to_ary(VALUE self) return rb_ary_new3(2, rb_point1(self), rb_point2(self)); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + + rb_klass = rb_define_class_under(opencv, "CvTwoPoints", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "point1", RUBY_METHOD_FUNC(rb_point1), 0); + rb_define_method(rb_klass, "point2", RUBY_METHOD_FUNC(rb_point2), 0); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "to_ary", RUBY_METHOD_FUNC(rb_to_ary), 0); + rb_define_alias(rb_klass, "to_a", "to_ary"); +} + __NAMESPACE_END_CVTWOPOINTS __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvtwopoints.h b/ext/opencv/cvtwopoints.h index 79177c2..2a1787a 100644 --- a/ext/opencv/cvtwopoints.h +++ b/ext/opencv/cvtwopoints.h @@ -26,7 +26,7 @@ __NAMESPACE_BEGIN_CVTWOPOINTS VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/cvvideowriter.cpp b/ext/opencv/cvvideowriter.cpp index a1f0d9a..dcd5531 100644 --- a/ext/opencv/cvvideowriter.cpp +++ b/ext/opencv/cvvideowriter.cpp @@ -26,27 +26,10 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "CvVideoWriter", rb_cObject); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "write", RUBY_METHOD_FUNC(rb_write), 1); - rb_define_method(rb_klass, "close", RUBY_METHOD_FUNC(rb_close), 0); -} - /* * call-seq: - * CvVideoWriter.new(filname, fourcc, fps, size[, is_color]) -> cvvideowriter - * CvVideoWriter.new(filname, fourcc, fps, size[, is_color]){|vw| ... } -> nil + * CvVideoWriter.new(filname, fourcc, fps, size[, is_color]) -> cvvideowriter + * CvVideoWriter.new(filname, fourcc, fps, size[, is_color]){|vw| ... } -> nil * * Open new video writer. If block given, writer is closed automatically when end of block. * @@ -98,7 +81,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * write(frame) + * write(frame) * * Write image as frame of video stream. * frame should be IplImage @@ -132,6 +115,28 @@ rb_close(VALUE self) return Qnil; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "CvVideoWriter", rb_cObject); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "write", RUBY_METHOD_FUNC(rb_write), 1); + rb_define_method(rb_klass, "close", RUBY_METHOD_FUNC(rb_close), 0); +} __NAMESPACE_END_CVVIDEOWRITER __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/cvvideowriter.h b/ext/opencv/cvvideowriter.h index ddd34fc..9e99daf 100644 --- a/ext/opencv/cvvideowriter.h +++ b/ext/opencv/cvvideowriter.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_CVVIDEOWRITER VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); VALUE rb_write(VALUE self, VALUE frame); diff --git a/ext/opencv/eigenfaces.cpp b/ext/opencv/eigenfaces.cpp index 456df83..69beb79 100644 --- a/ext/opencv/eigenfaces.cpp +++ b/ext/opencv/eigenfaces.cpp @@ -47,8 +47,15 @@ rb_initialize(int argc, VALUE argv[], VALUE self) } void -define_ruby_class() +init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE alghorithm = rb_define_class_under(opencv, "Algorithm", rb_cObject); + VALUE face_recognizer = rb_define_class_under(opencv, "FaceRecognizer", alghorithm); +#endif + if (rb_klass) return; /* @@ -57,7 +64,8 @@ define_ruby_class() * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "EigenFaces", cFaceRecognizer::rb_class()); + VALUE face_recognizer = cFaceRecognizer::rb_class(); + rb_klass = rb_define_class_under(opencv, "EigenFaces", face_recognizer); rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); } diff --git a/ext/opencv/eigenfaces.h b/ext/opencv/eigenfaces.h index 71a00c9..2884808 100644 --- a/ext/opencv/eigenfaces.h +++ b/ext/opencv/eigenfaces.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_EIGENFACES VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE argv[], VALUE self); __NAMESPACE_END_EIGENFACES diff --git a/ext/opencv/extconf.rb b/ext/opencv/extconf.rb index 8dc665e..f3720b6 100755 --- a/ext/opencv/extconf.rb +++ b/ext/opencv/extconf.rb @@ -1,4 +1,14 @@ #!/usr/bin/env ruby + +CC = RbConfig::CONFIG['CC'] +if CC =~ /clang/ + RbConfig::MAKEFILE_CONFIG['try_header'] = :try_cpp + RbConfig::CONFIG['CPP'] = "#{CC} -E" +elsif RbConfig::CONFIG['arch'] =~ /mswin32/ + RbConfig::MAKEFILE_CONFIG['try_header'] = :try_cpp + RbConfig::CONFIG['CPP'] = "#{CC} /P" +end + require "mkmf" def cv_version_suffix(incdir) @@ -46,6 +56,7 @@ when /mswin32/ warn "#{lib}.lib not found." unless have_library(lib) } $CFLAGS << ' /EHsc' + CONFIG['CXXFLAGS'] << ' /EHsc' when /mingw32/ suffix = cv_version_suffix(incdir) opencv_libraries.map! {|lib| lib + suffix } @@ -73,15 +84,7 @@ opencv_headers.each {|header| raise "#{header} not found." unless have_header(header) } opencv_headers_opt.each {|header| - unless have_header(header) - if CONFIG["arch"] =~ /mswin32/ and File.exists? "#{incdir}/#{header}" - # In mswin32, have_header('opencv2/nonfree/nonfree.hpp') fails because of a syntax problem. - warn "warning: #{header} found but `have_header` failed." - $defs << "-DHAVE_#{header.tr_cpp}" - else - warn "#{header} not found." - end - end + raise "#{header} not found." unless have_header(header) } have_header("stdarg.h") diff --git a/ext/opencv/facerecognizer.cpp b/ext/opencv/facerecognizer.cpp index d52a448..a6ae7f1 100644 --- a/ext/opencv/facerecognizer.cpp +++ b/ext/opencv/facerecognizer.cpp @@ -18,20 +18,19 @@ __NAMESPACE_BEGIN_FACERECOGNIZER VALUE rb_klass; -std::map< long, cv::Ptr > ptr_guard_map; +std::map > ptr_guard_map; void guard_facerecognizer(void* data_ptr, cv::Ptr ptr) { - ptr_guard_map[(long)data_ptr] = ptr; + ptr_guard_map[data_ptr] = ptr; } void -release_facerecognizer(void *ptr) +release_facerecognizer(void *data_ptr) { - long key = (long)ptr; - ptr_guard_map[key].release(); - ptr_guard_map.erase(key); + ptr_guard_map[data_ptr].release(); + ptr_guard_map.erase(data_ptr); } VALUE @@ -153,8 +152,14 @@ rb_load(VALUE self, VALUE filename) } void -define_ruby_class() +init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE alghorithm = rb_define_class_under(opencv, "Algorithm", rb_cObject); +#endif + if (rb_klass) return; /* @@ -163,7 +168,8 @@ define_ruby_class() * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "FaceRecognizer", cAlgorithm::rb_class()); + VALUE alghorithm = cAlgorithm::rb_class(); + rb_klass = rb_define_class_under(opencv, "FaceRecognizer", alghorithm); rb_define_method(rb_klass, "train", RUBY_METHOD_FUNC(rb_train), 2); rb_define_method(rb_klass, "predict", RUBY_METHOD_FUNC(rb_predict), 1); rb_define_method(rb_klass, "save", RUBY_METHOD_FUNC(rb_save), 1); @@ -172,3 +178,4 @@ define_ruby_class() __NAMESPACE_END_FACERECOGNIZER __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/facerecognizer.h b/ext/opencv/facerecognizer.h index e662b9b..2d17059 100644 --- a/ext/opencv/facerecognizer.h +++ b/ext/opencv/facerecognizer.h @@ -20,14 +20,14 @@ __NAMESPACE_BEGIN_FACERECOGNIZER VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_train(VALUE self, VALUE src, VALUE labels); VALUE rb_predict(VALUE self, VALUE src); VALUE rb_save(VALUE self, VALUE filename); VALUE rb_load(VALUE self, VALUE filename); void guard_facerecognizer(void* data_ptr, cv::Ptr ptr); -void release_facerecognizer(void *ptr); +void release_facerecognizer(void *data_ptr); VALUE allocate_facerecognizer(VALUE klass); __NAMESPACE_END_FACERECOGNIZER diff --git a/ext/opencv/fisherfaces.cpp b/ext/opencv/fisherfaces.cpp index 9b58e7b..503afe4 100644 --- a/ext/opencv/fisherfaces.cpp +++ b/ext/opencv/fisherfaces.cpp @@ -47,8 +47,15 @@ rb_initialize(int argc, VALUE argv[], VALUE self) } void -define_ruby_class() +init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE alghorithm = rb_define_class_under(opencv, "Algorithm", rb_cObject); + VALUE face_recognizer = rb_define_class_under(opencv, "FaceRecognizer", alghorithm); +#endif + if (rb_klass) return; /* @@ -57,7 +64,8 @@ define_ruby_class() * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "FisherFaces", cFaceRecognizer::rb_class()); + VALUE face_recognizer = cFaceRecognizer::rb_class(); + rb_klass = rb_define_class_under(opencv, "FisherFaces", face_recognizer); rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); } diff --git a/ext/opencv/fisherfaces.h b/ext/opencv/fisherfaces.h index 4b29db4..dea9e6f 100644 --- a/ext/opencv/fisherfaces.h +++ b/ext/opencv/fisherfaces.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_FISHERFACES VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE argv[], VALUE self); __NAMESPACE_END_FISHERFACES diff --git a/ext/opencv/gui.cpp b/ext/opencv/gui.cpp index f2240b4..bff86f5 100644 --- a/ext/opencv/gui.cpp +++ b/ext/opencv/gui.cpp @@ -10,9 +10,6 @@ #include "gui.h" /* * Document-module: OpenCV::GUI - * - * OpenCV simple GUI interface. Provides Window, Trackbar. - * This GUI work on GTK or Microsoft Windows native GUI. */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_GUI @@ -25,28 +22,14 @@ rb_module_GUI() return rb_module; } -void -define_ruby_module() -{ - if (rb_module) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_module = rb_define_module_under(opencv, "GUI"); - rb_define_singleton_method(rb_module, "wait_key", RUBY_METHOD_FUNC(rb_wait_key), -1); -} - /* - * call-seq: - * wait_key([delay]) -> int or nil + * Waits for a pressed key. * - * Waits for a pressed key each GUI wedget. - * Return the code of the pressed key or nil if no key were pressed until the specified timeout has elapsed. - * delay should be Fixnum. Wait delay millisecond. + * @overload wait_key(delay = 0) + * @param delay [Integer] Delay in milliseconds. 0 is the special value that means "forever". + * @return [Number] The code of the pressed key or nil if no key was pressed + * before the specified time had elapsed. + * @opencv_func cvWaitKey */ VALUE rb_wait_key(int argc, VALUE *argv, VALUE self) @@ -63,6 +46,26 @@ rb_wait_key(int argc, VALUE *argv, VALUE self) return (keycode < 0) ? Qnil : INT2NUM(keycode); } +void +init_ruby_module() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_module) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_module = rb_define_module_under(opencv, "GUI"); + rb_define_singleton_method(rb_module, "wait_key", RUBY_METHOD_FUNC(rb_wait_key), -1); +} + __NAMESPACE_END_GUI __NAMESPACE_END_OPENCV diff --git a/ext/opencv/gui.h b/ext/opencv/gui.h index 882a515..486c076 100644 --- a/ext/opencv/gui.h +++ b/ext/opencv/gui.h @@ -19,7 +19,7 @@ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_GUI VALUE rb_module_GUI(); -void define_ruby_module(); +void init_ruby_module(); VALUE rb_wait_key(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/iplconvkernel.cpp b/ext/opencv/iplconvkernel.cpp index bcedb96..8438728 100644 --- a/ext/opencv/iplconvkernel.cpp +++ b/ext/opencv/iplconvkernel.cpp @@ -29,30 +29,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "IplConvKernel", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_size), 0); - rb_define_method(rb_klass, "cols", RUBY_METHOD_FUNC(rb_cols), 0); - rb_define_alias(rb_klass, "columns", "cols"); - rb_define_method(rb_klass, "rows", RUBY_METHOD_FUNC(rb_rows), 0); - rb_define_method(rb_klass, "anchor", RUBY_METHOD_FUNC(rb_anchor), 0); - rb_define_method(rb_klass, "anchor_x", RUBY_METHOD_FUNC(rb_anchor_x), 0); - rb_define_method(rb_klass, "anchor_y", RUBY_METHOD_FUNC(rb_anchor_y), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -188,5 +164,35 @@ rb_anchor_y(VALUE self) return INT2NUM(IPLCONVKERNEL(self)->anchorY); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + rb_klass = rb_define_class_under(opencv, "IplConvKernel", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_size), 0); + rb_define_method(rb_klass, "cols", RUBY_METHOD_FUNC(rb_cols), 0); + rb_define_alias(rb_klass, "columns", "cols"); + rb_define_method(rb_klass, "rows", RUBY_METHOD_FUNC(rb_rows), 0); + rb_define_method(rb_klass, "anchor", RUBY_METHOD_FUNC(rb_anchor), 0); + rb_define_method(rb_klass, "anchor_x", RUBY_METHOD_FUNC(rb_anchor_x), 0); + rb_define_method(rb_klass, "anchor_y", RUBY_METHOD_FUNC(rb_anchor_y), 0); +} + __NAMESPACE_END_IPLCONVKERNEL __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/iplconvkernel.h b/ext/opencv/iplconvkernel.h index 16efd47..5953196 100644 --- a/ext/opencv/iplconvkernel.h +++ b/ext/opencv/iplconvkernel.h @@ -21,7 +21,7 @@ __NAMESPACE_BEGIN_IPLCONVKERNEL VALUE rb_class(); VALUE rb_allocate(VALUE klass); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); VALUE rb_size(VALUE self); VALUE rb_cols(VALUE self); diff --git a/ext/opencv/iplimage.cpp b/ext/opencv/iplimage.cpp index baccc66..e5998a3 100644 --- a/ext/opencv/iplimage.cpp +++ b/ext/opencv/iplimage.cpp @@ -33,40 +33,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * cvmat = rb_define_class_under(opencv, "CvMat", rb_cObject); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - VALUE cvmat = cCvMat::rb_class(); - rb_klass = rb_define_class_under(opencv, "IplImage", cvmat); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_singleton_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load_image), -1); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "get_roi", RUBY_METHOD_FUNC(rb_get_roi), 0); - rb_define_alias(rb_klass, "roi", "get_roi"); - rb_define_method(rb_klass, "set_roi", RUBY_METHOD_FUNC(rb_set_roi), 1); - rb_define_alias(rb_klass, "roi=", "set_roi"); - rb_define_method(rb_klass, "reset_roi", RUBY_METHOD_FUNC(rb_reset_roi), 0); - rb_define_method(rb_klass, "get_coi", RUBY_METHOD_FUNC(rb_get_coi), 0); - rb_define_alias(rb_klass, "coi", "get_coi"); - rb_define_method(rb_klass, "set_coi", RUBY_METHOD_FUNC(rb_set_coi), 1); - rb_define_alias(rb_klass, "coi=", "set_coi"); - rb_define_method(rb_klass, "reset_coi", RUBY_METHOD_FUNC(rb_reset_coi), 0); - rb_define_method(rb_klass, "pyr_segmentation", RUBY_METHOD_FUNC(rb_pyr_segmentation), 3); - rb_define_method(rb_klass, "smoothness", RUBY_METHOD_FUNC(rb_smoothness), -1); - - rb_define_singleton_method(rb_klass, "decode_image", RUBY_METHOD_FUNC(rb_decode_image), -1); - rb_define_alias(rb_singleton_class(rb_klass), "decode", "decode_image"); -} - VALUE rb_allocate(VALUE klass) { @@ -75,7 +41,7 @@ rb_allocate(VALUE klass) /* * call-seq: - * new(width, height[, depth = CV_8U][, channel = 3]) + * new(width, height[, depth = CV_8U][, channel = 3]) * * Create width * height image. Each element-value set 0. * @@ -99,7 +65,7 @@ rb_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * IplImage::load(filename[,iscolor = CV_LOAD_IMAGE_COLOR]) + * IplImage::load(filename[,iscolor = CV_LOAD_IMAGE_COLOR]) * * Load an image from file. * iscolor = CV_LOAD_IMAGE_COLOR, the loaded image is forced to be a 3-channel color image @@ -183,8 +149,8 @@ rb_get_roi(VALUE self) /* * call-seq: - * set_roi(rect) - * set_roi(rect){|image| ...} + * set_roi(rect) + * set_roi(rect){|image| ...} * * Set ROI. rect should be CvRect or compatible object. * Return self. @@ -244,8 +210,8 @@ rb_get_coi(VALUE self) /* * call-seq: - * set_coi(coi) - * set_coi(coi){|image| ...} + * set_coi(coi) + * set_coi(coi){|image| ...} * * Set COI. coi should be Fixnum. * Return self. @@ -288,7 +254,7 @@ rb_reset_coi(VALUE self) /* * call-seq: - * IplImage.smoothness(lowFreqRatio, blankDensity, messyDensity, highFreqRatio) -> [ symbol, float, float ] + * IplImage.smoothness(lowFreqRatio, blankDensity, messyDensity, highFreqRatio) -> [ symbol, float, float ] * * Determines if the image's smoothness is either, :smooth, :messy, or :blank. * @@ -593,7 +559,7 @@ high_pass_range(const IplImage *pImage, float lostPercentage, int &outLow, int & /* * call-seq: - * pyr_segmentation(level, threshold1, threshold2) -> [iplimage, cvseq(include cvconnectedcomp)] + * pyr_segmentation(level, threshold1, threshold2) -> [iplimage, cvseq(include cvconnectedcomp)] * * Does image segmentation by pyramids. * The pyramid builds up to the level level. @@ -640,5 +606,46 @@ new_object(CvSize size, int type) return OPENCV_OBJECT(rb_klass, rb_cvCreateImage(size, cvIplDepth(type), CV_MAT_CN(type))); } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE cvmat = rb_define_class_under(opencv, "CvMat", rb_cObject); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * cvmat = rb_define_class_under(opencv, "CvMat", rb_cObject); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + VALUE cvmat = cCvMat::rb_class(); + rb_klass = rb_define_class_under(opencv, "IplImage", cvmat); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_singleton_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load_image), -1); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "get_roi", RUBY_METHOD_FUNC(rb_get_roi), 0); + rb_define_alias(rb_klass, "roi", "get_roi"); + rb_define_method(rb_klass, "set_roi", RUBY_METHOD_FUNC(rb_set_roi), 1); + rb_define_alias(rb_klass, "roi=", "set_roi"); + rb_define_method(rb_klass, "reset_roi", RUBY_METHOD_FUNC(rb_reset_roi), 0); + rb_define_method(rb_klass, "get_coi", RUBY_METHOD_FUNC(rb_get_coi), 0); + rb_define_alias(rb_klass, "coi", "get_coi"); + rb_define_method(rb_klass, "set_coi", RUBY_METHOD_FUNC(rb_set_coi), 1); + rb_define_alias(rb_klass, "coi=", "set_coi"); + rb_define_method(rb_klass, "reset_coi", RUBY_METHOD_FUNC(rb_reset_coi), 0); + rb_define_method(rb_klass, "pyr_segmentation", RUBY_METHOD_FUNC(rb_pyr_segmentation), 3); + rb_define_method(rb_klass, "smoothness", RUBY_METHOD_FUNC(rb_smoothness), -1); + + rb_define_singleton_method(rb_klass, "decode_image", RUBY_METHOD_FUNC(rb_decode_image), -1); + rb_define_alias(rb_singleton_class(rb_klass), "decode", "decode_image"); +} + __NAMESPACE_END_IPLIMAGE __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/iplimage.h b/ext/opencv/iplimage.h index d1c53fd..e7a77f4 100644 --- a/ext/opencv/iplimage.h +++ b/ext/opencv/iplimage.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_IPLIMAGE VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); VALUE rb_initialize(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/lbph.cpp b/ext/opencv/lbph.cpp index 35577f6..895fe32 100644 --- a/ext/opencv/lbph.cpp +++ b/ext/opencv/lbph.cpp @@ -50,8 +50,15 @@ rb_initialize(int argc, VALUE argv[], VALUE self) } void -define_ruby_class() +init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE alghorithm = rb_define_class_under(opencv, "Algorithm", rb_cObject); + VALUE face_recognizer = rb_define_class_under(opencv, "FaceRecognizer", alghorithm); +#endif + if (rb_klass) return; /* @@ -60,7 +67,8 @@ define_ruby_class() * note: this comment is used by rdoc. */ VALUE opencv = rb_module_opencv(); - rb_klass = rb_define_class_under(opencv, "LBPH", cFaceRecognizer::rb_class()); + VALUE face_recognizer = cFaceRecognizer::rb_class(); + rb_klass = rb_define_class_under(opencv, "LBPH", face_recognizer); rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer); rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); } diff --git a/ext/opencv/lbph.h b/ext/opencv/lbph.h index accc7c6..2903af5 100644 --- a/ext/opencv/lbph.h +++ b/ext/opencv/lbph.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_LBPH VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_initialize(int argc, VALUE argv[], VALUE self); __NAMESPACE_END_LBPH diff --git a/ext/opencv/mouseevent.cpp b/ext/opencv/mouseevent.cpp index 1b9e442..4b40936 100644 --- a/ext/opencv/mouseevent.cpp +++ b/ext/opencv/mouseevent.cpp @@ -12,8 +12,6 @@ * Document-module: OpenCV::GUI::MouseEvent * * MouseEvent object. - * have - * see OpenCV::GUI::Window#set_mouse_callback. */ __NAMESPACE_BEGIN_OPENCV __NAMESPACE_BEGIN_GUI @@ -27,29 +25,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * GUI = rb_define_module_under(opencv, "GUI"); - * cvpoint = rb_define_class_under(opencv, "CvPoint", rb_cObject); - */ - VALUE GUI = rb_module_GUI(); - VALUE cvpoint = cCvPoint::rb_class(); - rb_klass = rb_define_class_under(GUI, "MouseEvent", cvpoint); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_method(rb_klass, "event", RUBY_METHOD_FUNC(rb_event), 0); - rb_define_method(rb_klass, "left_button?", RUBY_METHOD_FUNC(rb_left_button_q), 0); - rb_define_method(rb_klass, "right_button?", RUBY_METHOD_FUNC(rb_right_button_q), 0); - rb_define_method(rb_klass, "middle_button?", RUBY_METHOD_FUNC(rb_middle_button_q), 0); - rb_define_method(rb_klass, "ctrl_key?", RUBY_METHOD_FUNC(rb_ctrl_key_q), 0); - rb_define_method(rb_klass, "shift_key?", RUBY_METHOD_FUNC(rb_shift_key_q), 0); - rb_define_method(rb_klass, "alt_key?", RUBY_METHOD_FUNC(rb_alt_key_q), 0); -} - VALUE rb_allocate(VALUE klass) { @@ -175,6 +150,36 @@ new_object(int event, int x, int y, int flags) return object; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE GUI = rb_define_module_under(opencv, "GUI"); + VALUE cvpoint = rb_define_class_under(opencv, "CvPoint", rb_cObject); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * GUI = rb_define_module_under(opencv, "GUI"); + * cvpoint = rb_define_class_under(opencv, "CvPoint", rb_cObject); + */ + VALUE GUI = rb_module_GUI(); + VALUE cvpoint = cCvPoint::rb_class(); + rb_klass = rb_define_class_under(GUI, "MouseEvent", cvpoint); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "event", RUBY_METHOD_FUNC(rb_event), 0); + rb_define_method(rb_klass, "left_button?", RUBY_METHOD_FUNC(rb_left_button_q), 0); + rb_define_method(rb_klass, "right_button?", RUBY_METHOD_FUNC(rb_right_button_q), 0); + rb_define_method(rb_klass, "middle_button?", RUBY_METHOD_FUNC(rb_middle_button_q), 0); + rb_define_method(rb_klass, "ctrl_key?", RUBY_METHOD_FUNC(rb_ctrl_key_q), 0); + rb_define_method(rb_klass, "shift_key?", RUBY_METHOD_FUNC(rb_shift_key_q), 0); + rb_define_method(rb_klass, "alt_key?", RUBY_METHOD_FUNC(rb_alt_key_q), 0); +} + __NAMESPACE_END_MOUSEEVENT __NAMESPACE_END_GUI __NAMESPACE_END_OPENCV diff --git a/ext/opencv/mouseevent.h b/ext/opencv/mouseevent.h index 55b29a5..8ad4948 100644 --- a/ext/opencv/mouseevent.h +++ b/ext/opencv/mouseevent.h @@ -27,7 +27,7 @@ typedef struct MouseEvent { VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index 8577417..7f6f7a2 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -154,7 +154,7 @@ rb_module_opencv() } void -define_ruby_module() +init_ruby_module() { if (rb_module) return; @@ -320,6 +320,8 @@ define_ruby_module() /* Flags of window */ rb_define_const(rb_module, "CV_WINDOW_AUTOSIZE", INT2FIX(CV_WINDOW_AUTOSIZE)); + rb_define_const(rb_module, "CV_WINDOW_NORMAL", INT2FIX(CV_WINDOW_NORMAL)); + rb_define_const(rb_module, "CV_WINDOW_OPENGL", INT2FIX(CV_WINDOW_OPENGL)); /* Object detection mode */ rb_define_const(rb_module, "CV_HAAR_DO_CANNY_PRUNING", INT2FIX(CV_HAAR_DO_CANNY_PRUNING)); @@ -705,70 +707,67 @@ extern "C" { { cvRedirectError((CvErrorCallback)mOpenCV::error_callback); - mOpenCV::define_ruby_module(); + mOpenCV::init_ruby_module(); - mOpenCV::cCvError::define_ruby_class(); - mOpenCV::cCvPoint::define_ruby_class(); - mOpenCV::cCvPoint2D32f::define_ruby_class(); - mOpenCV::cCvPoint3D32f::define_ruby_class(); - mOpenCV::cCvSize::define_ruby_class(); - mOpenCV::cCvSize2D32f::define_ruby_class(); - mOpenCV::cCvRect::define_ruby_class(); - mOpenCV::cCvScalar::define_ruby_class(); - mOpenCV::cCvSlice::define_ruby_class(); - mOpenCV::cCvTermCriteria::define_ruby_class(); - mOpenCV::cCvBox2D::define_ruby_class(); - mOpenCV::cCvFont::define_ruby_class(); - mOpenCV::cIplConvKernel::define_ruby_class(); - mOpenCV::cCvMoments::define_ruby_class(); - mOpenCV::cCvHuMoments::define_ruby_class(); - mOpenCV::cCvConvexityDefect::define_ruby_class(); + mOpenCV::cCvError::init_ruby_class(); + mOpenCV::cCvPoint::init_ruby_class(); + mOpenCV::cCvPoint2D32f::init_ruby_class(); + mOpenCV::cCvPoint3D32f::init_ruby_class(); + mOpenCV::cCvSize::init_ruby_class(); + mOpenCV::cCvSize2D32f::init_ruby_class(); + mOpenCV::cCvRect::init_ruby_class(); + mOpenCV::cCvScalar::init_ruby_class(); + mOpenCV::cCvSlice::init_ruby_class(); + mOpenCV::cCvTermCriteria::init_ruby_class(); + mOpenCV::cCvBox2D::init_ruby_class(); + mOpenCV::cCvFont::init_ruby_class(); + mOpenCV::cIplConvKernel::init_ruby_class(); + mOpenCV::cCvMoments::init_ruby_class(); + mOpenCV::cCvHuMoments::init_ruby_class(); + mOpenCV::cCvConvexityDefect::init_ruby_class(); - mOpenCV::cCvSURFPoint::define_ruby_class(); - mOpenCV::cCvSURFParams::define_ruby_class(); + mOpenCV::cCvSURFPoint::init_ruby_class(); + mOpenCV::cCvSURFParams::init_ruby_class(); - mOpenCV::cCvMemStorage::define_ruby_class(); + mOpenCV::cCvMemStorage::init_ruby_class(); - mOpenCV::cCvSeq::define_ruby_class(); - mOpenCV::mCurve::define_ruby_module(); - mOpenCV::mPointSet::define_ruby_module(); - mOpenCV::cCvChain::define_ruby_class(); - mOpenCV::cCvContour::define_ruby_class(); - mOpenCV::cCvContourTree::define_ruby_class(); + mOpenCV::cCvSeq::init_ruby_class(); + mOpenCV::mCurve::init_ruby_module(); + mOpenCV::mPointSet::init_ruby_module(); + mOpenCV::cCvChain::init_ruby_class(); + mOpenCV::cCvContour::init_ruby_class(); + mOpenCV::cCvContourTree::init_ruby_class(); - mOpenCV::cCvMat::define_ruby_class(); - mOpenCV::cIplImage::define_ruby_class(); - mOpenCV::cCvMatND::define_ruby_class(); - mOpenCV::cCvSparseMat::define_ruby_class(); - mOpenCV::cCvHistogram::define_ruby_class(); - mOpenCV::cCvCapture::define_ruby_class(); - mOpenCV::cCvVideoWriter::define_ruby_class(); + mOpenCV::cCvMat::init_ruby_class(); + mOpenCV::cIplImage::init_ruby_class(); + mOpenCV::cCvHistogram::init_ruby_class(); + mOpenCV::cCvCapture::init_ruby_class(); + mOpenCV::cCvVideoWriter::init_ruby_class(); - mOpenCV::cCvLine::define_ruby_class(); - mOpenCV::cCvTwoPoints::define_ruby_class(); - mOpenCV::cCvCircle32f::define_ruby_class(); + mOpenCV::cCvLine::init_ruby_class(); + mOpenCV::cCvTwoPoints::init_ruby_class(); + mOpenCV::cCvCircle32f::init_ruby_class(); - mOpenCV::cCvConDensation::define_ruby_class(); - mOpenCV::cCvFeatureTree::define_ruby_class(); + mOpenCV::cCvFeatureTree::init_ruby_class(); - mOpenCV::cCvConnectedComp::define_ruby_class(); - mOpenCV::cCvAvgComp::define_ruby_class(); - mOpenCV::cCvHaarClassifierCascade::define_ruby_class(); + mOpenCV::cCvConnectedComp::init_ruby_class(); + mOpenCV::cCvAvgComp::init_ruby_class(); + mOpenCV::cCvHaarClassifierCascade::init_ruby_class(); - mOpenCV::cAlgorithm::define_ruby_class(); - mOpenCV::cFaceRecognizer::define_ruby_class(); - mOpenCV::cEigenFaces::define_ruby_class(); - mOpenCV::cFisherFaces::define_ruby_class(); - mOpenCV::cLBPH::define_ruby_class(); + mOpenCV::cAlgorithm::init_ruby_class(); + mOpenCV::cFaceRecognizer::init_ruby_class(); + mOpenCV::cEigenFaces::init_ruby_class(); + mOpenCV::cFisherFaces::init_ruby_class(); + mOpenCV::cLBPH::init_ruby_class(); - mOpenCV::mGUI::define_ruby_module(); - mOpenCV::mGUI::cWindow::define_ruby_class(); - mOpenCV::mGUI::cTrackbar::define_ruby_class(); - mOpenCV::mGUI::cMouseEvent::define_ruby_class(); + mOpenCV::mGUI::init_ruby_module(); + mOpenCV::mGUI::cWindow::init_ruby_class(); + mOpenCV::mGUI::cTrackbar::init_ruby_class(); + mOpenCV::mGUI::cMouseEvent::init_ruby_class(); #ifdef HAVE_ML_H /* feature support. - mOpenCV::mMachineLearning::define_ruby_module(); + mOpenCV::mMachineLearning::init_ruby_module(); */ #endif diff --git a/ext/opencv/opencv.h b/ext/opencv/opencv.h index 78c3d8b..2f20551 100644 --- a/ext/opencv/opencv.h +++ b/ext/opencv/opencv.h @@ -112,8 +112,6 @@ extern "C" { #include "cvmat.h" #include "iplimage.h" -#include "cvmatnd.h" -#include "cvsparsemat.h" #include "cvhistogram.h" #include "cvcapture.h" #include "cvvideowriter.h" @@ -122,8 +120,6 @@ extern "C" { #include "cvtwopoints.h" #include "cvcircle32f.h" -#include "cvcondensation.h" - #include "cvconnectedcomp.h" #include "cvavgcomp.h" #include "cvhaarclassifiercascade.h" @@ -203,7 +199,7 @@ void release_object(void *ptr); void release_iplconvkernel_object(void *ptr); VALUE rb_module_opencv(); -void define_ruby_module(); +void init_ruby_module(); // Ruby/OpenCV inline functions inline CvArr* diff --git a/ext/opencv/pointset.cpp b/ext/opencv/pointset.cpp index a5886e3..3afbcdd 100644 --- a/ext/opencv/pointset.cpp +++ b/ext/opencv/pointset.cpp @@ -23,29 +23,6 @@ rb_module() return module; } -void -define_ruby_module() -{ - if (module) - return; - /* - * opencv = rb_define_module("OpenCV"); - * - * note: this comment is used by rdoc. - */ - VALUE opencv = rb_module_opencv(); - module = rb_define_module_under(opencv, "PointSet"); - rb_define_method(module, "contour_area", RUBY_METHOD_FUNC(rb_contour_area), -1); - rb_define_method(module, "fit_ellipse2", RUBY_METHOD_FUNC(rb_fit_ellipse2), 0); - - rb_define_method(module, "convex_hull2", RUBY_METHOD_FUNC(rb_convex_hull2), -1); - rb_define_method(module, "check_contour_convexity", RUBY_METHOD_FUNC(rb_check_contour_convexity), 0); - rb_define_alias(module, "convexity?", "check_contour_convexity"); - rb_define_method(module, "convexity_defects", RUBY_METHOD_FUNC(rb_convexity_defects), 1); - rb_define_method(module, "min_area_rect2", RUBY_METHOD_FUNC(rb_min_area_rect2), 0); - rb_define_method(module, "min_enclosing_circle", RUBY_METHOD_FUNC(rb_min_enclosing_circle), 0); -} - /* * call-seq: * contour_area -> float @@ -90,7 +67,7 @@ rb_fit_ellipse2(VALUE self) /* * call-seq: - * convex_hull2([orientation_clockwise = true]) -> cvcontour + * convex_hull2([orientation_clockwise = true]) -> cvcontour * * Finds convex hull of 2D point set using Sklansky's algorithm. * @@ -136,7 +113,7 @@ rb_check_contour_convexity(VALUE self) /* * call-seq: - * convexity_defects(hull) -> cvseq(include CvConvexityDefect) + * convexity_defects(hull) -> cvseq(include CvConvexityDefect) * * Finds convexity defects of contour. */ @@ -197,6 +174,34 @@ rb_min_enclosing_circle(VALUE self) return success ? circle : Qnil; } +void +init_ruby_module() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); +#endif + + if (module) + return; + /* + * opencv = rb_define_module("OpenCV"); + * + * note: this comment is used by rdoc. + */ + VALUE opencv = rb_module_opencv(); + module = rb_define_module_under(opencv, "PointSet"); + rb_define_method(module, "contour_area", RUBY_METHOD_FUNC(rb_contour_area), -1); + rb_define_method(module, "fit_ellipse2", RUBY_METHOD_FUNC(rb_fit_ellipse2), 0); + + rb_define_method(module, "convex_hull2", RUBY_METHOD_FUNC(rb_convex_hull2), -1); + rb_define_method(module, "check_contour_convexity", RUBY_METHOD_FUNC(rb_check_contour_convexity), 0); + rb_define_alias(module, "convexity?", "check_contour_convexity"); + rb_define_method(module, "convexity_defects", RUBY_METHOD_FUNC(rb_convexity_defects), 1); + rb_define_method(module, "min_area_rect2", RUBY_METHOD_FUNC(rb_min_area_rect2), 0); + rb_define_method(module, "min_enclosing_circle", RUBY_METHOD_FUNC(rb_min_enclosing_circle), 0); +} + __NAMESPACE_END_POINT_SET int @@ -272,3 +277,4 @@ VALUE_TO_POINT_SET(VALUE object) } __NAMESPACE_END_OPENCV + diff --git a/ext/opencv/pointset.h b/ext/opencv/pointset.h index 4b8c8b3..99c38f7 100644 --- a/ext/opencv/pointset.h +++ b/ext/opencv/pointset.h @@ -20,7 +20,7 @@ __NAMESPACE_BEGIN_POINT_SET VALUE rb_module(); -void define_ruby_module(); +void init_ruby_module(); VALUE rb_contour_area(int argc, VALUE *argv, VALUE self); VALUE rb_fit_ellipse2(VALUE self); VALUE rb_convex_hull2(int argc, VALUE *argv, VALUE self); diff --git a/ext/opencv/trackbar.cpp b/ext/opencv/trackbar.cpp index 183cd3c..360091f 100644 --- a/ext/opencv/trackbar.cpp +++ b/ext/opencv/trackbar.cpp @@ -25,25 +25,6 @@ VALUE rb_class() { return rb_klass; } -void define_ruby_class() { - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * GUI = rb_define_module_under(opencv, "GUI"); - * - * note: this comment is used by rdoc. - */ - VALUE GUI = rb_module_GUI(); - rb_klass = rb_define_class_under(GUI, "Trackbar", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "name", RUBY_METHOD_FUNC(rb_name), 0); - rb_define_method(rb_klass, "max", RUBY_METHOD_FUNC(rb_max), 0); - rb_define_method(rb_klass, "value", RUBY_METHOD_FUNC(rb_value), 0); - rb_define_method(rb_klass, "value=", RUBY_METHOD_FUNC(rb_set_value), 1); -} - VALUE rb_allocate(VALUE klass) { Trackbar *ptr; return Data_Make_Struct(klass, Trackbar, trackbar_mark, trackbar_free, ptr); @@ -61,8 +42,8 @@ void trackbar_free(void *ptr) { /* * call-seq: - * new(name,maxval[,val],&block) - * new(name,maxval[,val]){|value| ... } + * new(name,maxval[,val],&block) + * new(name,maxval[,val]){|value| ... } * * Create new Trackbar. * name should be String. @@ -114,6 +95,31 @@ VALUE rb_set_value(VALUE self, VALUE val) { TRACKBAR(self)->val = NUM2INT(val); return self; } + +void init_ruby_class() { +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE GUI = rb_define_module_under(opencv, "GUI"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * GUI = rb_define_module_under(opencv, "GUI"); + * + * note: this comment is used by rdoc. + */ + VALUE GUI = rb_module_GUI(); + rb_klass = rb_define_class_under(GUI, "Trackbar", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "name", RUBY_METHOD_FUNC(rb_name), 0); + rb_define_method(rb_klass, "max", RUBY_METHOD_FUNC(rb_max), 0); + rb_define_method(rb_klass, "value", RUBY_METHOD_FUNC(rb_value), 0); + rb_define_method(rb_klass, "value=", RUBY_METHOD_FUNC(rb_set_value), 1); +} __NAMESPACE_END_TRACKBAR __NAMESPACE_END_GUI diff --git a/ext/opencv/trackbar.h b/ext/opencv/trackbar.h index ca08176..1ed87bf 100644 --- a/ext/opencv/trackbar.h +++ b/ext/opencv/trackbar.h @@ -33,7 +33,7 @@ __NAMESPACE_BEGIN_TRACKBAR VALUE rb_class(); -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); void trackbar_mark(void *ptr); diff --git a/ext/opencv/window.cpp b/ext/opencv/window.cpp index 8c01626..8dd64bf 100644 --- a/ext/opencv/window.cpp +++ b/ext/opencv/window.cpp @@ -32,33 +32,6 @@ rb_class() return rb_klass; } -void -define_ruby_class() -{ - if (rb_klass) - return; - /* - * opencv = rb_define_module("OpenCV"); - * GUI = rb_define_module_under(opencv, "GUI"); - * - * note: this comment is used by rdoc. - */ - VALUE GUI = rb_module_GUI(); - rb_klass = rb_define_class_under(GUI, "Window", rb_cObject); - rb_define_alloc_func(rb_klass, rb_allocate); - rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); - rb_define_method(rb_klass, "alive?", RUBY_METHOD_FUNC(rb_alive_q), 0); - rb_define_method(rb_klass, "destroy", RUBY_METHOD_FUNC(rb_destroy), 0); - rb_define_singleton_method(rb_klass, "destroy_all", RUBY_METHOD_FUNC(rb_destroy_all), 0); - rb_define_method(rb_klass, "resize", RUBY_METHOD_FUNC(rb_resize), -1); - rb_define_method(rb_klass, "move", RUBY_METHOD_FUNC(rb_move), -1); - rb_define_method(rb_klass, "show_image", RUBY_METHOD_FUNC(rb_show_image), 1); - rb_define_alias(rb_klass, "show", "show_image"); - rb_define_method(rb_klass, "set_trackbar", RUBY_METHOD_FUNC(rb_set_trackbar), -1); - rb_define_method(rb_klass, "set_mouse_callback", RUBY_METHOD_FUNC(rb_set_mouse_callback), -1); - rb_define_alias(rb_klass, "on_mouse", "set_mouse_callback"); -} - VALUE rb_allocate(VALUE klass) { @@ -83,11 +56,16 @@ window_free(void *ptr) } /* - * call-seq: - * new(name[, flags]) + * Creates a window. * - * Create new window named name. - * If flags is CV_WINDOW_AUTOSIZE (default), window size automatically resize when image given. + * @overload new(name, flags = CV_WINDOW_AUTOSIZE) + * @param name [String] Name of the window in the window caption that may be used as a window identifier. + * @param flags [Integer] Flags of the window. The supported flags are: + * * CV_WINDOW_AUTOSIZE - If this is set, the window size is automatically adjusted + * to fit the displayed image, and you cannot change the window size manually. + * * CV_WINDOW_NORMAL - If this is set, the user can resize the window (no constraint). + * * CV_WINDOW_OPENGL - If this is set, the window will be created with OpenGL support. + * @opencv_func cvNamedWindow */ VALUE rb_initialize(int argc, VALUE *argv, VALUE self) @@ -166,11 +144,14 @@ rb_destroy_all(VALUE klass) } /* - * call-seq: - * resize(size) - * resize(width, height) + * Resizes window to the specified size. * - * Set window size. + * @overload resize(size) + * @param size [CvSize] The new window size. + * @overload resize(width, height) + * @param width [Integer] The new window width. + * @param height [Integer] The new window height. + * @opencv_func cvResizeWindow */ VALUE rb_resize(int argc, VALUE *argv, VALUE self) @@ -202,11 +183,14 @@ rb_resize(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * move(point) - * move(x, y) + * Moves window to the specified position. * - * Set window position. + * @overload move(point) + * @param point [CvPoint] The new coordinate of the window. + * @overload move(x, y) + * @param x [Integer] The new x-coordinate of the window. + * @param y [Integer] The new y-coordinate of the window. + * @opencv_func cvMoveWindow */ VALUE rb_move(int argc, VALUE *argv, VALUE self) @@ -238,11 +222,11 @@ rb_move(int argc, VALUE *argv, VALUE self) } /* - * call-seq: - * show_image(image) + * Displays an image in the specified window. * - * Show the image. If the window was created with flags = CV_WINDOW_AUTOSIZE then the image is shown - * with its original size, otherwize the image is scaled to fit the window. + * @overload show_image(image) + * @param image [CvMat] Image to be shown. + * @opencv_func cvShowImage */ VALUE rb_show_image(VALUE self, VALUE img) @@ -265,13 +249,19 @@ trackbar_callback(int value, void* block) } /* - * call-seq: - * set_trackbar(trackbar) - * set_trackbar(name,maxval[,val],&block) - * set_trackbar(name,maxval[,val]){|value| ... } + * Creates or sets a trackbar and attaches it to the specified window. * - * Create Trackbar on this window. Return new Trackbar. - * see Trackbar.new + * @overload set_trackbar(trackbar) + * @param trackbar [TrackBar] The trackbar to set. + * + * @overload set_trackbar(name, count, value = nil) { |value| ... } + * @param name [String] Name of the created trackbar. + * @param count [Integer] Maximal position of the slider. The minimal position is always 0. + * @param value [Integer] Optional value to an integer variable whose value reflects the position of the slider. + * Upon creation, the slider position is defined by this variable. + * @yield [value] Function to be called every time the slider changes position. + * @yieldparam value [Integer] The trackbar position. + * @opencv_func cv::createTrackbar */ VALUE rb_set_trackbar(int argc, VALUE *argv, VALUE self) @@ -306,16 +296,13 @@ on_mouse(int event, int x, int y, int flags, void* param) } /* - * call-seq: - * set_mouse_callback(&block) - * set_mouse_callback {|mouse_event| ... } + * Sets mouse handler for the specified window. * - * Set mouse callback. - * When the mouse is operated on the window, block will be called. - * Return Proc object. - * block given mouse event object, see GUI::Window::MouseEvent + * @overload set_mouse_callback { |mouse_event| ... } + * @yield [mouse_event] Mouse callback. + * @yieldparam mouse_event [MouseEvent] Mouse event * - * e.g. display mouse event on console. + * @example display mouse event on console * window = OpenCV::GUI::Window.new "sample window" * image = OpenCV::IplImage::load "sample.png" * window.show(image) @@ -351,6 +338,39 @@ rb_set_mouse_callback(int argc, VALUE* argv, VALUE self) return block; } +void +init_ruby_class() +{ +#if 0 + // For documentation using YARD + VALUE opencv = rb_define_module("OpenCV"); + VALUE GUI = rb_define_module_under(opencv, "GUI"); +#endif + + if (rb_klass) + return; + /* + * opencv = rb_define_module("OpenCV"); + * GUI = rb_define_module_under(opencv, "GUI"); + * + * note: this comment is used by rdoc. + */ + VALUE GUI = rb_module_GUI(); + rb_klass = rb_define_class_under(GUI, "Window", rb_cObject); + rb_define_alloc_func(rb_klass, rb_allocate); + rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_method(rb_klass, "alive?", RUBY_METHOD_FUNC(rb_alive_q), 0); + rb_define_method(rb_klass, "destroy", RUBY_METHOD_FUNC(rb_destroy), 0); + rb_define_singleton_method(rb_klass, "destroy_all", RUBY_METHOD_FUNC(rb_destroy_all), 0); + rb_define_method(rb_klass, "resize", RUBY_METHOD_FUNC(rb_resize), -1); + rb_define_method(rb_klass, "move", RUBY_METHOD_FUNC(rb_move), -1); + rb_define_method(rb_klass, "show_image", RUBY_METHOD_FUNC(rb_show_image), 1); + rb_define_alias(rb_klass, "show", "show_image"); + rb_define_method(rb_klass, "set_trackbar", RUBY_METHOD_FUNC(rb_set_trackbar), -1); + rb_define_method(rb_klass, "set_mouse_callback", RUBY_METHOD_FUNC(rb_set_mouse_callback), -1); + rb_define_alias(rb_klass, "on_mouse", "set_mouse_callback"); +} + __NAMESPACE_END_WINDOW __NAMESPACE_END_GUI __NAMESPACE_END_OPENCV diff --git a/ext/opencv/window.h b/ext/opencv/window.h index b61b7f4..93cf20c 100644 --- a/ext/opencv/window.h +++ b/ext/opencv/window.h @@ -30,7 +30,7 @@ typedef struct Window { __NAMESPACE_BEGIN_WINDOW -void define_ruby_class(); +void init_ruby_class(); VALUE rb_allocate(VALUE klass); diff --git a/images/face_detect_from_lena.jpg b/images/face_detect_from_lena.jpg deleted file mode 100644 index eabd54e..0000000 Binary files a/images/face_detect_from_lena.jpg and /dev/null differ diff --git a/lib/opencv/version.rb b/lib/opencv/version.rb index c1ae18a..0995f45 100755 --- a/lib/opencv/version.rb +++ b/lib/opencv/version.rb @@ -1,3 +1,4 @@ module OpenCV - VERSION = '0.0.10' + VERSION = '0.0.12' end + diff --git a/ruby-opencv.gemspec b/ruby-opencv.gemspec index b92339f..32ec2cb 100644 --- a/ruby-opencv.gemspec +++ b/ruby-opencv.gemspec @@ -1,45 +1,46 @@ # -*- encoding: utf-8 -*- -# stub: ruby-opencv 0.0.10.20131125011902 ruby lib +# stub: ruby-opencv 0.0.12.20140119050230 ruby lib +# stub: ext/opencv/extconf.rb Gem::Specification.new do |s| s.name = "ruby-opencv" - s.version = "0.0.10.20131125011902" + s.version = "0.0.12.20140119050230" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.require_paths = ["lib"] s.authors = ["lsxi", "ser1zw", "pcting"] - s.date = "2013-11-24" + s.date = "2014-01-18" s.description = "ruby-opencv is a wrapper of OpenCV for Ruby. It helps you to write computer vision programs (e.g. detecting faces from pictures) with Ruby." s.email = ["masakazu.yonekura@gmail.com", "azariahsawtikes@gmail.com", "pcting@gmail.com"] s.extensions = ["ext/opencv/extconf.rb"] - s.extra_rdoc_files = ["DEVELOPERS_NOTE.md", "History.txt", "License.txt", "Manifest.txt", "README.md", "examples/facerec/readme.md", "examples/matching_to_many_images/train/trainImages.txt"] - s.files = [".gitignore", "DEVELOPERS_NOTE.md", "Gemfile", "History.txt", "License.txt", "Manifest.txt", "README.md", "Rakefile", "config.yml", "examples/alpha_blend.rb", "examples/contours/bitmap-contours-with-labels.png", "examples/contours/bitmap-contours.png", "examples/contours/bounding-box-detect-canny.rb", "examples/contours/contour_retrieval_modes.rb", "examples/contours/rotated-boxes.jpg", "examples/convexhull.rb", "examples/face_detect.rb", "examples/facerec/create_csv.rb", "examples/facerec/facerec_eigenfaces.rb", "examples/facerec/facerec_fisherfaces.rb", "examples/facerec/facerec_lbph.rb", "examples/facerec/readme.md", "examples/find_obj.rb", "examples/houghcircle.rb", "examples/images/box.png", "examples/images/box_in_scene.png", "examples/images/inpaint.png", "examples/images/lena-256x256.jpg", "examples/images/lena-eyes.jpg", "examples/images/lenna-rotated.jpg", "examples/images/lenna.jpg", "examples/images/stuff.jpg", "examples/images/tiffany.jpg", "examples/inpaint.rb", "examples/match_kdtree.rb", "examples/match_template.rb", "examples/matching_to_many_images/matching_to_many_images.rb", "examples/matching_to_many_images/query.png", "examples/matching_to_many_images/train/1.png", "examples/matching_to_many_images/train/2.png", "examples/matching_to_many_images/train/3.png", "examples/matching_to_many_images/train/trainImages.txt", "examples/paint.rb", "examples/snake.rb", "ext/opencv/algorithm.cpp", "ext/opencv/algorithm.h", "ext/opencv/curve.cpp", "ext/opencv/curve.h", "ext/opencv/cvavgcomp.cpp", "ext/opencv/cvavgcomp.h", "ext/opencv/cvbox2d.cpp", "ext/opencv/cvbox2d.h", "ext/opencv/cvcapture.cpp", "ext/opencv/cvcapture.h", "ext/opencv/cvchain.cpp", "ext/opencv/cvchain.h", "ext/opencv/cvcircle32f.cpp", "ext/opencv/cvcircle32f.h", "ext/opencv/cvcondensation.cpp", "ext/opencv/cvcondensation.h", "ext/opencv/cvconnectedcomp.cpp", "ext/opencv/cvconnectedcomp.h", "ext/opencv/cvcontour.cpp", "ext/opencv/cvcontour.h", "ext/opencv/cvcontourtree.cpp", "ext/opencv/cvcontourtree.h", "ext/opencv/cvconvexitydefect.cpp", "ext/opencv/cvconvexitydefect.h", "ext/opencv/cverror.cpp", "ext/opencv/cverror.h", "ext/opencv/cvfeaturetree.cpp", "ext/opencv/cvfeaturetree.h", "ext/opencv/cvfont.cpp", "ext/opencv/cvfont.h", "ext/opencv/cvhaarclassifiercascade.cpp", "ext/opencv/cvhaarclassifiercascade.h", "ext/opencv/cvhistogram.cpp", "ext/opencv/cvhistogram.h", "ext/opencv/cvhumoments.cpp", "ext/opencv/cvhumoments.h", "ext/opencv/cvline.cpp", "ext/opencv/cvline.h", "ext/opencv/cvmat.cpp", "ext/opencv/cvmat.h", "ext/opencv/cvmatnd.cpp", "ext/opencv/cvmatnd.h", "ext/opencv/cvmemstorage.cpp", "ext/opencv/cvmemstorage.h", "ext/opencv/cvmoments.cpp", "ext/opencv/cvmoments.h", "ext/opencv/cvpoint.cpp", "ext/opencv/cvpoint.h", "ext/opencv/cvpoint2d32f.cpp", "ext/opencv/cvpoint2d32f.h", "ext/opencv/cvpoint3d32f.cpp", "ext/opencv/cvpoint3d32f.h", "ext/opencv/cvrect.cpp", "ext/opencv/cvrect.h", "ext/opencv/cvscalar.cpp", "ext/opencv/cvscalar.h", "ext/opencv/cvseq.cpp", "ext/opencv/cvseq.h", "ext/opencv/cvsize.cpp", "ext/opencv/cvsize.h", "ext/opencv/cvsize2d32f.cpp", "ext/opencv/cvsize2d32f.h", "ext/opencv/cvslice.cpp", "ext/opencv/cvslice.h", "ext/opencv/cvsparsemat.cpp", "ext/opencv/cvsparsemat.h", "ext/opencv/cvsurfparams.cpp", "ext/opencv/cvsurfparams.h", "ext/opencv/cvsurfpoint.cpp", "ext/opencv/cvsurfpoint.h", "ext/opencv/cvtermcriteria.cpp", "ext/opencv/cvtermcriteria.h", "ext/opencv/cvtwopoints.cpp", "ext/opencv/cvtwopoints.h", "ext/opencv/cvutils.cpp", "ext/opencv/cvutils.h", "ext/opencv/cvvideowriter.cpp", "ext/opencv/cvvideowriter.h", "ext/opencv/eigenfaces.cpp", "ext/opencv/eigenfaces.h", "ext/opencv/extconf.rb", "ext/opencv/facerecognizer.cpp", "ext/opencv/facerecognizer.h", "ext/opencv/fisherfaces.cpp", "ext/opencv/fisherfaces.h", "ext/opencv/gui.cpp", "ext/opencv/gui.h", "ext/opencv/iplconvkernel.cpp", "ext/opencv/iplconvkernel.h", "ext/opencv/iplimage.cpp", "ext/opencv/iplimage.h", "ext/opencv/lbph.cpp", "ext/opencv/lbph.h", "ext/opencv/mouseevent.cpp", "ext/opencv/mouseevent.h", "ext/opencv/opencv.cpp", "ext/opencv/opencv.h", "ext/opencv/pointset.cpp", "ext/opencv/pointset.h", "ext/opencv/trackbar.cpp", "ext/opencv/trackbar.h", "ext/opencv/window.cpp", "ext/opencv/window.h", "images/CvMat_sobel.png", "images/CvMat_sub_rect.png", "images/CvSeq_relationmap.png", "images/face_detect_from_lena.jpg", "lib/opencv.rb", "lib/opencv/psyched_yaml.rb", "lib/opencv/version.rb", "ruby-opencv.gemspec", "test/eigenfaces_save.xml", "test/fisherfaces_save.xml", "test/helper.rb", "test/lbph_save.xml", "test/runner.rb", "test/samples/airplane.jpg", "test/samples/baboon.jpg", "test/samples/baboon200.jpg", "test/samples/baboon200_rotated.jpg", "test/samples/blank0.jpg", "test/samples/blank1.jpg", "test/samples/blank2.jpg", "test/samples/blank3.jpg", "test/samples/blank4.jpg", "test/samples/blank5.jpg", "test/samples/blank6.jpg", "test/samples/blank7.jpg", "test/samples/blank8.jpg", "test/samples/blank9.jpg", "test/samples/cat.jpg", "test/samples/chessboard.jpg", "test/samples/contours.jpg", "test/samples/fruits.jpg", "test/samples/haarcascade_frontalface_alt.xml.gz", "test/samples/inpaint-mask.bmp", "test/samples/lena-256x256.jpg", "test/samples/lena-32x32.jpg", "test/samples/lena-eyes.jpg", "test/samples/lena-inpaint.jpg", "test/samples/lena.jpg", "test/samples/lines.jpg", "test/samples/messy0.jpg", "test/samples/messy1.jpg", "test/samples/movie_sample.avi", "test/samples/one_way_train_0000.jpg", "test/samples/one_way_train_0001.jpg", "test/samples/partially_blank0.jpg", "test/samples/partially_blank1.jpg", "test/samples/smooth0.jpg", "test/samples/smooth1.jpg", "test/samples/smooth2.jpg", "test/samples/smooth3.jpg", "test/samples/smooth4.jpg", "test/samples/smooth5.jpg", "test/samples/smooth6.jpg", "test/samples/str-cv-rotated.jpg", "test/samples/str-cv.jpg", "test/samples/str-ov.jpg", "test/samples/stuff.jpg", "test/test_curve.rb", "test/test_cvavgcomp.rb", "test/test_cvbox2d.rb", "test/test_cvcapture.rb", "test/test_cvchain.rb", "test/test_cvcircle32f.rb", "test/test_cvconnectedcomp.rb", "test/test_cvcontour.rb", "test/test_cvcontourtree.rb", "test/test_cverror.rb", "test/test_cvfeaturetree.rb", "test/test_cvfont.rb", "test/test_cvhaarclassifiercascade.rb", "test/test_cvhistogram.rb", "test/test_cvhumoments.rb", "test/test_cvline.rb", "test/test_cvmat.rb", "test/test_cvmat_drawing.rb", "test/test_cvmat_dxt.rb", "test/test_cvmat_imageprocessing.rb", "test/test_cvmat_matching.rb", "test/test_cvmoments.rb", "test/test_cvpoint.rb", "test/test_cvpoint2d32f.rb", "test/test_cvpoint3d32f.rb", "test/test_cvrect.rb", "test/test_cvscalar.rb", "test/test_cvseq.rb", "test/test_cvsize.rb", "test/test_cvsize2d32f.rb", "test/test_cvslice.rb", "test/test_cvsurfparams.rb", "test/test_cvsurfpoint.rb", "test/test_cvtermcriteria.rb", "test/test_cvtwopoints.rb", "test/test_cvvideowriter.rb", "test/test_eigenfaces.rb", "test/test_fisherfaces.rb", "test/test_iplconvkernel.rb", "test/test_iplimage.rb", "test/test_lbph.rb", "test/test_mouseevent.rb", "test/test_opencv.rb", "test/test_pointset.rb", "test/test_preliminary.rb", "test/test_trackbar.rb", "test/test_window.rb"] + s.extra_rdoc_files = ["DEVELOPERS_NOTE.md", "History.txt", "License.txt", "Manifest.txt", "README.md", "examples/facerec/readme.md"] + s.files = [".gitignore", ".yardopts", "DEVELOPERS_NOTE.md", "Gemfile", "History.txt", "License.txt", "Manifest.txt", "README.md", "Rakefile", "config.yml", "examples/alpha_blend.rb", "examples/contours/bitmap-contours-with-labels.png", "examples/contours/bitmap-contours.png", "examples/contours/bounding-box-detect-canny.rb", "examples/contours/contour_retrieval_modes.rb", "examples/contours/rotated-boxes.jpg", "examples/convexhull.rb", "examples/face_detect.rb", "examples/facerec/create_csv.rb", "examples/facerec/facerec_eigenfaces.rb", "examples/facerec/facerec_fisherfaces.rb", "examples/facerec/facerec_lbph.rb", "examples/facerec/readme.md", "examples/find_obj.rb", "examples/houghcircle.rb", "examples/images/box.png", "examples/images/box_in_scene.png", "examples/images/inpaint.png", "examples/images/lena-256x256.jpg", "examples/images/lena-eyes.jpg", "examples/images/lenna-rotated.jpg", "examples/images/lenna.jpg", "examples/images/stuff.jpg", "examples/images/tiffany.jpg", "examples/inpaint.rb", "examples/match_kdtree.rb", "examples/match_template.rb", "examples/paint.rb", "examples/snake.rb", "ext/opencv/algorithm.cpp", "ext/opencv/algorithm.h", "ext/opencv/curve.cpp", "ext/opencv/curve.h", "ext/opencv/cvavgcomp.cpp", "ext/opencv/cvavgcomp.h", "ext/opencv/cvbox2d.cpp", "ext/opencv/cvbox2d.h", "ext/opencv/cvcapture.cpp", "ext/opencv/cvcapture.h", "ext/opencv/cvchain.cpp", "ext/opencv/cvchain.h", "ext/opencv/cvcircle32f.cpp", "ext/opencv/cvcircle32f.h", "ext/opencv/cvconnectedcomp.cpp", "ext/opencv/cvconnectedcomp.h", "ext/opencv/cvcontour.cpp", "ext/opencv/cvcontour.h", "ext/opencv/cvcontourtree.cpp", "ext/opencv/cvcontourtree.h", "ext/opencv/cvconvexitydefect.cpp", "ext/opencv/cvconvexitydefect.h", "ext/opencv/cverror.cpp", "ext/opencv/cverror.h", "ext/opencv/cvfeaturetree.cpp", "ext/opencv/cvfeaturetree.h", "ext/opencv/cvfont.cpp", "ext/opencv/cvfont.h", "ext/opencv/cvhaarclassifiercascade.cpp", "ext/opencv/cvhaarclassifiercascade.h", "ext/opencv/cvhistogram.cpp", "ext/opencv/cvhistogram.h", "ext/opencv/cvhumoments.cpp", "ext/opencv/cvhumoments.h", "ext/opencv/cvline.cpp", "ext/opencv/cvline.h", "ext/opencv/cvmat.cpp", "ext/opencv/cvmat.h", "ext/opencv/cvmemstorage.cpp", "ext/opencv/cvmemstorage.h", "ext/opencv/cvmoments.cpp", "ext/opencv/cvmoments.h", "ext/opencv/cvpoint.cpp", "ext/opencv/cvpoint.h", "ext/opencv/cvpoint2d32f.cpp", "ext/opencv/cvpoint2d32f.h", "ext/opencv/cvpoint3d32f.cpp", "ext/opencv/cvpoint3d32f.h", "ext/opencv/cvrect.cpp", "ext/opencv/cvrect.h", "ext/opencv/cvscalar.cpp", "ext/opencv/cvscalar.h", "ext/opencv/cvseq.cpp", "ext/opencv/cvseq.h", "ext/opencv/cvsize.cpp", "ext/opencv/cvsize.h", "ext/opencv/cvsize2d32f.cpp", "ext/opencv/cvsize2d32f.h", "ext/opencv/cvslice.cpp", "ext/opencv/cvslice.h", "ext/opencv/cvsurfparams.cpp", "ext/opencv/cvsurfparams.h", "ext/opencv/cvsurfpoint.cpp", "ext/opencv/cvsurfpoint.h", "ext/opencv/cvtermcriteria.cpp", "ext/opencv/cvtermcriteria.h", "ext/opencv/cvtwopoints.cpp", "ext/opencv/cvtwopoints.h", "ext/opencv/cvutils.cpp", "ext/opencv/cvutils.h", "ext/opencv/cvvideowriter.cpp", "ext/opencv/cvvideowriter.h", "ext/opencv/eigenfaces.cpp", "ext/opencv/eigenfaces.h", "ext/opencv/extconf.rb", "ext/opencv/facerecognizer.cpp", "ext/opencv/facerecognizer.h", "ext/opencv/fisherfaces.cpp", "ext/opencv/fisherfaces.h", "ext/opencv/gui.cpp", "ext/opencv/gui.h", "ext/opencv/iplconvkernel.cpp", "ext/opencv/iplconvkernel.h", "ext/opencv/iplimage.cpp", "ext/opencv/iplimage.h", "ext/opencv/lbph.cpp", "ext/opencv/lbph.h", "ext/opencv/mouseevent.cpp", "ext/opencv/mouseevent.h", "ext/opencv/opencv.cpp", "ext/opencv/opencv.h", "ext/opencv/pointset.cpp", "ext/opencv/pointset.h", "ext/opencv/trackbar.cpp", "ext/opencv/trackbar.h", "ext/opencv/window.cpp", "ext/opencv/window.h", "images/CvMat_sobel.png", "images/CvMat_sub_rect.png", "images/CvSeq_relationmap.png", "lib/opencv.rb", "lib/opencv/psyched_yaml.rb", "lib/opencv/version.rb", "ruby-opencv.gemspec", "test/eigenfaces_save.xml", "test/fisherfaces_save.xml", "test/helper.rb", "test/lbph_save.xml", "test/runner.rb", "test/samples/airplane.jpg", "test/samples/baboon.jpg", "test/samples/baboon200.jpg", "test/samples/baboon200_rotated.jpg", "test/samples/blank0.jpg", "test/samples/blank1.jpg", "test/samples/blank2.jpg", "test/samples/blank3.jpg", "test/samples/blank4.jpg", "test/samples/blank5.jpg", "test/samples/blank6.jpg", "test/samples/blank7.jpg", "test/samples/blank8.jpg", "test/samples/blank9.jpg", "test/samples/cat.jpg", "test/samples/chessboard.jpg", "test/samples/contours.jpg", "test/samples/fruits.jpg", "test/samples/haarcascade_frontalface_alt.xml.gz", "test/samples/inpaint-mask.bmp", "test/samples/lena-256x256.jpg", "test/samples/lena-32x32.jpg", "test/samples/lena-eyes.jpg", "test/samples/lena-inpaint.jpg", "test/samples/lena.jpg", "test/samples/lines.jpg", "test/samples/messy0.jpg", "test/samples/messy1.jpg", "test/samples/movie_sample.avi", "test/samples/one_way_train_0000.jpg", "test/samples/one_way_train_0001.jpg", "test/samples/partially_blank0.jpg", "test/samples/partially_blank1.jpg", "test/samples/smooth0.jpg", "test/samples/smooth1.jpg", "test/samples/smooth2.jpg", "test/samples/smooth3.jpg", "test/samples/smooth4.jpg", "test/samples/smooth5.jpg", "test/samples/smooth6.jpg", "test/samples/str-cv-rotated.jpg", "test/samples/str-cv.jpg", "test/samples/str-ov.jpg", "test/samples/stuff.jpg", "test/test_curve.rb", "test/test_cvavgcomp.rb", "test/test_cvbox2d.rb", "test/test_cvcapture.rb", "test/test_cvchain.rb", "test/test_cvcircle32f.rb", "test/test_cvconnectedcomp.rb", "test/test_cvcontour.rb", "test/test_cvcontourtree.rb", "test/test_cverror.rb", "test/test_cvfeaturetree.rb", "test/test_cvfont.rb", "test/test_cvhaarclassifiercascade.rb", "test/test_cvhistogram.rb", "test/test_cvhumoments.rb", "test/test_cvline.rb", "test/test_cvmat.rb", "test/test_cvmat_drawing.rb", "test/test_cvmat_dxt.rb", "test/test_cvmat_imageprocessing.rb", "test/test_cvmoments.rb", "test/test_cvpoint.rb", "test/test_cvpoint2d32f.rb", "test/test_cvpoint3d32f.rb", "test/test_cvrect.rb", "test/test_cvscalar.rb", "test/test_cvseq.rb", "test/test_cvsize.rb", "test/test_cvsize2d32f.rb", "test/test_cvslice.rb", "test/test_cvsurfparams.rb", "test/test_cvsurfpoint.rb", "test/test_cvtermcriteria.rb", "test/test_cvtwopoints.rb", "test/test_cvvideowriter.rb", "test/test_eigenfaces.rb", "test/test_fisherfaces.rb", "test/test_iplconvkernel.rb", "test/test_iplimage.rb", "test/test_lbph.rb", "test/test_mouseevent.rb", "test/test_opencv.rb", "test/test_pointset.rb", "test/test_preliminary.rb", "test/test_trackbar.rb", "test/test_window.rb", "yard_extension.rb"] s.homepage = "https://github.com/ruby-opencv/ruby-opencv/" s.licenses = ["The BSD License"] s.rdoc_options = ["--main", "README.md"] - s.require_paths = ["lib"] s.rubyforge_project = "ruby-opencv" - s.rubygems_version = "2.1.11" + s.rubygems_version = "2.2.1" s.summary = "OpenCV wrapper for Ruby" - s.test_files = ["test/test_cvcontour.rb", "test/test_eigenfaces.rb", "test/test_cvmoments.rb", "test/test_cvseq.rb", "test/test_cvcontourtree.rb", "test/test_cvbox2d.rb", "test/test_iplimage.rb", "test/test_cvvideowriter.rb", "test/test_cvline.rb", "test/test_cvhumoments.rb", "test/test_cvfont.rb", "test/test_cvconnectedcomp.rb", "test/test_cvhistogram.rb", "test/test_trackbar.rb", "test/test_cvmat_imageprocessing.rb", "test/test_cvhaarclassifiercascade.rb", "test/test_cvcircle32f.rb", "test/test_cvcapture.rb", "test/test_cvmat_dxt.rb", "test/test_cvrect.rb", "test/test_iplconvkernel.rb", "test/test_cvsurfpoint.rb", "test/test_cvavgcomp.rb", "test/test_cvscalar.rb", "test/test_pointset.rb", "test/test_curve.rb", "test/test_cvtermcriteria.rb", "test/test_cvtwopoints.rb", "test/test_cvsurfparams.rb", "test/test_cvpoint2d32f.rb", "test/test_cvpoint3d32f.rb", "test/test_cvfeaturetree.rb", "test/test_mouseevent.rb", "test/test_cvchain.rb", "test/test_cvmat.rb", "test/test_fisherfaces.rb", "test/test_cvmat_matching.rb", "test/test_cverror.rb", "test/test_cvpoint.rb", "test/test_cvsize2d32f.rb", "test/test_preliminary.rb", "test/test_cvmat_drawing.rb", "test/test_lbph.rb", "test/test_cvsize.rb", "test/test_window.rb", "test/test_cvslice.rb", "test/test_opencv.rb"] + s.test_files = ["test/test_cvcontour.rb", "test/test_eigenfaces.rb", "test/test_cvmoments.rb", "test/test_cvseq.rb", "test/test_cvcontourtree.rb", "test/test_cvbox2d.rb", "test/test_iplimage.rb", "test/test_cvvideowriter.rb", "test/test_cvline.rb", "test/test_cvhumoments.rb", "test/test_cvfont.rb", "test/test_cvconnectedcomp.rb", "test/test_cvhistogram.rb", "test/test_trackbar.rb", "test/test_cvmat_imageprocessing.rb", "test/test_cvhaarclassifiercascade.rb", "test/test_cvcircle32f.rb", "test/test_cvcapture.rb", "test/test_cvmat_dxt.rb", "test/test_cvrect.rb", "test/test_iplconvkernel.rb", "test/test_cvsurfpoint.rb", "test/test_cvavgcomp.rb", "test/test_cvscalar.rb", "test/test_pointset.rb", "test/test_curve.rb", "test/test_cvtermcriteria.rb", "test/test_cvtwopoints.rb", "test/test_cvsurfparams.rb", "test/test_cvpoint2d32f.rb", "test/test_cvpoint3d32f.rb", "test/test_cvfeaturetree.rb", "test/test_mouseevent.rb", "test/test_cvchain.rb", "test/test_cvmat.rb", "test/test_fisherfaces.rb", "test/test_cverror.rb", "test/test_cvpoint.rb", "test/test_cvsize2d32f.rb", "test/test_preliminary.rb", "test/test_cvmat_drawing.rb", "test/test_lbph.rb", "test/test_cvsize.rb", "test/test_window.rb", "test/test_cvslice.rb", "test/test_opencv.rb"] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, ["~> 4.0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, ["~> 3.7"]) + s.add_development_dependency(%q, ["~> 0"]) + s.add_development_dependency(%q, ["~> 0"]) + s.add_development_dependency(%q, ["~> 3.8"]) else s.add_dependency(%q, ["~> 4.0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 3.7"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 3.8"]) end else s.add_dependency(%q, ["~> 4.0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 3.7"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 0"]) + s.add_dependency(%q, ["~> 3.8"]) end end diff --git a/test/test_cvmat_matching.rb b/test/test_cvmat_matching.rb deleted file mode 100755 index 27d8006..0000000 --- a/test/test_cvmat_matching.rb +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env ruby -# -*- mode: ruby; coding: utf-8 -*- -require 'test/unit' -require 'opencv' -require File.expand_path(File.dirname(__FILE__)) + '/helper' - -include OpenCV - -# Tests for matching functions of OpenCV::CvMat -class TestCvMat_matching < OpenCVTestCase - def setup - @query = read_test_image('query.png') - @images = ['1.png', '2.png', '3.png'].map{|f| read_test_image('train', f)} - end - - def data_dir - File.join(File.dirname(__FILE__), '..', 'examples', 'matching_to_many_images') - end - - def read_test_image(*path) - CvMat.load File.join(data_dir, *path), CV_LOAD_IMAGE_GRAYSCALE - end - - def test_match_descriptors - matchs = @query.match_descriptors(@images) - match_index, count = matchs.max_by {|image_index, count| count} - assert_equal 2, match_index - end - - def test_match_descriptors_with_empty_image_array - assert_equal({}, @query.match_descriptors([])) - end - - def test_match_descriptors_with_wrong_detector_type_argument - assert_raise ArgumentError do - @query.match_descriptors(@images, "Wrong") - end - end - - def test_match_descriptors_with_wrong_descriptor_type_argument - assert_raise ArgumentError do - @query.match_descriptors(@images, "SURF", "wrong") - end - end - - def test_match_descriptors_with_wrong_matcher_type_argument - assert_raise ArgumentError do - @query.match_descriptors(@images, "SURF", "SURF", "wrong") - end - end - - def test_match_descriptors_with_invalid_image_array - assert_raise TypeError do - @query.match_descriptors([DUMMY_OBJ, DUMMY_OBJ]) - end - end -end diff --git a/test/test_opencv.rb b/test/test_opencv.rb index 0a8230d..ddea724 100755 --- a/test/test_opencv.rb +++ b/test/test_opencv.rb @@ -9,14 +9,14 @@ include OpenCV class TestOpenCV < OpenCVTestCase def test_constants # OpenCV version - assert_equal('2.4.7', CV_VERSION) + assert_equal('2.4.8', CV_VERSION) assert_equal(2, CV_MAJOR_VERSION) assert_equal(4, CV_MINOR_VERSION) - assert_equal(7, CV_SUBMINOR_VERSION) + assert_equal(8, CV_SUBMINOR_VERSION) assert_equal(2, CV_VERSION_EPOCH) assert_equal(4, CV_VERSION_MAJOR) - assert_equal(7, CV_VERSION_MINOR) + assert_equal(8, CV_VERSION_MINOR) assert_equal(0, CV_VERSION_REVISION) # Depths @@ -149,7 +149,9 @@ class TestOpenCV < OpenCVTestCase assert_equal(4, CV_FM_LMEDS) # Flags of window + assert_equal(0, CV_WINDOW_NORMAL) assert_equal(1, CV_WINDOW_AUTOSIZE) + assert_equal(4096, CV_WINDOW_OPENGL) # Object detection mode assert_equal(1, CV_HAAR_DO_CANNY_PRUNING) diff --git a/yard_extension.rb b/yard_extension.rb new file mode 100644 index 0000000..46f68a3 --- /dev/null +++ b/yard_extension.rb @@ -0,0 +1,5 @@ +require 'yard' + +YARD::Tags::Library.define_tag('OpenCV function', :opencv_func) +YARD::Tags::Library.visible_tags.place(:opencv_func).before(:abstract) +