From 19b8a74911eb46c4c39f1d501048e4ec370c266f Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 5 Aug 2012 01:45:20 +0900 Subject: [PATCH] add documents of CvHaarClassifierCascade --- ext/opencv/cvhaarclassifiercascade.cpp | 98 ++++++++++--------------- ext/opencv/cvhaarclassifiercascade.h | 2 +- ext/opencv/opencv.cpp | 2 +- images/face_detect_from_lena.jpg | Bin 14197 -> 0 bytes 4 files changed, 41 insertions(+), 61 deletions(-) delete mode 100644 images/face_detect_from_lena.jpg diff --git a/ext/opencv/cvhaarclassifiercascade.cpp b/ext/opencv/cvhaarclassifiercascade.cpp index 1bbb77f..ae24053 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/opencv.cpp b/ext/opencv/opencv.cpp index 28e9086..aac8cfc 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -711,7 +711,7 @@ extern "C" { mOpenCV::cCvConnectedComp::init_ruby_class(); mOpenCV::cCvAvgComp::init_ruby_class(); - mOpenCV::cCvHaarClassifierCascade::define_ruby_class(); + mOpenCV::cCvHaarClassifierCascade::init_ruby_class(); mOpenCV::mGUI::define_ruby_module(); mOpenCV::mGUI::cWindow::define_ruby_class(); mOpenCV::mGUI::cTrackbar::define_ruby_class(); diff --git a/images/face_detect_from_lena.jpg b/images/face_detect_from_lena.jpg deleted file mode 100644 index eabd54e92dda29f471820e4c2d26b5250b5610e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14197 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 P+?44u*AVPXye|DWmoV92