From a2b46e483958e31e71985caa98a07ab1e21544ff Mon Sep 17 00:00:00 2001 From: ser1zw Date: Sun, 3 Apr 2016 07:47:06 +0900 Subject: [PATCH] change module name to Cv --- ext/opencv/cascadeclassifier.cpp | 2 +- ext/opencv/cascadeclassifier.cppe | 138 ++++ ext/opencv/error.cpp | 2 +- ext/opencv/error.cppe | 92 +++ ext/opencv/mat.cpp | 2 +- ext/opencv/mat.cppe | 875 +++++++++++++++++++++ ext/opencv/mat_drawing.cppe | 158 ++++ ext/opencv/mat_imgproc.cppe | 181 +++++ ext/opencv/opencv.cpp | 2 +- ext/opencv/opencv.cppe | 109 +++ ext/opencv/opencv_const.cppe | 381 +++++++++ ext/opencv/point.cpp | 2 +- ext/opencv/point.cppe | 172 ++++ ext/opencv/rect.cpp | 2 +- ext/opencv/rect.cppe | 200 +++++ ext/opencv/scalar.cpp | 2 +- ext/opencv/scalar.cppe | 132 ++++ ext/opencv/size.cpp | 2 +- ext/opencv/size.cppe | 146 ++++ ext/opencv/trackbar.cpp | 2 +- ext/opencv/trackbar.cppe | 129 +++ ext/opencv/videocapture.cpp | 2 +- ext/opencv/videocapture.cppe | 266 +++++++ ext/opencv/window.cpp | 2 +- ext/opencv/window.cppe | 275 +++++++ lib/opencv.rb | 2 +- lib/opencv/basic_structs.rb | 2 +- lib/opencv/cvmat.rb | 2 +- lib/opencv/version.rb | 2 +- ruby-opencv.gemspec | 2 +- test/helper.rb | 4 +- test/legacy/test_cvmat.rb | 6 +- test/legacy/test_cvmat.rbe | 213 +++++ test/legacy/test_cvmat_imageprocessing.rb | 10 +- test/legacy/test_cvmat_imageprocessing.rbe | 84 ++ test/test_cascadeclassifier.rb | 4 +- test/test_mat.rb | 20 +- test/test_mat_imgproc.rb | 30 +- test/test_opencv.rb | 24 +- test/test_point.rb | 6 +- test/test_rect.rb | 6 +- test/test_scalar.rb | 8 +- test/test_size.rb | 6 +- test/test_videocapture.rb | 4 +- 44 files changed, 3631 insertions(+), 80 deletions(-) create mode 100644 ext/opencv/cascadeclassifier.cppe create mode 100644 ext/opencv/error.cppe create mode 100644 ext/opencv/mat.cppe create mode 100644 ext/opencv/mat_drawing.cppe create mode 100644 ext/opencv/mat_imgproc.cppe create mode 100644 ext/opencv/opencv.cppe create mode 100644 ext/opencv/opencv_const.cppe create mode 100644 ext/opencv/point.cppe create mode 100644 ext/opencv/rect.cppe create mode 100644 ext/opencv/scalar.cppe create mode 100644 ext/opencv/size.cppe create mode 100644 ext/opencv/trackbar.cppe create mode 100644 ext/opencv/videocapture.cppe create mode 100644 ext/opencv/window.cppe create mode 100755 test/legacy/test_cvmat.rbe create mode 100755 test/legacy/test_cvmat_imageprocessing.rbe diff --git a/ext/opencv/cascadeclassifier.cpp b/ext/opencv/cascadeclassifier.cpp index 782e94f..ed3ce26 100644 --- a/ext/opencv/cascadeclassifier.cpp +++ b/ext/opencv/cascadeclassifier.cpp @@ -124,7 +124,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "CascadeClassifier", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/cascadeclassifier.cppe b/ext/opencv/cascadeclassifier.cppe new file mode 100644 index 0000000..782e94f --- /dev/null +++ b/ext/opencv/cascadeclassifier.cppe @@ -0,0 +1,138 @@ +#include "opencv2/objdetect.hpp" + +#include "opencv.hpp" +#include "mat.hpp" +#include "size.hpp" +#include "rect.hpp" +#include "error.hpp" + +/* + * Document-class: OpenCV::CascadeClassifier + */ +namespace rubyopencv { + namespace CascadeClassifier { + void free_cascadeclassifier(void* ptr); + size_t memsize_cascadeclassifier(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_cascadeclassifier_type = { + "CascadeClassifier", + { 0, free_cascadeclassifier, memsize_cascadeclassifier, 0 }, + 0, + 0, + 0 + }; + + void free_cascadeclassifier(void* ptr) { + delete (cv::CascadeClassifier*)ptr; + } + + size_t memsize_cascadeclassifier(const void* ptr) { + return sizeof(cv::CascadeClassifier); + } + + cv::CascadeClassifier* obj2cascadeclassifier(VALUE obj) { + cv::CascadeClassifier* ptr = NULL; + TypedData_Get_Struct(obj, cv::CascadeClassifier, &opencv_cascadeclassifier_type, ptr); + return ptr; + } + + VALUE rb_allocate(VALUE klass) { + cv::CascadeClassifier* ptr = new cv::CascadeClassifier(); + return TypedData_Wrap_Struct(klass, &opencv_cascadeclassifier_type, ptr); + } + + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE filename; + rb_scan_args(argc, argv, "01", &filename); + + cv::CascadeClassifier* selfptr = obj2cascadeclassifier(self); + if (!NIL_P(filename)) { + selfptr->load(StringValueCStr(filename)); + } + + return self; + } + + VALUE rb_load(VALUE self, VALUE filename) { + cv::CascadeClassifier* selfptr = obj2cascadeclassifier(self); + bool ret = selfptr->load(StringValueCStr(filename)); + + return ret ? Qtrue : Qfalse; + } + + /* + * Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles. + * + * @overload detect_multi_scale(image, options = nil) + * @param image [Mat] 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 [Integer] :min_neighbors + * Parameter specifying how many neighbors each candidate rectangle should have to retain it. + * @option options [Size] :min_size + * Minimum possible object size. Objects smaller than that are ignored. + * @option options [Size] :max_size + * Maximum possible object size. Objects larger than that are ignored. + * @return [Array] Detected objects as a list of rectangles. + * @opencv_func cv::CascadeClassifier::detectMultiScale + */ + VALUE rb_detect_multi_scale(int argc, VALUE *argv, VALUE self) { + VALUE image, options; + + rb_scan_args(argc, argv, "11", &image, &options); + + cv::CascadeClassifier* selfptr = obj2cascadeclassifier(self); + std::vector objects; + try { + cv::Mat* m = Mat::obj2mat(image); + if (NIL_P(options)) { + selfptr->detectMultiScale(*m, objects); + } + else { + Check_Type(options, T_HASH); + double scale_factor = NUM2DBL_DEFAULT(HASH_LOOKUP(options, "scale_factor"), 1.1); + int min_neighbors = NUM2INT_DEFAULT(HASH_LOOKUP(options, "min_neighbors"), 3); + cv::Size min_size; + cv::Size max_size; + + VALUE tmp = Qnil; + tmp = rb_hash_lookup(options, ID2SYM(rb_intern("min_size"))); + if (!NIL_P(tmp)) { + min_size = *(Size::obj2size(tmp)); + } + tmp = rb_hash_lookup(options, ID2SYM(rb_intern("max_size"))); + if (!NIL_P(tmp)) { + max_size = *(Size::obj2size(tmp)); + } + selfptr->detectMultiScale(*m, objects, scale_factor, min_neighbors, 0, min_size, max_size); + } + } + catch (cv::Exception& e) { + Error::raise(e); + } + + const long size = objects.size(); + VALUE detected_objects = rb_ary_new_capa(size); + for (long i = 0; i < size; i++) { + VALUE v = Rect::rect2obj(objects[i]); + rb_ary_store(detected_objects, i, v); + } + + return detected_objects; + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "CascadeClassifier", rb_cData); + 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, "load", RUBY_METHOD_FUNC(rb_load), 1); + rb_define_method(rb_klass, "detect_multi_scale", RUBY_METHOD_FUNC(rb_detect_multi_scale), -1); + } + } +} diff --git a/ext/opencv/error.cpp b/ext/opencv/error.cpp index ead656f..28cc9c1 100644 --- a/ext/opencv/error.cpp +++ b/ext/opencv/error.cpp @@ -29,7 +29,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Error", rb_eStandardError); REGISTER_CVERROR("StsOk", cv::Error::StsOk); diff --git a/ext/opencv/error.cppe b/ext/opencv/error.cppe new file mode 100644 index 0000000..ead656f --- /dev/null +++ b/ext/opencv/error.cppe @@ -0,0 +1,92 @@ +// -*- mode: c++; coding: utf-8 -*- +#include +#include "error.hpp" + +namespace rubyopencv { + namespace Error { + VALUE rb_klass; + std::map error_code_map; + + inline void REGISTER_CVERROR(const char* object_name, int error_code) { + VALUE klass = rb_define_class_under(rb_klass, object_name, rb_klass); + error_code_map[error_code] = klass; + } + + VALUE rb_class() { + return rb_klass; + } + + VALUE find_error_by_code(int error_code) { + VALUE klass = Qnil; + if (error_code_map.find(error_code) != error_code_map.end()) { + klass = error_code_map[error_code]; + } + return NIL_P(klass) ? rb_eStandardError : klass; + } + + void raise(cv::Exception e) { + rb_raise(find_error_by_code(e.code), "%s", e.what()); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + rb_klass = rb_define_class_under(opencv, "Error", rb_eStandardError); + + REGISTER_CVERROR("StsOk", cv::Error::StsOk); + REGISTER_CVERROR("StsBackTrace", cv::Error::StsBackTrace); + REGISTER_CVERROR("StsError", cv::Error::StsError); + REGISTER_CVERROR("StsInternal", cv::Error::StsInternal); + REGISTER_CVERROR("StsNoMem", cv::Error::StsNoMem); + REGISTER_CVERROR("StsBadArg", cv::Error::StsBadArg); + REGISTER_CVERROR("StsBadFunc", cv::Error::StsBadFunc); + REGISTER_CVERROR("StsNoConv", cv::Error::StsNoConv); + REGISTER_CVERROR("StsAutoTrace", cv::Error::StsAutoTrace); + REGISTER_CVERROR("HeaderIsNull", cv::Error::HeaderIsNull); + REGISTER_CVERROR("BadImageSize", cv::Error::BadImageSize); + REGISTER_CVERROR("BadOffset", cv::Error::BadOffset); + REGISTER_CVERROR("BadDataPtr", cv::Error::BadDataPtr); + REGISTER_CVERROR("BadStep", cv::Error::BadStep); + REGISTER_CVERROR("BadModelOrChSeq", cv::Error::BadModelOrChSeq); + REGISTER_CVERROR("BadNumChannels", cv::Error::BadNumChannels); + REGISTER_CVERROR("BadNumChannel1U", cv::Error::BadNumChannel1U); + REGISTER_CVERROR("BadDepth", cv::Error::BadDepth); + REGISTER_CVERROR("BadAlphaChannel", cv::Error::BadAlphaChannel); + REGISTER_CVERROR("BadOrder", cv::Error::BadOrder); + REGISTER_CVERROR("BadOrigin", cv::Error::BadOrigin); + REGISTER_CVERROR("BadAlign", cv::Error::BadAlign); + REGISTER_CVERROR("BadCallBack", cv::Error::BadCallBack); + REGISTER_CVERROR("BadTileSize", cv::Error::BadTileSize); + REGISTER_CVERROR("BadCOI", cv::Error::BadCOI); + REGISTER_CVERROR("BadROISize", cv::Error::BadROISize); + REGISTER_CVERROR("MaskIsTiled", cv::Error::MaskIsTiled); + REGISTER_CVERROR("StsNullPtr", cv::Error::StsNullPtr); + REGISTER_CVERROR("StsVecLengthErr", cv::Error::StsVecLengthErr); + REGISTER_CVERROR("StsFilterStructContentErr", cv::Error::StsFilterStructContentErr); + REGISTER_CVERROR("StsKernelStructContentErr", cv::Error::StsKernelStructContentErr); + REGISTER_CVERROR("StsFilterOffsetErr", cv::Error::StsFilterOffsetErr); + REGISTER_CVERROR("StsBadSize", cv::Error::StsBadSize); + REGISTER_CVERROR("StsDivByZero", cv::Error::StsDivByZero); + REGISTER_CVERROR("StsInplaceNotSupported", cv::Error::StsInplaceNotSupported); + REGISTER_CVERROR("StsObjectNotFound", cv::Error::StsObjectNotFound); + REGISTER_CVERROR("StsUnmatchedFormats", cv::Error::StsUnmatchedFormats); + REGISTER_CVERROR("StsBadFlag", cv::Error::StsBadFlag); + REGISTER_CVERROR("StsBadPoint", cv::Error::StsBadPoint); + REGISTER_CVERROR("StsBadMask", cv::Error::StsBadMask); + REGISTER_CVERROR("StsUnmatchedSizes", cv::Error::StsUnmatchedSizes); + REGISTER_CVERROR("StsUnsupportedFormat", cv::Error::StsUnsupportedFormat); + REGISTER_CVERROR("StsOutOfRange", cv::Error::StsOutOfRange); + REGISTER_CVERROR("StsParseError", cv::Error::StsParseError); + REGISTER_CVERROR("StsNotImplemented", cv::Error::StsNotImplemented); + REGISTER_CVERROR("StsBadMemBlock", cv::Error::StsBadMemBlock); + REGISTER_CVERROR("StsAssert", cv::Error::StsAssert); + REGISTER_CVERROR("GpuNotSupported", cv::Error::GpuNotSupported); + REGISTER_CVERROR("GpuApiCallError", cv::Error::GpuApiCallError); + REGISTER_CVERROR("OpenGlNotSupported", cv::Error::OpenGlNotSupported); + REGISTER_CVERROR("OpenGlApiCallError", cv::Error::OpenGlApiCallError); + REGISTER_CVERROR("OpenCLApiCallError", cv::Error::OpenCLApiCallError); + REGISTER_CVERROR("OpenCLDoubleNotSupported", cv::Error::OpenCLDoubleNotSupported); + REGISTER_CVERROR("OpenCLInitError", cv::Error::OpenCLInitError); + REGISTER_CVERROR("OpenCLNoAMDBlasFft", cv::Error::OpenCLNoAMDBlasFft); + } + } +} diff --git a/ext/opencv/mat.cpp b/ext/opencv/mat.cpp index 40d6f82..141b2d7 100644 --- a/ext/opencv/mat.cpp +++ b/ext/opencv/mat.cpp @@ -817,7 +817,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Mat", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/mat.cppe b/ext/opencv/mat.cppe new file mode 100644 index 0000000..40d6f82 --- /dev/null +++ b/ext/opencv/mat.cppe @@ -0,0 +1,875 @@ +// -*- mode: c++; coding: utf-8 -*- +#include +#include "opencv2/highgui.hpp" + +#include "mat.hpp" +#include "mat_imgproc.hpp" +#include "mat_drawing.hpp" +#include "scalar.hpp" + +#include "error.hpp" + +/* + * Document-class: OpenCV::Mat + */ +namespace rubyopencv { + namespace Mat { + void free_mat(void* ptr); + size_t memsize_mat(const void *ptr); + + VALUE rb_klass = Qnil; + RubyMatAllocator allocator; + rb_data_type_t opencv_mat_type = { + "Mat", + { 0, free_mat, memsize_mat, 0 }, + 0, + 0, + 0 + }; + + cv::Mat* obj2mat(VALUE obj) { + cv::Mat* dataptr = NULL; + TypedData_Get_Struct(obj, cv::Mat, &opencv_mat_type, dataptr); + return dataptr; + } + + VALUE mat2obj(cv::Mat* ptr, VALUE klass) { + return TypedData_Wrap_Struct(klass, &opencv_mat_type, (void*)ptr); + } + + VALUE mat2obj(cv::Mat* ptr) { + return mat2obj(ptr, rb_klass); + } + + cv::Mat* empty_mat() { + cv::Mat* m = new cv::Mat(); + m->allocator = &allocator; + return m; + } + + void free_mat(void* ptr) { + if (ptr) { + cv::Mat* dataptr = (cv::Mat*)ptr; + dataptr->release(); + } + } + + size_t memsize_mat(const void *ptr) { + size_t size = 0; + if (ptr) { + cv::Mat* m = (cv::Mat*)ptr; + size += sizeof(*m); + if (m->u) { + size += m->u->size; + } + } + return size; + } + + VALUE rb_allocate(VALUE klass) { + return TypedData_Wrap_Struct(klass, &opencv_mat_type, 0); + } + + /* + * Creates a matrix + * + * @overload new(rows, cols, type) + * @param row [Integer] Number of rows in the matrix + * @param col [Integer] Number of columns in the matrix + * @param type [Integer] + * The type of the matrix elements in the form of constant CV_. + * @return [Mat] Created matrix + * @opencv_func cv::Mat + * @example + * mat1 = Mat.new(3, 4) # Creates a 3-channels 3x4 matrix whose elements are 8bit unsigned. + * mat2 = Mat.new(5, 6, CV_32F) # Creates a 1-channel 5x6 matrix whose elements are 32bit float. + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE row, column, type; + rb_scan_args(argc, argv, "21", &row, &column, &type); + + cv::Mat* dataptr = NULL; + try { + cv::Mat tempdata(NUM2INT(row), NUM2INT(column), (NIL_P(type) ? CV_8UC1 : NUM2INT(type))); + if (tempdata.empty()) { + rb_raise(rb_eNoMemError, "Failed to create matrix"); + return Qnil; + } + + dataptr = empty_mat(); + tempdata.copyTo(*dataptr); + + RTYPEDDATA_DATA(self) = dataptr; + } + catch (cv::Exception& e) { + delete dataptr; + Error::raise(e); + } + + return self; + } + + /** + * Returns a zero array of the specified size and type. + * + * @overload zeros(rows, cols, type) + * @param row [Integer] Number of rows in the matrix + * @param col [Integer] Number of columns in the matrix + * @param type [Integer] + * The type of the matrix elements in the form of constant CV_. + * @return [Mat] Zero array + */ + VALUE rb_zeros(VALUE self, VALUE rows, VALUE cols, VALUE type) { + cv::Mat* destptr = NULL; + try { + destptr = empty_mat(); + cv::Mat z = cv::Mat::zeros(NUM2INT(rows), NUM2INT(cols), NUM2INT(type)); + z.copyTo(*destptr); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr); + } + + /** + * Returns an array of all 1's of the specified size and type. + * + * @overload ones(rows, cols, type) + * @param row [Integer] Number of rows in the matrix + * @param col [Integer] Number of columns in the matrix + * @param type [Integer] + * The type of the matrix elements in the form of constant CV_. + * @return [Mat] Array of all 1's + */ + VALUE rb_ones(VALUE self, VALUE rows, VALUE cols, VALUE type) { + cv::Mat* destptr = NULL; + try { + destptr = empty_mat(); + cv::Mat z = cv::Mat::ones(NUM2INT(rows), NUM2INT(cols), NUM2INT(type)); + z.copyTo(*destptr); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr); + } + + /** + * Returns an identity matrix of the specified size and type. + * + * @overload eye(rows, cols, type) + * @param row [Integer] Number of rows in the matrix + * @param col [Integer] Number of columns in the matrix + * @param type [Integer] + * The type of the matrix elements in the form of constant CV_. + * @return [Mat] Identity matrix + */ + VALUE rb_eye(VALUE self, VALUE rows, VALUE cols, VALUE type) { + cv::Mat* destptr = NULL; + try { + destptr = empty_mat(); + cv::Mat z = cv::Mat::eye(NUM2INT(rows), NUM2INT(cols), NUM2INT(type)); + z.copyTo(*destptr); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr); + } + + /* + * Makes a clone of an object. + * + * @overload clone + * @return [Mat] Clone of the object + */ + VALUE rb_clone(VALUE self) { + VALUE clone = rb_obj_clone(self); + cv::Mat* selfptr = obj2mat(self); + cv::Mat* dataptr = NULL; + try { + dataptr = empty_mat(); + selfptr->copyTo(*dataptr); + RTYPEDDATA_DATA(clone) = dataptr; + } + catch (cv::Exception& e) { + delete dataptr; + Error::raise(e); + } + + return clone; + } + + VALUE rb_imread_internal(VALUE self, VALUE filename, VALUE flags, VALUE klass) { + cv::Mat* dataptr = NULL; + try { + cv::Mat tmp = cv::imread(StringValueCStr(filename), NUM2INT(flags)); + if (tmp.empty()) { + rb_raise(rb_eStandardError, "Failed to load image"); + return Qnil; + } + + dataptr = empty_mat(); + tmp.copyTo(*dataptr); + } + catch (cv::Exception& e) { + delete dataptr; + Error::raise(e); + } + + return mat2obj(dataptr, klass); + } + + /* + * Loads an image from a file. + * + * @overload imread(filename, flags) + * @param filename [String] Name of file to be loaded. + * @param flags [Integer] Flags specifying the color type of a loaded image: + * - CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. + * - CV_LOAD_IMAGE_COLOR - If set, always convert image to the color one + * - CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one + * - >0 Return a 3-channel color image. + * - \=0 Return a grayscale image. + * - <0 Return the loaded image as is (with alpha channel). + * @return [Mat] Loaded image + * @opencv_func cv::imread + */ + VALUE rb_imread(VALUE self, VALUE filename, VALUE flags) { + return rb_imread_internal(self, filename, flags, rb_klass); + } + + VALUE rb_imread_as(VALUE self, VALUE filename, VALUE flags, VALUE klass) { + return rb_imread_internal(self, filename, flags, klass); + } + + VALUE rb_imwrite_internal(VALUE filename, VALUE img, VALUE params) { + std::vector params_value; + + if (!NIL_P(params)) { + Check_Type(params, T_ARRAY); + int size = RARRAY_LEN(params); + for (long i = 0; i < size; i++) { + VALUE n = rb_ary_entry(params, i); + params_value.push_back(NUM2INT(n)); + } + } + + cv::Mat* m = obj2mat(img); + bool ret = false; + try { + ret = cv::imwrite(StringValueCStr(filename), *m, params_value); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return ret ? Qtrue : Qfalse; + } + + /* + * Saves an image to a specified file. + * The image format is chosen based on the filename extension. + * + * @overload save(filename, params = nil) + * @param filename [String] Name of the file + * @return [Boolean] Result + * @opencv_func cv::imwrite + */ + VALUE rb_save(int argc, VALUE* argv, VALUE self) { + VALUE filename, params; + rb_scan_args(argc, argv, "11", &filename, ¶ms); + return rb_imwrite_internal(filename, self, params); + } + + VALUE rb_imencode_internal(VALUE ext, VALUE img, VALUE params) { + cv::Mat* dataptr = obj2mat(img); + std::vector buf; + std::vector params_vector; + + if (!NIL_P(params)) { + Check_Type(params, T_ARRAY); + size_t param_size = RARRAY_LEN(params); + for (size_t i = 0; i < param_size; i++) { + params_vector.push_back(NUM2INT(RARRAY_AREF(params, i))); + } + } + + try { + cv::imencode(StringValueCStr(ext), *dataptr, buf, params_vector); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + const size_t size = buf.size(); + VALUE array = rb_ary_new2(size); + for (size_t i = 0; i < size; i++) { + rb_ary_push(array, CHR2FIX(buf[i])); + } + return array; + } + + /* + * Encodes an image into a memory buffer. + * + * @overload imencode(ext, params = nil) + * @param ext [String] File extension that defines the output format. + * @param params [Array] Format-specific parameters. + * @return [Array] Encoded result + * @opencv_func cv::imwrite + */ + VALUE rb_imencode(int argc, VALUE* argv, VALUE self) { + VALUE ext, params; + rb_scan_args(argc, argv, "11", &ext, ¶ms); + return rb_imencode_internal(ext, self, params); + } + + VALUE rb_imdecode_internal(VALUE self, VALUE buf, VALUE flags, VALUE klass) { + Check_Type(buf, T_ARRAY); + + const size_t size = RARRAY_LEN(buf); + std::vector data(size); + for (size_t i = 0; i < size; i++) { + data[i] = (uchar)(NUM2INT(RARRAY_AREF(buf, i)) & 0xff); + } + + cv::Mat* dstptr = empty_mat(); + try { + cv::imdecode(data, NUM2INT(flags), dstptr); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, klass); + } + + /* + * Reads an image from a buffer in memory. + * @overload decode(buf, flags) + * @param buf [Array] Input array of bytes + * @param flags [Integer] Flags specifying the color type of a decoded image (the same flags as imread) + * @return [CvMat] Loaded matrix + * @opencv_func cvDecodeImageM + */ + VALUE rb_imdecode(VALUE self, VALUE buf, VALUE flags) { + return rb_imdecode_internal(self, buf, flags, rb_klass); + } + + VALUE rb_imdecode_as(VALUE self, VALUE buf, VALUE flags, VALUE klass) { + return rb_imdecode_internal(self, buf, flags, klass); + } + + /* + * Returns number of rows of the matrix. + * + * @overload rows + * @return [Integer] Number of rows of the matrix + */ + VALUE rb_rows(VALUE self) { + const cv::Mat* dataptr = obj2mat(self); + return INT2NUM(dataptr->rows); + } + + /* + * Returns number of columns of the matrix. + * + * @overload cols + * @return [Integer] Number of columns of the matrix + */ + VALUE rb_cols(VALUE self) { + const cv::Mat* dataptr = obj2mat(self); + return INT2NUM(dataptr->cols); + } + + /* + * Returns number of dimensions of the matrix. + * + * @overload dims + * @return [Integer] Number of dimensions of the matrix + */ + VALUE rb_dims(VALUE self) { + const cv::Mat* dataptr = obj2mat(self); + return INT2NUM(dataptr->dims); + } + + /* + * Returns depth of the matrix. + * + * @overload depth + * @return [Integer] Depth of the matrix + */ + VALUE rb_depth(VALUE self) { + const cv::Mat* dataptr = obj2mat(self); + return INT2NUM(dataptr->depth()); + } + + /* + * Returns number of channels of the matrix. + * + * @overload channels + * @return [Integer] Number of channels of the matrix + */ + VALUE rb_channels(VALUE self) { + const cv::Mat* dataptr = obj2mat(self); + return INT2NUM(dataptr->channels()); + } + + /* + * @overload to_s + * @return [String] String representation of the matrix + */ + VALUE rb_to_s(VALUE self) { + std::stringstream s; + cv::Mat* selfptr = obj2mat(self); + s << *selfptr; + + VALUE param[7]; + param[0] = rb_str_new2("<%s:%dx%d,depth=%s,channels=%d,\n%s>"); + param[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + param[2] = INT2NUM(selfptr->rows); + param[3] = INT2NUM(selfptr->cols); + param[4] = INT2NUM(selfptr->depth()); + param[5] = INT2NUM(selfptr->channels()); + param[6] = rb_str_new2(s.str().c_str()); + + int n = sizeof(param) / sizeof(param[0]); + return rb_f_sprintf(n, param); + } + + /** + * Returns the specified array element. + * + * @overload [](i) + * @param i [Integer] Zero-based component of the element index + * @overload [](i, j) + * @param i [Integer] Zero-based component of the element index + * @param j [Integer] Zero-based component of the element index + * @overload [](i, j, k) + * @param i [Integer] Zero-based component of the element index + * @param j [Integer] Zero-based component of the element index + * @param k [Integer] Zero-based component of the element index + * @overload [](i, j, k, ...) + * @param i [Integer] Zero-based component of the element index + * @param j [Integer] Zero-based component of the element index + * @param k [Integer] Zero-based component of the element index + * @return [Scalar] Array element + * @opencv_func cv::Mat.at + */ + VALUE rb_aref(VALUE self, VALUE args) { + int index[CV_MAX_DIM]; + const size_t length = RARRAY_LEN(args); + for (size_t i = 0; i < length; i++) { + index[i] = NUM2INT(rb_ary_entry(args, i)); + } + cv::Mat* selfptr = obj2mat(self); + cv::Scalar* scalar = NULL; + try { + switch (selfptr->depth()) { + case CV_8U: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_8S: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_16U: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_16S: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_32F: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_32S: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + case CV_64F: + scalar = new cv::Scalar(selfptr->at< cv::Scalar_ >(index)); + break; + default: + rb_raise(rb_eStandardError, "Invalid depth: %d", selfptr->depth()); + break; + } + } + catch (cv::Exception& e) { + delete scalar; + Error::raise(e); + } + return Scalar::scalar2obj(scalar); + } + + /* + * Changes the particular array element + * + * @overload []=(row, col, value) + * @param row [Integer] Row + * @param col [Integer] Column + * @param value [Scalar] The assigned value + * @return [Mat] self + * @opencv_func cv::Mat::at + */ + VALUE rb_aset(VALUE self, VALUE row, VALUE col, VALUE value) { + cv::Scalar* scalar = Scalar::obj2scalar(value); + cv::Mat* selfptr = obj2mat(self); + int y = NUM2INT(row); + int x = NUM2INT(col) * selfptr->channels(); + try { + switch (selfptr->depth()) { + case CV_8U: { + uchar* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (uchar)((*scalar)[i]); + } + break; + } + case CV_8S: { + char* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (char)((*scalar)[i]); + } + break; + } + case CV_16U: { + ushort* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (ushort)((*scalar)[i]); + } + break; + } + case CV_16S: { + short* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (short)((*scalar)[i]); + } + break; + } + case CV_32F: { + float* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (float)((*scalar)[i]); + } + break; + } + case CV_32S: { + int* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (int)((*scalar)[i]); + } + break; + } + case CV_64F: { + double* p = &(selfptr->ptr(y)[x]); + for (int i = 0; i < selfptr->channels(); i++) { + p[i] = (double)((*scalar)[i]); + } + break; + } + default: + rb_raise(rb_eStandardError, "Invalid depth: %d", selfptr->depth()); + break; + } + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + + /* + * Computes the per-element sum of two arrays or an array and a scalar. + * + * @overload +(value) + * @param value [Mat, Scalar] Array or scalar to add + * @return [Mat] Result array + * @opencv_func cv::Mat::operator+ + */ + VALUE rb_add(VALUE self, VALUE other) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* retptr = empty_mat(); + cv::Mat tmp; + + try { + if (rb_obj_is_kind_of(other, rb_klass)) { + cv::Mat* mat = obj2mat(other); + tmp = (*selfptr) + (*mat); + } + else if (rb_obj_is_kind_of(other, Scalar::klass())) { + cv::Scalar* s = Scalar::obj2scalar(other); + tmp = (*selfptr) + (*s); + } + else { + double scale = NUM2DBL(other); + tmp = (*selfptr) + scale; + } + tmp.copyTo(*retptr); + } + catch (cv::Exception& e) { + delete retptr; + Error::raise(e); + } + + return mat2obj(retptr, CLASS_OF(self)); + } + + /* + * Computes the per-element difference of two arrays or an array and a scalar. + * + * @overload -(value) + * @param value [Mat, Scalar] Array or scalar to subtract + * @return [Mat] Result array + * @opencv_func cv::Mat::operator- + */ + VALUE rb_sub(VALUE self, VALUE other) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* retptr = empty_mat(); + cv::Mat tmp; + + try { + if (rb_obj_is_kind_of(other, rb_klass)) { + cv::Mat* mat = obj2mat(other); + tmp = (*selfptr) - (*mat); + } + else if (rb_obj_is_kind_of(other, Scalar::klass())) { + cv::Scalar* s = Scalar::obj2scalar(other); + tmp = (*selfptr) - (*s); + } + else { + double scale = NUM2DBL(other); + tmp = (*selfptr) - scale; + } + tmp.copyTo(*retptr); + } + catch (cv::Exception& e) { + delete retptr; + Error::raise(e); + } + + return mat2obj(retptr, CLASS_OF(self)); + } + + /* + * Computes the per-element product of two arrays or an array and a scalar. + * + * @overload -(value) + * @param value [Mat, Scalar] Array or scalar to multiply + * @return [Mat] Result array + * @opencv_func cv::Mat::operator* + */ + VALUE rb_mul(VALUE self, VALUE other) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* retptr = empty_mat(); + cv::Mat tmp; + + try { + if (rb_obj_is_kind_of(other, rb_klass)) { + cv::Mat* mat = obj2mat(other); + tmp = (*selfptr) * (*mat); + } + else { + double scale = NUM2DBL(other); + tmp = (*selfptr) * scale; + } + tmp.copyTo(*retptr); + } + catch (cv::Exception& e) { + delete retptr; + Error::raise(e); + } + + return mat2obj(retptr, CLASS_OF(self)); + } + + /* + * Computes the per-element division of two arrays or an array and a scalar. + * + * @overload /(value) + * @param value [Mat, Scalar] Array or scalar to divide + * @return [Mat] Result array + * @opencv_func cv::Mat::operator/ + */ + VALUE rb_div(VALUE self, VALUE other) { + cv::Mat* selfptr = obj2mat(self); + cv::Mat* retptr = empty_mat(); + cv::Mat tmp; + + try { + if (rb_obj_is_kind_of(other, rb_klass)) { + cv::Mat* mat = obj2mat(other); + tmp = (*selfptr) / (*mat); + } + else { + double scale = NUM2DBL(other); + tmp = (*selfptr) / scale; + } + tmp.copyTo(*retptr); + } + catch (cv::Exception& e) { + delete retptr; + Error::raise(e); + } + + return mat2obj(retptr, CLASS_OF(self)); + } + + /* + * Sets all or some of the array elements to the specified value. + * + * @overload set_to(value, mask = nil) + * @param value [Scalar] Assigned scalar converted to the actual array type. + * @param mask [Mat] Operation mask of the same size as self. + * @return [Mat] Output array + */ + VALUE rb_set_to(int argc, VALUE *argv, VALUE self) { + VALUE value, mask; + rb_scan_args(argc, argv, "11", &value, &mask); + cv::Mat* selfptr = obj2mat(self); + cv::Mat* dstptr = empty_mat(); + try { + cv::Mat tmp; + cv::Scalar* s = Scalar::obj2scalar(value); + if (NIL_P(mask)) { + tmp = selfptr->setTo(*s); + } + else { + cv::Mat* maskptr = obj2mat(mask); + tmp = selfptr->setTo(*s, *maskptr); + } + tmp.copyTo(*dstptr); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, CLASS_OF(self)); + } + + /* + * 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, dtype = -1) + * @param src1 [Mat] The first source array. + * @param alpha [Number] Weight for the first array elements. + * @param src2 [Mat] The second source array. + * @param beta [Number] Weight for the second array elements. + * @param gamma [Number] Scalar added to each sum. + * @param dtype [Number] optional depth of the output array; when both input arrays have the same depth, + * dtype can be set to -1, which will be equivalent to src1.depth. + * @return [Mat] Output array + * @opencv_func cv::addWeighted + */ + VALUE rb_add_weighted(int argc, VALUE *argv, VALUE self) { + VALUE src1, alpha, src2, beta, gamma, dtype; + rb_scan_args(argc, argv, "51", &src1, &alpha, &src2, &beta, &gamma, &dtype); + int dtype_value = NIL_P(dtype) ? -1 : NUM2INT(dtype); + + cv::Mat* src1ptr = obj2mat(src1); + cv::Mat* src2ptr = obj2mat(src2); + cv::Mat* dstptr = empty_mat(); + try { + cv::addWeighted(*src1ptr, NUM2DBL(alpha), *src2ptr, NUM2DBL(beta), NUM2DBL(gamma), *dstptr, dtype_value); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, CLASS_OF(src1)); + } + + /* + * Scales, computes absolute values, and converts the result to 8-bit. + * + * @overload convert_scale_abs(alpha = 1, beta = 0) + * @return [Mat] Output array + * @opencv_func cv::convertScaleAbs + */ + VALUE rb_convert_scale_abs(int argc, VALUE *argv, VALUE self) { + VALUE alpha, beta; + rb_scan_args(argc, argv, "02", &alpha, &beta); + double alpha_value = NIL_P(alpha) ? 1.0 : NUM2DBL(alpha); + double beta_value = NIL_P(beta) ? 0 : NUM2DBL(beta); + + cv::Mat* selfptr = obj2mat(self); + cv::Mat* dstptr = empty_mat(); + try { + cv::convertScaleAbs(*selfptr, *dstptr, alpha_value, beta_value); + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return mat2obj(dstptr, CLASS_OF(self)); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Mat", rb_cData); + rb_define_alloc_func(rb_klass, rb_allocate); + + rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); + rb_define_singleton_method(rb_klass, "zeros", RUBY_METHOD_FUNC(rb_zeros), 3); + rb_define_singleton_method(rb_klass, "ones", RUBY_METHOD_FUNC(rb_ones), 3); + rb_define_singleton_method(rb_klass, "eye", RUBY_METHOD_FUNC(rb_eye), 3); + + rb_define_method(rb_klass, "+", RUBY_METHOD_FUNC(rb_add), 1); + rb_define_method(rb_klass, "-", RUBY_METHOD_FUNC(rb_sub), 1); + rb_define_method(rb_klass, "*", RUBY_METHOD_FUNC(rb_mul), 1); + rb_define_method(rb_klass, "/", RUBY_METHOD_FUNC(rb_div), 1); + + rb_define_method(rb_klass, "clone", RUBY_METHOD_FUNC(rb_clone), 0); + + rb_define_method(rb_klass, "rows", RUBY_METHOD_FUNC(rb_rows), 0); + rb_define_alias(rb_klass, "height", "rows"); + rb_define_method(rb_klass, "cols", RUBY_METHOD_FUNC(rb_cols), 0); + rb_define_alias(rb_klass, "width", "cols"); + + rb_define_method(rb_klass, "dims", RUBY_METHOD_FUNC(rb_dims), 0); + rb_define_method(rb_klass, "depth", RUBY_METHOD_FUNC(rb_depth), 0); + rb_define_method(rb_klass, "channels", RUBY_METHOD_FUNC(rb_channels), 0); + + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), -2); + rb_define_alias(rb_klass, "at", "[]"); + rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 3); + rb_define_method(rb_klass, "set_to", RUBY_METHOD_FUNC(rb_set_to), -1); + + rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0); + + rb_define_method(rb_klass, "sobel", RUBY_METHOD_FUNC(rb_sobel), -1); // in ext/opencv/mat_imgproc.cpp + rb_define_method(rb_klass, "canny", RUBY_METHOD_FUNC(rb_canny), -1); // in ext/opencv/mat_imgproc.cpp + rb_define_method(rb_klass, "laplacian", RUBY_METHOD_FUNC(rb_laplacian), -1); // in ext/opencv/mat_imgproc.cpp + + rb_define_method(rb_klass, "line", RUBY_METHOD_FUNC(rb_line), -1); // in ext/opencv/mat_drawing.cpp + rb_define_method(rb_klass, "line!", RUBY_METHOD_FUNC(rb_line_bang), -1); // in ext/opencv/mat_drawing.cpp + + rb_define_method(rb_klass, "rectangle", RUBY_METHOD_FUNC(rb_rectangle), -1); // in ext/opencv/mat_drawing.cpp + rb_define_method(rb_klass, "rectangle!", RUBY_METHOD_FUNC(rb_rectangle_bang), -1); // in ext/opencv/mat_drawing.cpp + + rb_define_method(rb_klass, "resize", RUBY_METHOD_FUNC(rb_resize), -1); // in ext/opencv/mat_imgproc.cpp + rb_define_method(rb_klass, "cvt_color", RUBY_METHOD_FUNC(rb_cvt_color), -1); // in ext/opencv/mat_imgproc.cpp + + rb_define_method(rb_klass, "save", RUBY_METHOD_FUNC(rb_save), -1); + + rb_define_method(rb_klass, "imencode", RUBY_METHOD_FUNC(rb_imencode), -1); + rb_define_singleton_method(rb_klass, "imread_as", RUBY_METHOD_FUNC(rb_imread_as), 3); + rb_define_singleton_method(rb_klass, "imdecode_as", RUBY_METHOD_FUNC(rb_imdecode_as), 3); + + rb_define_method(rb_klass, "convert_scale_abs", RUBY_METHOD_FUNC(rb_convert_scale_abs), -1); + } + } +} diff --git a/ext/opencv/mat_drawing.cppe b/ext/opencv/mat_drawing.cppe new file mode 100644 index 0000000..26a52bc --- /dev/null +++ b/ext/opencv/mat_drawing.cppe @@ -0,0 +1,158 @@ +#include "ruby.h" + +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" + +#include "mat.hpp" +#include "mat_drawing.hpp" +#include "scalar.hpp" +#include "point.hpp" +#include "error.hpp" + +/* + * Document-class: OpenCV::Mat + */ +namespace rubyopencv { + namespace Mat { + typedef struct _drawing_option { + int thickness; + int line_type; + int shift; + } drawing_option_t; + const drawing_option_t DEFAULT_DRAWING_OPTION = { 1, 8, 0 }; + + drawing_option_t drawing_option(VALUE option) { + drawing_option_t opt = DEFAULT_DRAWING_OPTION; + + if (!NIL_P(option)) { + Check_Type(option, T_HASH); + + VALUE tmp = Qnil; + tmp = rb_hash_lookup(option, ID2SYM(rb_intern("thickness"))); + if (!NIL_P(tmp)) { + opt.thickness = NUM2INT(tmp); + } + tmp = rb_hash_lookup(option, ID2SYM(rb_intern("line_type"))); + if (!NIL_P(tmp)) { + opt.line_type = NUM2INT(tmp); + } + tmp = rb_hash_lookup(option, ID2SYM(rb_intern("shift"))); + if (!NIL_P(tmp)) { + opt.shift = NUM2INT(tmp); + } + } + + return opt; + } + + /* + * Draws a line segment connecting two points. + * + * @overload line!(p1, p2, color, options = nil) + * @param p1 [Point] First point of the line segment. + * @param p2 [Point] Second point of the line segment. + * @param color [Scalar] Line color. + * @param options [Hash] Drawing options + * @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 [Mat] self + * @opencv_func (see #line) + */ + VALUE rb_line_bang(int argc, VALUE *argv, VALUE self) { + VALUE p1, p2, color, option; + rb_scan_args(argc, argv, "31", &p1, &p2, &color, &option); + + drawing_option_t opt = drawing_option(option); + try { + cv::Point pt1 = Point::conpatible_obj2point(p1); + cv::Point pt2 = Point::conpatible_obj2point(p2); + cv::line(*(obj2mat(self)), pt1, pt2, *(Scalar::obj2scalar(color)), opt.thickness, opt.line_type, opt.shift); + } + catch (cv::Exception& e) { + Error::raise(e); + } + return self; + } + + /* + * Returns a line segment connecting two points. + * + * @overload line!(p1, p2, color, options = nil) + * @param p1 [Point] First point of the line segment. + * @param p2 [Point] Second point of the line segment. + * @param color [Scalar] Line color. + * @param options [Hash] Drawing options + * @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 [Mat] Image + * @opencv_func cv::line + */ + VALUE rb_line(int argc, VALUE *argv, VALUE self) { + VALUE dst = rb_clone(self); + return rb_line_bang(argc, argv, dst); + } + + /* + * Returns a simple, thick, or filled up-right rectangle. + * + * @overload rectangle(p1, p2, color, options = nil) + * @param p1 [Point] Vertex of the rectangle. + * @param p2 [Point] Vertex of the rectangle opposite to p1. + * @param color [Scalar] Line color. + * @param options [Hash] Drawing options + * @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 [Mat] self + * @opencv_func cv::rectangle + */ + VALUE rb_rectangle(int argc, VALUE *argv, VALUE self) { + VALUE dst = rb_clone(self); + return rb_rectangle_bang(argc, argv, dst); + } + + /* + * Draws a simple, thick, or filled up-right rectangle. + * + * @overload rectangle!(p1, p2, color, options = nil) + * @param p1 [Point] Vertex of the rectangle. + * @param p2 [Point] Vertex of the rectangle opposite to p1. + * @param color [Scalar] Line color. + * @param options [Hash] Drawing options + * @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 [Mat] self + * @opencv_func cv::rectangle + */ + VALUE rb_rectangle_bang(int argc, VALUE *argv, VALUE self) { + VALUE p1, p2, color, option; + rb_scan_args(argc, argv, "31", &p1, &p2, &color, &option); + + drawing_option_t opt = drawing_option(option); + try { + cv::Point pt1 = Point::conpatible_obj2point(p1); + cv::Point pt2 = Point::conpatible_obj2point(p2); + cv::rectangle(*(obj2mat(self)), pt1, pt2, *(Scalar::obj2scalar(color)), opt.thickness, opt.line_type, opt.shift); + } + catch (cv::Exception& e) { + Error::raise(e); + } + return self; + } + } +} diff --git a/ext/opencv/mat_imgproc.cppe b/ext/opencv/mat_imgproc.cppe new file mode 100644 index 0000000..995dcd0 --- /dev/null +++ b/ext/opencv/mat_imgproc.cppe @@ -0,0 +1,181 @@ +// -*- mode: c++; coding: utf-8 -*- +#include "opencv2/imgproc.hpp" + +#include "mat.hpp" +#include "size.hpp" +#include "error.hpp" + +/* + * Document-class: OpenCV::Mat + */ +namespace rubyopencv { + namespace Mat { + /* + * Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. + * + * @overload sobel(ddepth, dx, dy, ksize = 3, scale = 1, delta = 0, border_type = BORDER_DEFAULT) + * @param ddepth [Integer] Output image depth + * @param dx [Integer] Order of the derivative x. + * @param dy [Integer] Order of the derivative y. + * @param ksize [Integer] Size of the extended Sobel kernel; it must be 1, 3, 5, or 7. + * @param scale [Number] Optional scale factor for the computed derivative values; by default, no scaling is applied. + * @param delta [Number] Optional delta value that is added to the results prior to storing them in the output image. + * @param border_type [Integer] Pixel extrapolation method. + * @return [Mat] Output image. + * @opencv_func cv::Sovel + */ + VALUE rb_sobel(int argc, VALUE *argv, VALUE self) { + VALUE ddepth, dx, dy, ksize, scale, delta, border_type; + rb_scan_args(argc, argv, "34", &ddepth ,&dx, &dy, &ksize, &scale, &delta, &border_type); + int ksize_value = NIL_P(ksize) ? 3 : NUM2INT(ksize); + double scale_value = NIL_P(scale) ? 1.0 : NUM2DBL(scale); + double delta_value = NIL_P(delta) ? 0.0 : NUM2DBL(delta); + int border_type_value = NIL_P(border_type) ? cv::BORDER_DEFAULT : NUM2INT(border_type); + + cv::Mat* selfptr = obj2mat(self); + cv::Mat* destptr = empty_mat(); + try { + cv::Sobel(*selfptr, *destptr, NUM2INT(ddepth), NUM2INT(dx), NUM2INT(dy), + ksize_value, scale_value, delta_value, border_type_value); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr, CLASS_OF(self)); + } + + /** + * Finds edges in an image using the [Canny86] algorithm. + * + * @overload canny(threshold1, threshold2, aperture_size = 3, l2gradient = false) + * @param threshold1 [Number] First threshold for the hysteresis procedure. + * @param threshold2 [Number] Second threshold for the hysteresis procedure. + * @param aperture_size [Integer] Aperture size for the Sobel operator. + * @param l2gradient [Boolean] a flag, indicating whether a more accurate L_2 =\sqrt{ (dI/dx)^2 + (dI/dy)^2 } norm + * should be used to calculate the image gradient magnitude (l2gradient=true), + * or whether the default L_1 norm =|dI/dx|+|dI/dy| is enough (l2gradient=false). + * @opencv_func cv::Canny + */ + VALUE rb_canny(int argc, VALUE *argv, VALUE self) { + VALUE threshold1, threshold2, aperture_size, l2gradient; + rb_scan_args(argc, argv, "22", &threshold1, &threshold2, &aperture_size, &l2gradient); + + int aperture_size_value = NIL_P(aperture_size) ? 3 : NUM2INT(aperture_size); + bool l2gradient_value = RTEST(l2gradient) ? true : false; + + cv::Mat* selfptr = obj2mat(self); + cv::Mat* destptr = empty_mat(); + try { + cv::Canny(*selfptr, *destptr, NUM2DBL(threshold1), NUM2DBL(threshold2), + aperture_size_value, l2gradient_value); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr, CLASS_OF(self)); + } + + /* + * Calculates the Laplacian of an image. + * + * @overload laplacian(ddepth, ksize = 1, scale = 1, delta = 0, border_type = BORDER_DEFAULT) + * @param ddepth [Integer] Desired depth of the destination image. + * @param ksize [Integer] Aperture size used to compute the second-derivative filters. + * The size must be positive and odd. + * @param scale [Number] Optional scale factor for the computed Laplacian values. By default, no scaling is applied. + * @param delta [Number] Optional delta value that is added to the results prior to storing them in the output image. + * @param border_type [Integer] Pixel extrapolation method. + * @return [Mat] Output image. + * @opencv_func cv::Laplacian + */ + VALUE rb_laplacian(int argc, VALUE *argv, VALUE self) { + VALUE ddepth, ksize, scale, delta, border_type; + rb_scan_args(argc, argv, "14", &ddepth, &ksize, &scale, &delta, &border_type); + int ksize_value = NIL_P(ksize) ? 3 : NUM2INT(ksize); + double scale_value = NIL_P(scale) ? 1.0 : NUM2DBL(scale); + double delta_value = NIL_P(delta) ? 0.0 : NUM2DBL(delta); + int border_type_value = NIL_P(border_type) ? cv::BORDER_DEFAULT : NUM2INT(border_type); + + cv::Mat* selfptr = obj2mat(self); + cv::Mat* destptr = empty_mat(); + try { + cv::Laplacian(*selfptr, *destptr, NUM2INT(ddepth), ksize_value, scale_value, + delta_value, border_type_value); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr, CLASS_OF(self)); + } + + /** + * Converts an image from one color space to another. + * + * @overload cvt_color(code, dcn = 0) + * @param code [Integer] Color space conversion code + * @param dcn [Integer] Number of channels in the destination image; if the parameter is 0, + * the number of the channels is derived automatically from src and code + * @return [Mat] Output image + * @opencv_func cv::cvtColor + */ + VALUE rb_cvt_color(int argc, VALUE *argv, VALUE self) { + VALUE code, dcn; + rb_scan_args(argc, argv, "11", &code, &dcn); + int dcn_value = NIL_P(dcn) ? 0 : NUM2INT(dcn); + + cv::Mat* destptr = empty_mat(); + cv::Mat* selfptr = obj2mat(self); + try { + cv::cvtColor(*selfptr, *destptr, NUM2INT(code), dcn_value); + } + catch (cv::Exception& e) { + delete destptr; + Error::raise(e); + } + + return mat2obj(destptr, CLASS_OF(self)); + } + + /* + * Resizes an image. + * + * @overload resize(size, interpolation = INTER_LINEAR) + * @param size [Size] Output image size. + * @param interpolation [Integer] Interpolation method: + * * INTER_NEAREST - A nearest-neighbor interpolation + * * INTER_LINEAR - A bilinear interpolation (used by default) + * * 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 INTER_NEAREST method. + * * INTER_CUBIC - A bicubic interpolation over 4x4 pixel neighborhood + * * INTER_LANCZOS4 - A Lanczos interpolation over 8x8 pixel neighborhood + * @return [Mat] Output image. + * @opencv_func cv::Resize + */ + VALUE rb_resize(int argc, VALUE *argv, VALUE self) { + VALUE size, inv_scale_x, inv_scale_y, interpolation; + rb_scan_args(argc, argv, "13", &size, &inv_scale_x, &inv_scale_y, &interpolation); + cv::Size* sizeptr = Size::obj2size(size); + cv::Mat* selfptr = obj2mat(self); + cv::Mat* destptr = empty_mat(); + double sx = NIL_P(inv_scale_x) ? 0 : NUM2DBL(inv_scale_x); + double sy = NIL_P(inv_scale_y) ? 0 : NUM2DBL(inv_scale_y); + int method = NIL_P(interpolation) ? CV_INTER_LINEAR : NUM2INT(interpolation); + + try { + cv::resize(*selfptr, *destptr, *sizeptr, sx, sy, method); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return mat2obj(destptr, CLASS_OF(self)); + } + } +} diff --git a/ext/opencv/opencv.cpp b/ext/opencv/opencv.cpp index fd70b0c..72a1f05 100644 --- a/ext/opencv/opencv.cpp +++ b/ext/opencv/opencv.cpp @@ -80,7 +80,7 @@ namespace rubyopencv { void Init_opencv() { cv::redirectError(error_callback, NULL, NULL); - rb_module = rb_define_module("OpenCV"); + rb_module = rb_define_module("Cv"); define_const(rb_module); diff --git a/ext/opencv/opencv.cppe b/ext/opencv/opencv.cppe new file mode 100644 index 0000000..72a1f05 --- /dev/null +++ b/ext/opencv/opencv.cppe @@ -0,0 +1,109 @@ +// -*- mode: c++; coding: utf-8 -*- +#include "ruby.h" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" + +#include "opencv.hpp" +#include "opencv_const.hpp" +#include "mat.hpp" +#include "point.hpp" +#include "rect.hpp" +#include "size.hpp" +#include "scalar.hpp" + +#include "cascadeclassifier.hpp" +#include "videocapture.hpp" + +#include "error.hpp" +#include "window.hpp" +#include "trackbar.hpp" + +namespace rubyopencv { + VALUE rb_module = Qnil; + + VALUE rb_module_opencv() { + return rb_module; + } + + int error_callback(int status, const char *function_name, const char *error_message, + const char *file_name, int line, void *user_data) { + return 0; + } + + /* + * Returns full configuration time cmake output. + * Returned value is raw cmake output including version control system revision, + * compiler version, compiler flags, enabled modules and third party libraries, etc. + * Output format depends on target architecture. + * + * @overload rb_build_information() + * @return [String] Full configuration time cmake output. + * @opencv_func cv::getBuildInformation + */ + VALUE rb_build_information(VALUE klass) { + const char* ptr = cv::getBuildInformation().c_str(); + return rb_str_new(ptr, strlen(ptr)); + } + + /* + * Saves an image to a specified file. + * + * @overload imwrite(filename, img, params = nil) + * @param filename [String] Name of the file. + * @param img [Mat] Image to be saved. + * @param params [Array] + * Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ...) + * @return [Bool] Result + * @opencv_func cv::imwrite + */ + VALUE rb_imwrite(int argc, VALUE* argv, VALUE self) { + VALUE filename, img, params; + rb_scan_args(argc, argv, "21", &filename, &img, ¶ms); + return Mat::rb_imwrite_internal(filename, img, params); + } + + /* + * Makes a type from depth and channels + * + * @overload CV_MAKETYPE(depth, cn) + * @param depth [String] Depth + * @param cn [Mat] Number of channels + * @return [Integer] Type + * @opencv_func CV_MAKETYPE + */ + VALUE rb_maketype(VALUE self, VALUE depth, VALUE channels) { + int type = CV_MAKETYPE(NUM2INT(depth), NUM2INT(channels)); + return INT2NUM(type); + } + + extern "C" + void Init_opencv() { + cv::redirectError(error_callback, NULL, NULL); + + rb_module = rb_define_module("Cv"); + + define_const(rb_module); + + Mat::init(); + Point::init(); + Rect::init(); + Size::init(); + Scalar::init(); + CascadeClassifier::init(); + VideoCapture::init(); + Window::init(); + Trackbar::init(); + Error::init(); + + rb_define_module_function(rb_module, "build_information", RUBY_METHOD_FUNC(rb_build_information), 0); + + rb_define_singleton_method(rb_module, "imread", RUBY_METHOD_FUNC(Mat::rb_imread), 2); // in ext/opencv/mat.cpp + rb_define_singleton_method(rb_module, "imwrite", RUBY_METHOD_FUNC(rb_imwrite), -1); + rb_define_singleton_method(rb_module, "imdecode", RUBY_METHOD_FUNC(Mat::rb_imdecode), 2); // in ext/opencv/mat.cpp + rb_define_singleton_method(rb_module, "wait_key", RUBY_METHOD_FUNC(Window::rb_wait_key), -1); // in ext/opencv/window.cpp + + rb_define_singleton_method(rb_module, "add_weighted", RUBY_METHOD_FUNC(Mat::rb_add_weighted), -1); // in ext/opencv/mat.cpp + + rb_define_singleton_method(rb_module, "CV_MAKETYPE", RUBY_METHOD_FUNC(rb_maketype), 2); + } +} diff --git a/ext/opencv/opencv_const.cppe b/ext/opencv/opencv_const.cppe new file mode 100644 index 0000000..b28f6ce --- /dev/null +++ b/ext/opencv/opencv_const.cppe @@ -0,0 +1,381 @@ +// -*- mode: c++; coding: utf-8 -*- +#include "ruby.h" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/highgui.hpp" + +#include "opencv_const.hpp" + +namespace rubyopencv { + void define_const(VALUE rb_module) { + rb_define_const(rb_module, "CV_VERSION", rb_str_new2(CV_VERSION)); + rb_define_const(rb_module, "CV_MAJOR_VERSION", INT2FIX(CV_MAJOR_VERSION)); + rb_define_const(rb_module, "CV_MINOR_VERSION", INT2FIX(CV_MINOR_VERSION)); + rb_define_const(rb_module, "CV_SUBMINOR_VERSION", INT2FIX(CV_SUBMINOR_VERSION)); + + rb_define_const(rb_module, "CV_8U", INT2FIX(CV_8U)); + rb_define_const(rb_module, "CV_8S", INT2FIX(CV_8S)); + rb_define_const(rb_module, "CV_16U", INT2FIX(CV_16U)); + rb_define_const(rb_module, "CV_16S", INT2FIX(CV_16S)); + rb_define_const(rb_module, "CV_32S", INT2FIX(CV_32S)); + rb_define_const(rb_module, "CV_32F", INT2FIX(CV_32F)); + rb_define_const(rb_module, "CV_64F", INT2FIX(CV_64F)); + + rb_define_const(rb_module, "CV_8UC1", INT2FIX(CV_8UC1)); + rb_define_const(rb_module, "CV_8UC2", INT2FIX(CV_8UC2)); + rb_define_const(rb_module, "CV_8UC3", INT2FIX(CV_8UC3)); + rb_define_const(rb_module, "CV_8UC4", INT2FIX(CV_8UC4)); + rb_define_const(rb_module, "CV_8SC1", INT2FIX(CV_8SC1)); + rb_define_const(rb_module, "CV_8SC2", INT2FIX(CV_8SC2)); + rb_define_const(rb_module, "CV_8SC3", INT2FIX(CV_8SC3)); + rb_define_const(rb_module, "CV_8SC4", INT2FIX(CV_8SC4)); + rb_define_const(rb_module, "CV_16UC1", INT2FIX(CV_16UC1)); + rb_define_const(rb_module, "CV_16UC2", INT2FIX(CV_16UC2)); + rb_define_const(rb_module, "CV_16UC3", INT2FIX(CV_16UC3)); + rb_define_const(rb_module, "CV_16UC4", INT2FIX(CV_16UC4)); + rb_define_const(rb_module, "CV_16SC1", INT2FIX(CV_16SC1)); + rb_define_const(rb_module, "CV_16SC2", INT2FIX(CV_16SC2)); + rb_define_const(rb_module, "CV_16SC3", INT2FIX(CV_16SC3)); + rb_define_const(rb_module, "CV_16SC4", INT2FIX(CV_16SC4)); + rb_define_const(rb_module, "CV_32SC1", INT2FIX(CV_32SC1)); + rb_define_const(rb_module, "CV_32SC2", INT2FIX(CV_32SC2)); + rb_define_const(rb_module, "CV_32SC3", INT2FIX(CV_32SC3)); + rb_define_const(rb_module, "CV_32SC4", INT2FIX(CV_32SC4)); + rb_define_const(rb_module, "CV_32FC1", INT2FIX(CV_32FC1)); + rb_define_const(rb_module, "CV_32FC2", INT2FIX(CV_32FC2)); + rb_define_const(rb_module, "CV_32FC3", INT2FIX(CV_32FC3)); + rb_define_const(rb_module, "CV_32FC4", INT2FIX(CV_32FC4)); + rb_define_const(rb_module, "CV_64FC1", INT2FIX(CV_64FC1)); + rb_define_const(rb_module, "CV_64FC2", INT2FIX(CV_64FC2)); + rb_define_const(rb_module, "CV_64FC3", INT2FIX(CV_64FC3)); + rb_define_const(rb_module, "CV_64FC4", INT2FIX(CV_64FC4)); + + rb_define_const(rb_module, "COLOR_BGR2BGRA", INT2FIX(cv::COLOR_BGR2BGRA)); + rb_define_const(rb_module, "COLOR_RGB2RGBA", INT2FIX(cv::COLOR_RGB2RGBA)); + rb_define_const(rb_module, "COLOR_BGRA2BGR", INT2FIX(cv::COLOR_BGRA2BGR)); + rb_define_const(rb_module, "COLOR_RGBA2RGB", INT2FIX(cv::COLOR_RGBA2RGB)); + rb_define_const(rb_module, "COLOR_BGR2RGBA", INT2FIX(cv::COLOR_BGR2RGBA)); + rb_define_const(rb_module, "COLOR_RGB2BGRA", INT2FIX(cv::COLOR_RGB2BGRA)); + rb_define_const(rb_module, "COLOR_RGBA2BGR", INT2FIX(cv::COLOR_RGBA2BGR)); + rb_define_const(rb_module, "COLOR_BGRA2RGB", INT2FIX(cv::COLOR_BGRA2RGB)); + rb_define_const(rb_module, "COLOR_BGR2RGB", INT2FIX(cv::COLOR_BGR2RGB)); + rb_define_const(rb_module, "COLOR_RGB2BGR", INT2FIX(cv::COLOR_RGB2BGR)); + rb_define_const(rb_module, "COLOR_BGRA2RGBA", INT2FIX(cv::COLOR_BGRA2RGBA)); + rb_define_const(rb_module, "COLOR_RGBA2BGRA", INT2FIX(cv::COLOR_RGBA2BGRA)); + rb_define_const(rb_module, "COLOR_BGR2GRAY", INT2FIX(cv::COLOR_BGR2GRAY)); + rb_define_const(rb_module, "COLOR_RGB2GRAY", INT2FIX(cv::COLOR_RGB2GRAY)); + rb_define_const(rb_module, "COLOR_GRAY2BGR", INT2FIX(cv::COLOR_GRAY2BGR)); + rb_define_const(rb_module, "COLOR_GRAY2RGB", INT2FIX(cv::COLOR_GRAY2RGB)); + rb_define_const(rb_module, "COLOR_GRAY2BGRA", INT2FIX(cv::COLOR_GRAY2BGRA)); + rb_define_const(rb_module, "COLOR_GRAY2RGBA", INT2FIX(cv::COLOR_GRAY2RGBA)); + rb_define_const(rb_module, "COLOR_BGRA2GRAY", INT2FIX(cv::COLOR_BGRA2GRAY)); + rb_define_const(rb_module, "COLOR_RGBA2GRAY", INT2FIX(cv::COLOR_RGBA2GRAY)); + rb_define_const(rb_module, "COLOR_BGR2BGR565", INT2FIX(cv::COLOR_BGR2BGR565)); + rb_define_const(rb_module, "COLOR_RGB2BGR565", INT2FIX(cv::COLOR_RGB2BGR565)); + rb_define_const(rb_module, "COLOR_BGR5652BGR", INT2FIX(cv::COLOR_BGR5652BGR)); + rb_define_const(rb_module, "COLOR_BGR5652RGB", INT2FIX(cv::COLOR_BGR5652RGB)); + rb_define_const(rb_module, "COLOR_BGRA2BGR565", INT2FIX(cv::COLOR_BGRA2BGR565)); + rb_define_const(rb_module, "COLOR_RGBA2BGR565", INT2FIX(cv::COLOR_RGBA2BGR565)); + rb_define_const(rb_module, "COLOR_BGR5652BGRA", INT2FIX(cv::COLOR_BGR5652BGRA)); + rb_define_const(rb_module, "COLOR_BGR5652RGBA", INT2FIX(cv::COLOR_BGR5652RGBA)); + rb_define_const(rb_module, "COLOR_GRAY2BGR565", INT2FIX(cv::COLOR_GRAY2BGR565)); + rb_define_const(rb_module, "COLOR_BGR5652GRAY", INT2FIX(cv::COLOR_BGR5652GRAY)); + rb_define_const(rb_module, "COLOR_BGR2BGR555", INT2FIX(cv::COLOR_BGR2BGR555)); + rb_define_const(rb_module, "COLOR_RGB2BGR555", INT2FIX(cv::COLOR_RGB2BGR555)); + rb_define_const(rb_module, "COLOR_BGR5552BGR", INT2FIX(cv::COLOR_BGR5552BGR)); + rb_define_const(rb_module, "COLOR_BGR5552RGB", INT2FIX(cv::COLOR_BGR5552RGB)); + rb_define_const(rb_module, "COLOR_BGRA2BGR555", INT2FIX(cv::COLOR_BGRA2BGR555)); + rb_define_const(rb_module, "COLOR_RGBA2BGR555", INT2FIX(cv::COLOR_RGBA2BGR555)); + rb_define_const(rb_module, "COLOR_BGR5552BGRA", INT2FIX(cv::COLOR_BGR5552BGRA)); + rb_define_const(rb_module, "COLOR_BGR5552RGBA", INT2FIX(cv::COLOR_BGR5552RGBA)); + rb_define_const(rb_module, "COLOR_GRAY2BGR555", INT2FIX(cv::COLOR_GRAY2BGR555)); + rb_define_const(rb_module, "COLOR_BGR5552GRAY", INT2FIX(cv::COLOR_BGR5552GRAY)); + rb_define_const(rb_module, "COLOR_BGR2XYZ", INT2FIX(cv::COLOR_BGR2XYZ)); + rb_define_const(rb_module, "COLOR_RGB2XYZ", INT2FIX(cv::COLOR_RGB2XYZ)); + rb_define_const(rb_module, "COLOR_XYZ2BGR", INT2FIX(cv::COLOR_XYZ2BGR)); + rb_define_const(rb_module, "COLOR_XYZ2RGB", INT2FIX(cv::COLOR_XYZ2RGB)); + rb_define_const(rb_module, "COLOR_BGR2YCrCb", INT2FIX(cv::COLOR_BGR2YCrCb)); + rb_define_const(rb_module, "COLOR_RGB2YCrCb", INT2FIX(cv::COLOR_RGB2YCrCb)); + rb_define_const(rb_module, "COLOR_YCrCb2BGR", INT2FIX(cv::COLOR_YCrCb2BGR)); + rb_define_const(rb_module, "COLOR_YCrCb2RGB", INT2FIX(cv::COLOR_YCrCb2RGB)); + rb_define_const(rb_module, "COLOR_BGR2HSV", INT2FIX(cv::COLOR_BGR2HSV)); + rb_define_const(rb_module, "COLOR_RGB2HSV", INT2FIX(cv::COLOR_RGB2HSV)); + rb_define_const(rb_module, "COLOR_BGR2Lab", INT2FIX(cv::COLOR_BGR2Lab)); + rb_define_const(rb_module, "COLOR_RGB2Lab", INT2FIX(cv::COLOR_RGB2Lab)); + rb_define_const(rb_module, "COLOR_BGR2Luv", INT2FIX(cv::COLOR_BGR2Luv)); + rb_define_const(rb_module, "COLOR_RGB2Luv", INT2FIX(cv::COLOR_RGB2Luv)); + rb_define_const(rb_module, "COLOR_BGR2HLS", INT2FIX(cv::COLOR_BGR2HLS)); + rb_define_const(rb_module, "COLOR_RGB2HLS", INT2FIX(cv::COLOR_RGB2HLS)); + rb_define_const(rb_module, "COLOR_HSV2BGR", INT2FIX(cv::COLOR_HSV2BGR)); + rb_define_const(rb_module, "COLOR_HSV2RGB", INT2FIX(cv::COLOR_HSV2RGB)); + rb_define_const(rb_module, "COLOR_Lab2BGR", INT2FIX(cv::COLOR_Lab2BGR)); + rb_define_const(rb_module, "COLOR_Lab2RGB", INT2FIX(cv::COLOR_Lab2RGB)); + rb_define_const(rb_module, "COLOR_Luv2BGR", INT2FIX(cv::COLOR_Luv2BGR)); + rb_define_const(rb_module, "COLOR_Luv2RGB", INT2FIX(cv::COLOR_Luv2RGB)); + rb_define_const(rb_module, "COLOR_HLS2BGR", INT2FIX(cv::COLOR_HLS2BGR)); + rb_define_const(rb_module, "COLOR_HLS2RGB", INT2FIX(cv::COLOR_HLS2RGB)); + rb_define_const(rb_module, "COLOR_BGR2HSV_FULL", INT2FIX(cv::COLOR_BGR2HSV_FULL)); + rb_define_const(rb_module, "COLOR_BGR2HLS_FULL", INT2FIX(cv::COLOR_BGR2HLS_FULL)); + rb_define_const(rb_module, "COLOR_RGB2HLS_FULL", INT2FIX(cv::COLOR_RGB2HLS_FULL)); + rb_define_const(rb_module, "COLOR_HSV2BGR_FULL", INT2FIX(cv::COLOR_HSV2BGR_FULL)); + rb_define_const(rb_module, "COLOR_HSV2RGB_FULL", INT2FIX(cv::COLOR_HSV2RGB_FULL)); + rb_define_const(rb_module, "COLOR_HLS2BGR_FULL", INT2FIX(cv::COLOR_HLS2BGR_FULL)); + rb_define_const(rb_module, "COLOR_HLS2RGB_FULL", INT2FIX(cv::COLOR_HLS2RGB_FULL)); + rb_define_const(rb_module, "COLOR_LBGR2Lab", INT2FIX(cv::COLOR_LBGR2Lab)); + rb_define_const(rb_module, "COLOR_LRGB2Lab", INT2FIX(cv::COLOR_LRGB2Lab)); + rb_define_const(rb_module, "COLOR_LBGR2Luv", INT2FIX(cv::COLOR_LBGR2Luv)); + rb_define_const(rb_module, "COLOR_LRGB2Luv", INT2FIX(cv::COLOR_LRGB2Luv)); + rb_define_const(rb_module, "COLOR_Lab2LBGR", INT2FIX(cv::COLOR_Lab2LBGR)); + rb_define_const(rb_module, "COLOR_Lab2LRGB", INT2FIX(cv::COLOR_Lab2LRGB)); + rb_define_const(rb_module, "COLOR_Luv2LBGR", INT2FIX(cv::COLOR_Luv2LBGR)); + rb_define_const(rb_module, "COLOR_Luv2LRGB", INT2FIX(cv::COLOR_Luv2LRGB)); + rb_define_const(rb_module, "COLOR_BGR2YUV", INT2FIX(cv::COLOR_BGR2YUV)); + rb_define_const(rb_module, "COLOR_RGB2YUV", INT2FIX(cv::COLOR_RGB2YUV)); + rb_define_const(rb_module, "COLOR_YUV2BGR", INT2FIX(cv::COLOR_YUV2BGR)); + rb_define_const(rb_module, "COLOR_YUV2RGB", INT2FIX(cv::COLOR_YUV2RGB)); + rb_define_const(rb_module, "COLOR_YUV2RGB_NV12", INT2FIX(cv::COLOR_YUV2RGB_NV12)); + rb_define_const(rb_module, "COLOR_YUV2BGR_NV12", INT2FIX(cv::COLOR_YUV2BGR_NV12)); + rb_define_const(rb_module, "COLOR_YUV2RGB_NV21", INT2FIX(cv::COLOR_YUV2RGB_NV21)); + rb_define_const(rb_module, "COLOR_YUV2BGR_NV21", INT2FIX(cv::COLOR_YUV2BGR_NV21)); + rb_define_const(rb_module, "COLOR_YUV420sp2RGB", INT2FIX(cv::COLOR_YUV420sp2RGB)); + rb_define_const(rb_module, "COLOR_YUV420sp2BGR", INT2FIX(cv::COLOR_YUV420sp2BGR)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_NV12", INT2FIX(cv::COLOR_YUV2RGBA_NV12)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_NV12", INT2FIX(cv::COLOR_YUV2BGRA_NV12)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_NV21", INT2FIX(cv::COLOR_YUV2RGBA_NV21)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_NV21", INT2FIX(cv::COLOR_YUV2BGRA_NV21)); + rb_define_const(rb_module, "COLOR_YUV420sp2RGBA", INT2FIX(cv::COLOR_YUV420sp2RGBA)); + rb_define_const(rb_module, "COLOR_YUV420sp2BGRA", INT2FIX(cv::COLOR_YUV420sp2BGRA)); + rb_define_const(rb_module, "COLOR_YUV2RGB_YV12", INT2FIX(cv::COLOR_YUV2RGB_YV12)); + rb_define_const(rb_module, "COLOR_YUV2BGR_YV12", INT2FIX(cv::COLOR_YUV2BGR_YV12)); + rb_define_const(rb_module, "COLOR_YUV2RGB_IYUV", INT2FIX(cv::COLOR_YUV2RGB_IYUV)); + rb_define_const(rb_module, "COLOR_YUV2BGR_IYUV", INT2FIX(cv::COLOR_YUV2BGR_IYUV)); + rb_define_const(rb_module, "COLOR_YUV2RGB_I420", INT2FIX(cv::COLOR_YUV2RGB_I420)); + rb_define_const(rb_module, "COLOR_YUV2BGR_I420", INT2FIX(cv::COLOR_YUV2BGR_I420)); + rb_define_const(rb_module, "COLOR_YUV420p2RGB", INT2FIX(cv::COLOR_YUV420p2RGB)); + rb_define_const(rb_module, "COLOR_YUV420p2BGR", INT2FIX(cv::COLOR_YUV420p2BGR)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_YV12", INT2FIX(cv::COLOR_YUV2RGBA_YV12)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_YV12", INT2FIX(cv::COLOR_YUV2BGRA_YV12)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_IYUV", INT2FIX(cv::COLOR_YUV2RGBA_IYUV)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_IYUV", INT2FIX(cv::COLOR_YUV2BGRA_IYUV)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_I420", INT2FIX(cv::COLOR_YUV2RGBA_I420)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_I420", INT2FIX(cv::COLOR_YUV2BGRA_I420)); + rb_define_const(rb_module, "COLOR_YUV420p2RGBA", INT2FIX(cv::COLOR_YUV420p2RGBA)); + rb_define_const(rb_module, "COLOR_YUV420p2BGRA", INT2FIX(cv::COLOR_YUV420p2BGRA)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_420", INT2FIX(cv::COLOR_YUV2GRAY_420)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_NV21", INT2FIX(cv::COLOR_YUV2GRAY_NV21)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_NV12", INT2FIX(cv::COLOR_YUV2GRAY_NV12)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_YV12", INT2FIX(cv::COLOR_YUV2GRAY_YV12)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_IYUV", INT2FIX(cv::COLOR_YUV2GRAY_IYUV)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_I420", INT2FIX(cv::COLOR_YUV2GRAY_I420)); + rb_define_const(rb_module, "COLOR_YUV420sp2GRAY", INT2FIX(cv::COLOR_YUV420sp2GRAY)); + rb_define_const(rb_module, "COLOR_YUV420p2GRAY", INT2FIX(cv::COLOR_YUV420p2GRAY)); + rb_define_const(rb_module, "COLOR_YUV2RGB_UYVY", INT2FIX(cv::COLOR_YUV2RGB_UYVY)); + rb_define_const(rb_module, "COLOR_YUV2BGR_UYVY", INT2FIX(cv::COLOR_YUV2BGR_UYVY)); + rb_define_const(rb_module, "COLOR_YUV2RGB_Y422", INT2FIX(cv::COLOR_YUV2RGB_Y422)); + rb_define_const(rb_module, "COLOR_YUV2BGR_Y422", INT2FIX(cv::COLOR_YUV2BGR_Y422)); + rb_define_const(rb_module, "COLOR_YUV2RGB_UYNV", INT2FIX(cv::COLOR_YUV2RGB_UYNV)); + rb_define_const(rb_module, "COLOR_YUV2BGR_UYNV", INT2FIX(cv::COLOR_YUV2BGR_UYNV)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_UYVY", INT2FIX(cv::COLOR_YUV2RGBA_UYVY)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_UYVY", INT2FIX(cv::COLOR_YUV2BGRA_UYVY)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_Y422", INT2FIX(cv::COLOR_YUV2RGBA_Y422)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_Y422", INT2FIX(cv::COLOR_YUV2BGRA_Y422)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_UYNV", INT2FIX(cv::COLOR_YUV2RGBA_UYNV)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_UYNV", INT2FIX(cv::COLOR_YUV2BGRA_UYNV)); + rb_define_const(rb_module, "COLOR_YUV2RGB_YUY2", INT2FIX(cv::COLOR_YUV2RGB_YUY2)); + rb_define_const(rb_module, "COLOR_YUV2BGR_YUY2", INT2FIX(cv::COLOR_YUV2BGR_YUY2)); + rb_define_const(rb_module, "COLOR_YUV2RGB_YVYU", INT2FIX(cv::COLOR_YUV2RGB_YVYU)); + rb_define_const(rb_module, "COLOR_YUV2BGR_YVYU", INT2FIX(cv::COLOR_YUV2BGR_YVYU)); + rb_define_const(rb_module, "COLOR_YUV2RGB_YUYV", INT2FIX(cv::COLOR_YUV2RGB_YUYV)); + rb_define_const(rb_module, "COLOR_YUV2BGR_YUYV", INT2FIX(cv::COLOR_YUV2BGR_YUYV)); + rb_define_const(rb_module, "COLOR_YUV2RGB_YUNV", INT2FIX(cv::COLOR_YUV2RGB_YUNV)); + rb_define_const(rb_module, "COLOR_YUV2BGR_YUNV", INT2FIX(cv::COLOR_YUV2BGR_YUNV)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_YUY2", INT2FIX(cv::COLOR_YUV2RGBA_YUY2)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_YUY2", INT2FIX(cv::COLOR_YUV2BGRA_YUY2)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_YVYU", INT2FIX(cv::COLOR_YUV2RGBA_YVYU)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_YVYU", INT2FIX(cv::COLOR_YUV2BGRA_YVYU)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_YUYV", INT2FIX(cv::COLOR_YUV2RGBA_YUYV)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_YUYV", INT2FIX(cv::COLOR_YUV2BGRA_YUYV)); + rb_define_const(rb_module, "COLOR_YUV2RGBA_YUNV", INT2FIX(cv::COLOR_YUV2RGBA_YUNV)); + rb_define_const(rb_module, "COLOR_YUV2BGRA_YUNV", INT2FIX(cv::COLOR_YUV2BGRA_YUNV)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_UYVY", INT2FIX(cv::COLOR_YUV2GRAY_UYVY)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_YUY2", INT2FIX(cv::COLOR_YUV2GRAY_YUY2)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_Y422", INT2FIX(cv::COLOR_YUV2GRAY_Y422)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_UYNV", INT2FIX(cv::COLOR_YUV2GRAY_UYNV)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_YVYU", INT2FIX(cv::COLOR_YUV2GRAY_YVYU)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_YUYV", INT2FIX(cv::COLOR_YUV2GRAY_YUYV)); + rb_define_const(rb_module, "COLOR_YUV2GRAY_YUNV", INT2FIX(cv::COLOR_YUV2GRAY_YUNV)); + rb_define_const(rb_module, "COLOR_RGBA2mRGBA", INT2FIX(cv::COLOR_RGBA2mRGBA)); + rb_define_const(rb_module, "COLOR_mRGBA2RGBA", INT2FIX(cv::COLOR_mRGBA2RGBA)); + rb_define_const(rb_module, "COLOR_RGB2YUV_I420", INT2FIX(cv::COLOR_RGB2YUV_I420)); + rb_define_const(rb_module, "COLOR_BGR2YUV_I420", INT2FIX(cv::COLOR_BGR2YUV_I420)); + rb_define_const(rb_module, "COLOR_RGB2YUV_IYUV", INT2FIX(cv::COLOR_RGB2YUV_IYUV)); + rb_define_const(rb_module, "COLOR_BGR2YUV_IYUV", INT2FIX(cv::COLOR_BGR2YUV_IYUV)); + rb_define_const(rb_module, "COLOR_RGBA2YUV_I420", INT2FIX(cv::COLOR_RGBA2YUV_I420)); + rb_define_const(rb_module, "COLOR_BGRA2YUV_I420", INT2FIX(cv::COLOR_BGRA2YUV_I420)); + rb_define_const(rb_module, "COLOR_RGBA2YUV_IYUV", INT2FIX(cv::COLOR_RGBA2YUV_IYUV)); + rb_define_const(rb_module, "COLOR_BGRA2YUV_IYUV", INT2FIX(cv::COLOR_BGRA2YUV_IYUV)); + rb_define_const(rb_module, "COLOR_RGB2YUV_YV12", INT2FIX(cv::COLOR_RGB2YUV_YV12)); + rb_define_const(rb_module, "COLOR_BGR2YUV_YV12", INT2FIX(cv::COLOR_BGR2YUV_YV12)); + rb_define_const(rb_module, "COLOR_RGBA2YUV_YV12", INT2FIX(cv::COLOR_RGBA2YUV_YV12)); + rb_define_const(rb_module, "COLOR_BGRA2YUV_YV12", INT2FIX(cv::COLOR_BGRA2YUV_YV12)); + rb_define_const(rb_module, "COLOR_BayerBG2BGR", INT2FIX(cv::COLOR_BayerBG2BGR)); + rb_define_const(rb_module, "COLOR_BayerGB2BGR", INT2FIX(cv::COLOR_BayerGB2BGR)); + rb_define_const(rb_module, "COLOR_BayerRG2BGR", INT2FIX(cv::COLOR_BayerRG2BGR)); + rb_define_const(rb_module, "COLOR_BayerGR2BGR", INT2FIX(cv::COLOR_BayerGR2BGR)); + rb_define_const(rb_module, "COLOR_BayerBG2RGB", INT2FIX(cv::COLOR_BayerBG2RGB)); + rb_define_const(rb_module, "COLOR_BayerGB2RGB", INT2FIX(cv::COLOR_BayerGB2RGB)); + rb_define_const(rb_module, "COLOR_BayerRG2RGB", INT2FIX(cv::COLOR_BayerRG2RGB)); + rb_define_const(rb_module, "COLOR_BayerGR2RGB", INT2FIX(cv::COLOR_BayerGR2RGB)); + rb_define_const(rb_module, "COLOR_BayerBG2GRAY", INT2FIX(cv::COLOR_BayerBG2GRAY)); + rb_define_const(rb_module, "COLOR_BayerGB2GRAY", INT2FIX(cv::COLOR_BayerGB2GRAY)); + rb_define_const(rb_module, "COLOR_BayerRG2GRAY", INT2FIX(cv::COLOR_BayerRG2GRAY)); + rb_define_const(rb_module, "COLOR_BayerGR2GRAY", INT2FIX(cv::COLOR_BayerGR2GRAY)); + rb_define_const(rb_module, "COLOR_BayerBG2BGR_VNG", INT2FIX(cv::COLOR_BayerBG2BGR_VNG)); + rb_define_const(rb_module, "COLOR_BayerGB2BGR_VNG", INT2FIX(cv::COLOR_BayerGB2BGR_VNG)); + rb_define_const(rb_module, "COLOR_BayerRG2BGR_VNG", INT2FIX(cv::COLOR_BayerRG2BGR_VNG)); + rb_define_const(rb_module, "COLOR_BayerGR2BGR_VNG", INT2FIX(cv::COLOR_BayerGR2BGR_VNG)); + rb_define_const(rb_module, "COLOR_BayerBG2RGB_VNG", INT2FIX(cv::COLOR_BayerBG2RGB_VNG)); + rb_define_const(rb_module, "COLOR_BayerGB2RGB_VNG", INT2FIX(cv::COLOR_BayerGB2RGB_VNG)); + rb_define_const(rb_module, "COLOR_BayerRG2RGB_VNG", INT2FIX(cv::COLOR_BayerRG2RGB_VNG)); + rb_define_const(rb_module, "COLOR_BayerGR2RGB_VNG", INT2FIX(cv::COLOR_BayerGR2RGB_VNG)); + rb_define_const(rb_module, "COLOR_BayerBG2BGR_EA", INT2FIX(cv::COLOR_BayerBG2BGR_EA)); + rb_define_const(rb_module, "COLOR_BayerGB2BGR_EA", INT2FIX(cv::COLOR_BayerGB2BGR_EA)); + rb_define_const(rb_module, "COLOR_BayerRG2BGR_EA", INT2FIX(cv::COLOR_BayerRG2BGR_EA)); + rb_define_const(rb_module, "COLOR_BayerGR2BGR_EA", INT2FIX(cv::COLOR_BayerGR2BGR_EA)); + rb_define_const(rb_module, "COLOR_BayerBG2RGB_EA", INT2FIX(cv::COLOR_BayerBG2RGB_EA)); + rb_define_const(rb_module, "COLOR_BayerGB2RGB_EA", INT2FIX(cv::COLOR_BayerGB2RGB_EA)); + rb_define_const(rb_module, "COLOR_BayerRG2RGB_EA", INT2FIX(cv::COLOR_BayerRG2RGB_EA)); + rb_define_const(rb_module, "COLOR_BayerGR2RGB_EA", INT2FIX(cv::COLOR_BayerGR2RGB_EA)); + rb_define_const(rb_module, "COLOR_COLORCVT_MAX", INT2FIX(cv::COLOR_COLORCVT_MAX)); + + rb_define_const(rb_module, "CV_LOAD_IMAGE_UNCHANGED", INT2FIX(CV_LOAD_IMAGE_UNCHANGED)); + rb_define_const(rb_module, "CV_LOAD_IMAGE_GRAYSCALE", INT2FIX(CV_LOAD_IMAGE_GRAYSCALE)); + rb_define_const(rb_module, "CV_LOAD_IMAGE_COLOR", INT2FIX(CV_LOAD_IMAGE_COLOR)); + rb_define_const(rb_module, "CV_LOAD_IMAGE_ANYDEPTH", INT2FIX(CV_LOAD_IMAGE_ANYDEPTH)); + rb_define_const(rb_module, "CV_LOAD_IMAGE_ANYCOLOR", INT2FIX(CV_LOAD_IMAGE_ANYCOLOR)); + + rb_define_const(rb_module, "CV_IMWRITE_JPEG_QUALITY", INT2FIX(CV_IMWRITE_JPEG_QUALITY)); + rb_define_const(rb_module, "CV_IMWRITE_JPEG_PROGRESSIVE", INT2FIX(CV_IMWRITE_JPEG_PROGRESSIVE)); + rb_define_const(rb_module, "CV_IMWRITE_JPEG_OPTIMIZE", INT2FIX(CV_IMWRITE_JPEG_OPTIMIZE)); + rb_define_const(rb_module, "CV_IMWRITE_JPEG_RST_INTERVAL", INT2FIX(CV_IMWRITE_JPEG_RST_INTERVAL)); + rb_define_const(rb_module, "CV_IMWRITE_JPEG_LUMA_QUALITY", INT2FIX(CV_IMWRITE_JPEG_LUMA_QUALITY)); + rb_define_const(rb_module, "CV_IMWRITE_JPEG_CHROMA_QUALITY", INT2FIX(CV_IMWRITE_JPEG_CHROMA_QUALITY)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_COMPRESSION", INT2FIX(CV_IMWRITE_PNG_COMPRESSION)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY", INT2FIX(CV_IMWRITE_PNG_STRATEGY)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_BILEVEL", INT2FIX(CV_IMWRITE_PNG_BILEVEL)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY_DEFAULT", INT2FIX(CV_IMWRITE_PNG_STRATEGY_DEFAULT)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY_FILTERED", INT2FIX(CV_IMWRITE_PNG_STRATEGY_FILTERED)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY", INT2FIX(CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY_RLE", INT2FIX(CV_IMWRITE_PNG_STRATEGY_RLE)); + rb_define_const(rb_module, "CV_IMWRITE_PNG_STRATEGY_FIXED", INT2FIX(CV_IMWRITE_PNG_STRATEGY_FIXED)); + rb_define_const(rb_module, "CV_IMWRITE_PXM_BINARY", INT2FIX(CV_IMWRITE_PXM_BINARY)); + rb_define_const(rb_module, "CV_IMWRITE_WEBP_QUALITY", INT2FIX(CV_IMWRITE_WEBP_QUALITY)); + + rb_define_const(rb_module, "IMREAD_UNCHANGED", INT2FIX(cv::IMREAD_UNCHANGED)); + rb_define_const(rb_module, "IMREAD_GRAYSCALE", INT2FIX(cv::IMREAD_GRAYSCALE)); + rb_define_const(rb_module, "IMREAD_COLOR", INT2FIX(cv::IMREAD_COLOR)); + rb_define_const(rb_module, "IMREAD_ANYDEPTH", INT2FIX(cv::IMREAD_ANYDEPTH)); + rb_define_const(rb_module, "IMREAD_ANYCOLOR", INT2FIX(cv::IMREAD_ANYCOLOR)); + rb_define_const(rb_module, "IMREAD_LOAD_GDAL", INT2FIX(cv::IMREAD_LOAD_GDAL)); + rb_define_const(rb_module, "IMREAD_REDUCED_GRAYSCALE_2", INT2FIX(cv::IMREAD_REDUCED_GRAYSCALE_2)); + rb_define_const(rb_module, "IMREAD_REDUCED_COLOR_2", INT2FIX(cv::IMREAD_REDUCED_COLOR_2)); + rb_define_const(rb_module, "IMREAD_REDUCED_GRAYSCALE_4", INT2FIX(cv::IMREAD_REDUCED_GRAYSCALE_4)); + rb_define_const(rb_module, "IMREAD_REDUCED_COLOR_4", INT2FIX(cv::IMREAD_REDUCED_COLOR_4)); + rb_define_const(rb_module, "IMREAD_REDUCED_GRAYSCALE_8", INT2FIX(cv::IMREAD_REDUCED_GRAYSCALE_8)); + rb_define_const(rb_module, "IMREAD_REDUCED_COLOR_8", INT2FIX(cv::IMREAD_REDUCED_COLOR_8)); + rb_define_const(rb_module, "IMWRITE_JPEG_QUALITY", INT2FIX(cv::IMWRITE_JPEG_QUALITY)); + rb_define_const(rb_module, "IMWRITE_JPEG_PROGRESSIVE", INT2FIX(cv::IMWRITE_JPEG_PROGRESSIVE)); + rb_define_const(rb_module, "IMWRITE_JPEG_OPTIMIZE", INT2FIX(cv::IMWRITE_JPEG_OPTIMIZE)); + rb_define_const(rb_module, "IMWRITE_JPEG_RST_INTERVAL", INT2FIX(cv::IMWRITE_JPEG_RST_INTERVAL)); + rb_define_const(rb_module, "IMWRITE_JPEG_LUMA_QUALITY", INT2FIX(cv::IMWRITE_JPEG_LUMA_QUALITY)); + rb_define_const(rb_module, "IMWRITE_JPEG_CHROMA_QUALITY", INT2FIX(cv::IMWRITE_JPEG_CHROMA_QUALITY)); + rb_define_const(rb_module, "IMWRITE_PNG_COMPRESSION", INT2FIX(cv::IMWRITE_PNG_COMPRESSION)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY", INT2FIX(cv::IMWRITE_PNG_STRATEGY)); + rb_define_const(rb_module, "IMWRITE_PNG_BILEVEL", INT2FIX(cv::IMWRITE_PNG_BILEVEL)); + rb_define_const(rb_module, "IMWRITE_PXM_BINARY", INT2FIX(cv::IMWRITE_PXM_BINARY)); + rb_define_const(rb_module, "IMWRITE_WEBP_QUALITY", INT2FIX(cv::IMWRITE_WEBP_QUALITY)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY_DEFAULT", INT2FIX(cv::IMWRITE_PNG_STRATEGY_DEFAULT)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY_FILTERED", INT2FIX(cv::IMWRITE_PNG_STRATEGY_FILTERED)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY", INT2FIX(cv::IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY_RLE", INT2FIX(cv::IMWRITE_PNG_STRATEGY_RLE)); + rb_define_const(rb_module, "IMWRITE_PNG_STRATEGY_FIXED", INT2FIX(cv::IMWRITE_PNG_STRATEGY_FIXED)); + + rb_define_const(rb_module, "CV_AA", INT2FIX(CV_AA)); + + rb_define_const(rb_module, "INTER_NEAREST", INT2FIX(cv::INTER_NEAREST)); + rb_define_const(rb_module, "INTER_LINEAR", INT2FIX(cv::INTER_LINEAR)); + rb_define_const(rb_module, "INTER_AREA", INT2FIX(cv::INTER_AREA)); + rb_define_const(rb_module, "INTER_CUBIC", INT2FIX(cv::INTER_CUBIC)); + rb_define_const(rb_module, "INTER_LANCZOS4", INT2FIX(cv::INTER_LANCZOS4)); + + rb_define_const(rb_module, "BORDER_CONSTANT", INT2FIX(cv::BORDER_CONSTANT)); + rb_define_const(rb_module, "BORDER_REPLICATE", INT2FIX(cv::BORDER_REPLICATE)); + rb_define_const(rb_module, "BORDER_REFLECT", INT2FIX(cv::BORDER_REFLECT)); + rb_define_const(rb_module, "BORDER_WRAP", INT2FIX(cv::BORDER_WRAP)); + rb_define_const(rb_module, "BORDER_REFLECT_101", INT2FIX(cv::BORDER_REFLECT_101)); + rb_define_const(rb_module, "BORDER_TRANSPARENT", INT2FIX(cv::BORDER_TRANSPARENT)); + rb_define_const(rb_module, "BORDER_REFLECT101", INT2FIX(cv::BORDER_REFLECT101)); + rb_define_const(rb_module, "BORDER_DEFAULT", INT2FIX(cv::BORDER_DEFAULT)); + rb_define_const(rb_module, "BORDER_ISOLATED", INT2FIX(cv::BORDER_ISOLATED)); + + rb_define_const(rb_module, "EVENT_MOUSEMOVE", INT2FIX(cv::EVENT_MOUSEMOVE)); + rb_define_const(rb_module, "EVENT_LBUTTONDOWN", INT2FIX(cv::EVENT_LBUTTONDOWN)); + rb_define_const(rb_module, "EVENT_RBUTTONDOWN", INT2FIX(cv::EVENT_RBUTTONDOWN)); + rb_define_const(rb_module, "EVENT_MBUTTONDOWN", INT2FIX(cv::EVENT_MBUTTONDOWN)); + rb_define_const(rb_module, "EVENT_LBUTTONUP", INT2FIX(cv::EVENT_LBUTTONUP)); + rb_define_const(rb_module, "EVENT_RBUTTONUP", INT2FIX(cv::EVENT_RBUTTONUP)); + rb_define_const(rb_module, "EVENT_MBUTTONUP", INT2FIX(cv::EVENT_MBUTTONUP)); + rb_define_const(rb_module, "EVENT_LBUTTONDBLCLK", INT2FIX(cv::EVENT_LBUTTONDBLCLK)); + rb_define_const(rb_module, "EVENT_RBUTTONDBLCLK", INT2FIX(cv::EVENT_RBUTTONDBLCLK)); + rb_define_const(rb_module, "EVENT_MBUTTONDBLCLK", INT2FIX(cv::EVENT_MBUTTONDBLCLK)); + rb_define_const(rb_module, "EVENT_MOUSEWHEEL", INT2FIX(cv::EVENT_MOUSEWHEEL)); + rb_define_const(rb_module, "EVENT_MOUSEHWHEEL", INT2FIX(cv::EVENT_MOUSEHWHEEL)); + rb_define_const(rb_module, "EVENT_FLAG_LBUTTON", INT2FIX(cv::EVENT_FLAG_LBUTTON)); + rb_define_const(rb_module, "EVENT_FLAG_RBUTTON", INT2FIX(cv::EVENT_FLAG_RBUTTON)); + rb_define_const(rb_module, "EVENT_FLAG_MBUTTON", INT2FIX(cv::EVENT_FLAG_MBUTTON)); + rb_define_const(rb_module, "EVENT_FLAG_CTRLKEY", INT2FIX(cv::EVENT_FLAG_CTRLKEY)); + rb_define_const(rb_module, "EVENT_FLAG_SHIFTKEY", INT2FIX(cv::EVENT_FLAG_SHIFTKEY)); + rb_define_const(rb_module, "EVENT_FLAG_ALTKEY", INT2FIX(cv::EVENT_FLAG_ALTKEY)); + + rb_define_const(rb_module, "CAP_PROP_POS_MSEC", INT2FIX(cv::CAP_PROP_POS_MSEC)); + rb_define_const(rb_module, "CAP_PROP_POS_FRAMES", INT2FIX(cv::CAP_PROP_POS_FRAMES)); + rb_define_const(rb_module, "CAP_PROP_POS_AVI_RATIO", INT2FIX(cv::CAP_PROP_POS_AVI_RATIO)); + rb_define_const(rb_module, "CAP_PROP_FRAME_WIDTH", INT2FIX(cv::CAP_PROP_FRAME_WIDTH)); + rb_define_const(rb_module, "CAP_PROP_FRAME_HEIGHT", INT2FIX(cv::CAP_PROP_FRAME_HEIGHT)); + rb_define_const(rb_module, "CAP_PROP_FPS", INT2FIX(cv::CAP_PROP_FPS)); + rb_define_const(rb_module, "CAP_PROP_FOURCC", INT2FIX(cv::CAP_PROP_FOURCC)); + rb_define_const(rb_module, "CAP_PROP_FRAME_COUNT", INT2FIX(cv::CAP_PROP_FRAME_COUNT)); + rb_define_const(rb_module, "CAP_PROP_FORMAT", INT2FIX(cv::CAP_PROP_FORMAT)); + rb_define_const(rb_module, "CAP_PROP_MODE", INT2FIX(cv::CAP_PROP_MODE)); + rb_define_const(rb_module, "CAP_PROP_BRIGHTNESS", INT2FIX(cv::CAP_PROP_BRIGHTNESS)); + rb_define_const(rb_module, "CAP_PROP_CONTRAST", INT2FIX(cv::CAP_PROP_CONTRAST)); + rb_define_const(rb_module, "CAP_PROP_SATURATION", INT2FIX(cv::CAP_PROP_SATURATION)); + rb_define_const(rb_module, "CAP_PROP_HUE", INT2FIX(cv::CAP_PROP_HUE)); + rb_define_const(rb_module, "CAP_PROP_GAIN", INT2FIX(cv::CAP_PROP_GAIN)); + rb_define_const(rb_module, "CAP_PROP_EXPOSURE", INT2FIX(cv::CAP_PROP_EXPOSURE)); + rb_define_const(rb_module, "CAP_PROP_CONVERT_RGB", INT2FIX(cv::CAP_PROP_CONVERT_RGB)); + rb_define_const(rb_module, "CAP_PROP_WHITE_BALANCE_BLUE_U", INT2FIX(cv::CAP_PROP_WHITE_BALANCE_BLUE_U)); + rb_define_const(rb_module, "CAP_PROP_RECTIFICATION", INT2FIX(cv::CAP_PROP_RECTIFICATION)); + rb_define_const(rb_module, "CAP_PROP_MONOCHROME", INT2FIX(cv::CAP_PROP_MONOCHROME)); + rb_define_const(rb_module, "CAP_PROP_SHARPNESS", INT2FIX(cv::CAP_PROP_SHARPNESS)); + rb_define_const(rb_module, "CAP_PROP_AUTO_EXPOSURE", INT2FIX(cv::CAP_PROP_AUTO_EXPOSURE)); + rb_define_const(rb_module, "CAP_PROP_GAMMA", INT2FIX(cv::CAP_PROP_GAMMA)); + rb_define_const(rb_module, "CAP_PROP_TEMPERATURE", INT2FIX(cv::CAP_PROP_TEMPERATURE)); + rb_define_const(rb_module, "CAP_PROP_TRIGGER", INT2FIX(cv::CAP_PROP_TRIGGER)); + rb_define_const(rb_module, "CAP_PROP_TRIGGER_DELAY", INT2FIX(cv::CAP_PROP_TRIGGER_DELAY)); + rb_define_const(rb_module, "CAP_PROP_WHITE_BALANCE_RED_V", INT2FIX(cv::CAP_PROP_WHITE_BALANCE_RED_V)); + rb_define_const(rb_module, "CAP_PROP_ZOOM", INT2FIX(cv::CAP_PROP_ZOOM)); + rb_define_const(rb_module, "CAP_PROP_FOCUS", INT2FIX(cv::CAP_PROP_FOCUS)); + rb_define_const(rb_module, "CAP_PROP_GUID", INT2FIX(cv::CAP_PROP_GUID)); + rb_define_const(rb_module, "CAP_PROP_ISO_SPEED", INT2FIX(cv::CAP_PROP_ISO_SPEED)); + rb_define_const(rb_module, "CAP_PROP_BACKLIGHT", INT2FIX(cv::CAP_PROP_BACKLIGHT)); + rb_define_const(rb_module, "CAP_PROP_PAN", INT2FIX(cv::CAP_PROP_PAN)); + rb_define_const(rb_module, "CAP_PROP_TILT", INT2FIX(cv::CAP_PROP_TILT)); + rb_define_const(rb_module, "CAP_PROP_ROLL", INT2FIX(cv::CAP_PROP_ROLL)); + rb_define_const(rb_module, "CAP_PROP_IRIS", INT2FIX(cv::CAP_PROP_IRIS)); + rb_define_const(rb_module, "CAP_PROP_SETTINGS", INT2FIX(cv::CAP_PROP_SETTINGS)); + rb_define_const(rb_module, "CAP_PROP_BUFFERSIZE", INT2FIX(cv::CAP_PROP_BUFFERSIZE)); + rb_define_const(rb_module, "CAP_PROP_AUTOFOCUS", INT2FIX(cv::CAP_PROP_AUTOFOCUS)); + } +} diff --git a/ext/opencv/point.cpp b/ext/opencv/point.cpp index eb59ce4..71c8d86 100644 --- a/ext/opencv/point.cpp +++ b/ext/opencv/point.cpp @@ -154,7 +154,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Point", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/point.cppe b/ext/opencv/point.cppe new file mode 100644 index 0000000..eb59ce4 --- /dev/null +++ b/ext/opencv/point.cppe @@ -0,0 +1,172 @@ +#include +#include "ruby.h" +#include "opencv2/core.hpp" + +#include "point.hpp" + +namespace rubyopencv { + namespace Point { + void free_point(void* ptr); + size_t memsize_point(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_point_type = { + "Point", + { 0, free_point, memsize_point, 0 }, + 0, + 0, + 0 + }; + + size_t memsize_point(const void* ptr) { + return sizeof(cv::Point); + } + + cv::Point* obj2point(VALUE obj) { + cv::Point* ptr = NULL; + TypedData_Get_Struct(obj, cv::Point, &opencv_point_type, ptr); + return ptr; + } + + VALUE point2obj(cv::Point* ptr) { + return TypedData_Wrap_Struct(rb_klass, &opencv_point_type, (void*)ptr); + } + + cv::Point conpatible_obj2point(VALUE obj) { + if (rb_respond_to(obj, rb_intern("x")) && rb_respond_to(obj, rb_intern("y"))) { + return cv::Point(NUM2INT(rb_funcall(obj, rb_intern("x"), 0)), + NUM2INT(rb_funcall(obj, rb_intern("y"), 0))); + } + rb_raise(rb_eTypeError, "wrong argument type %s (expected %s or compatible object)", + rb_obj_classname(obj), rb_class2name(rb_klass)); + throw; + } + + void free_point(void* ptr) { + xfree(ptr); + } + + VALUE rb_allocate(VALUE klass) { + cv::Point* ptr = NULL; + return TypedData_Make_Struct(klass, cv::Point, &opencv_point_type, ptr); + } + + /* + * call-seq: + * new -> OpenCV::Point.new(0, 0) + * new(obj) -> OpenCV::Point.new(obj.x.to_i, obj.y.to_i) + * new(x, y) + * + * Create new 2D-coordinate, (x, y). It is dropped below the decimal point. + * + * new() is same as new(0, 0) + * + * new(obj) is same as new(obj.x.to_i, obj.y.to_i) + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE v1, v2; + rb_scan_args(argc, argv, "02", &v1, &v2); + cv::Point* selfptr = obj2point(self); + switch (argc) { + case 0: + selfptr->x = 0; + selfptr->y = 0; + break; + case 1: { + cv::Point point = conpatible_obj2point(v1); + selfptr->x = point.x; + selfptr->y = point.y; + break; + } + case 2: + selfptr->x = NUM2INT(v1); + selfptr->y = NUM2INT(v2); + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc); + break; + } + + return self; + } + + /* + * Return parameter on x-axis. + */ + VALUE rb_x(VALUE self) { + return INT2NUM(obj2point(self)->x); + } + + /* + * call-seq: + * x = val + */ + VALUE rb_set_x(VALUE self, VALUE x) { + obj2point(self)->x = NUM2INT(x); + return self; + } + + /* + * Return parameter on y-axis. + */ + VALUE rb_y(VALUE self) { + return INT2NUM(obj2point(self)->y); + } + + /* + * call-seq: + * y = val + */ + VALUE rb_set_y(VALUE self, VALUE y) { + obj2point(self)->y = NUM2INT(y); + return self; + } + + /* + * Return x and y as an +String+. + * + * @overload to_s + * @return [String] String representation of the point + */ + VALUE rb_to_s(VALUE self) { + std::stringstream s; + cv::Point* selfptr = obj2point(self); + s << *selfptr; + + VALUE param[3]; + param[0] = rb_str_new2("#<%s:%s>"); + param[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + param[2] = rb_str_new2(s.str().c_str()); + + int n = sizeof(param) / sizeof(param[0]); + return rb_f_sprintf(n, param); + } + + /* + * Return x and y as an +Array+. + * + * @overload to_a + * @return [Array] Array representation of the point + */ + VALUE rb_to_a(VALUE self) { + cv::Point* selfptr = obj2point(self); + return rb_ary_new3(2, INT2NUM(selfptr->x), INT2NUM(selfptr->y)); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Point", rb_cData); + 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, "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_a", RUBY_METHOD_FUNC(rb_to_a), 0); + } + } +} + diff --git a/ext/opencv/rect.cpp b/ext/opencv/rect.cpp index 2fc47a4..b11d82d 100644 --- a/ext/opencv/rect.cpp +++ b/ext/opencv/rect.cpp @@ -179,7 +179,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Rect", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/rect.cppe b/ext/opencv/rect.cppe new file mode 100644 index 0000000..2fc47a4 --- /dev/null +++ b/ext/opencv/rect.cppe @@ -0,0 +1,200 @@ +#include +#include "ruby.h" +#include "opencv2/core.hpp" + +#include "error.hpp" + +/* + * Document-class: OpenCV::Rect + */ +namespace rubyopencv { + namespace Rect { + void free_rect(void* ptr); + size_t memsize_rect(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_rect_type = { + "Rect", + { 0, free_rect, memsize_rect, 0 }, + 0, + 0, + 0 + }; + + void free_rect(void* ptr) { + delete (cv::Rect*)ptr; + } + + size_t memsize_rect(const void* ptr) { + return sizeof(cv::Rect); + } + + cv::Rect* obj2rect(VALUE obj) { + cv::Rect* ptr = NULL; + TypedData_Get_Struct(obj, cv::Rect, &opencv_rect_type, ptr); + return ptr; + } + + VALUE rect2obj (cv::Rect rect) { + cv::Rect* ptr = new cv::Rect(rect); + return TypedData_Wrap_Struct(rb_klass, &opencv_rect_type, ptr); + } + + VALUE rb_allocate(VALUE klass) { + cv::Rect* ptr = new cv::Rect(); + return TypedData_Wrap_Struct(klass, &opencv_rect_type, ptr); + } + + /* + * Create a rectangle + * + * @overload new() + * @return [Rect] new rectangle + * @overload new(x, y, width, height) + * @param x [Integer] x coordinate + * @param y [Integer] y coordinate + * @param width [Integer] Width + * @param height [Integer] Height + * @return [Rect] new rectangle + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + const int SIZE = 4; + VALUE values[SIZE]; + rb_scan_args(argc, argv, "04", &values[0], &values[1], &values[2], &values[3]); + + cv::Rect* selfptr = obj2rect(self); + switch (argc) { + case 0: + selfptr->x = 0; + selfptr->y = 0; + selfptr->width = 0; + selfptr->height = 0; + break; + case 4: + selfptr->x = NUM2INT(values[0]); + selfptr->y = NUM2INT(values[1]); + selfptr->width = NUM2INT(values[2]); + selfptr->height = NUM2INT(values[3]); + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 4)", argc); + break; + } + + return self; + } + + /* + * Return parameter on x-axis. + */ + VALUE rb_x(VALUE self) { + return INT2NUM(obj2rect(self)->x); + } + + /* + * call-seq: + * x = val + */ + VALUE rb_set_x(VALUE self, VALUE x) { + obj2rect(self)->x = NUM2INT(x); + return self; + } + + /* + * Return parameter on y-axis. + */ + VALUE rb_y(VALUE self) { + return INT2NUM(obj2rect(self)->y); + } + + /* + * call-seq: + * y = val + */ + VALUE rb_set_y(VALUE self, VALUE y) { + obj2rect(self)->y = NUM2INT(y); + return self; + } + + /* + * Return width + * + * @overload width + * @return [Integer] Width + */ + VALUE rb_width(VALUE self) { + return INT2NUM(obj2rect(self)->width); + } + + /* + * Set width + * + * @overload width=(value) + * @param value [Integer] Width + * @return [Rect] +self+ + */ + VALUE rb_set_width(VALUE self, VALUE width) { + obj2rect(self)->width = NUM2INT(width); + return self; + } + + /* + * Return height + * + * @overload height + * @return [Integer] Height + */ + VALUE rb_height(VALUE self) { + return INT2NUM(obj2rect(self)->height); + } + + /* + * Set height + * + * @overload height=(value) + * @param value [Integer] Height + * @return [Rect] +self+ + */ + VALUE rb_set_height(VALUE self, VALUE height) { + obj2rect(self)->height = NUM2INT(height); + return self; + } + + /* + * @overload to_s + * @return [String] String representation of the rectangle + */ + VALUE rb_to_s(VALUE self) { + std::stringstream s; + cv::Rect* selfptr = obj2rect(self); + s << *selfptr; + + VALUE param[3]; + param[0] = rb_str_new2("#<%s:%s>"); + param[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + param[2] = rb_str_new2(s.str().c_str()); + + int n = sizeof(param) / sizeof(param[0]); + return rb_f_sprintf(n, param); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Rect", rb_cData); + 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_s", RUBY_METHOD_FUNC(rb_to_s), 0); + 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); + } + } +} diff --git a/ext/opencv/scalar.cpp b/ext/opencv/scalar.cpp index e99e027..5632cc8 100644 --- a/ext/opencv/scalar.cpp +++ b/ext/opencv/scalar.cpp @@ -116,7 +116,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Scalar", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/scalar.cppe b/ext/opencv/scalar.cppe new file mode 100644 index 0000000..e99e027 --- /dev/null +++ b/ext/opencv/scalar.cppe @@ -0,0 +1,132 @@ +// -*- mode: c++; coding: utf-8 -*- +#include +#include "ruby.h" +#include "opencv2/core.hpp" + +namespace rubyopencv { + namespace Scalar { + void free_scalar(void* ptr); + size_t memsize_scalar(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_scalar_type = { + "Scalar", + { 0, free_scalar, memsize_scalar, 0 }, + 0, + 0, + 0 + }; + + void free_scalar(void* ptr) { + delete (cv::Scalar*)ptr; + } + + size_t memsize_scalar(const void* ptr) { + return sizeof(cv::Scalar); + } + + VALUE klass() { + return rb_klass; + } + + cv::Scalar* obj2scalar(VALUE obj) { + cv::Scalar* ptr = NULL; + TypedData_Get_Struct(obj, cv::Scalar, &opencv_scalar_type, ptr); + return ptr; + } + + VALUE scalar2obj(cv::Scalar* ptr) { + return TypedData_Wrap_Struct(rb_klass, &opencv_scalar_type, ptr); + } + + VALUE rb_allocate(VALUE klass) { + cv::Scalar* ptr = NULL; + return TypedData_Make_Struct(klass, cv::Scalar, &opencv_scalar_type, ptr); + } + + /* + * Creates a new Scalar. + * + * @overload new(v0 = 0, v1 = 0, v2 = 0, v3 = 0) + * @param v0 [Number] Value 0 + * @param v1 [Number] Value 1 + * @param v2 [Number] Value 2 + * @param v3 [Number] Value 3 + * @return [Scalar] +self+ + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + const int SIZE = 4; + VALUE values[SIZE]; + rb_scan_args(argc, argv, "04", &values[0], &values[1], &values[2], &values[3]); + + cv::Scalar* selfptr = obj2scalar(self); + for (int i = 0; i < SIZE; i++) { + (*selfptr)[i] = NIL_P(values[i]) ? 0.0 : NUM2DBL(values[i]); + } + + return self; + } + + VALUE rb_aref(VALUE self, VALUE index) { + cv::Scalar* selfptr = obj2scalar(self); + int i = NUM2INT(index); + if (i < 0 || i >= 4) { + rb_raise(rb_eIndexError, "index should be 0...4"); + } + + return rb_float_new((*selfptr)[i]); + } + + VALUE rb_aset(VALUE self, VALUE index, VALUE value) { + int i = NUM2INT(index); + if (i < 0 || i >= 4) { + rb_raise(rb_eIndexError, "index should be 0...4"); + } + cv::Scalar* selfptr = obj2scalar(self); + (*selfptr)[i] = NUM2DBL(value); + + return self; + } + + /* + * @overload to_s + * @return [String] String representation of the scalar + */ + VALUE rb_to_s(VALUE self) { + std::stringstream s; + cv::Scalar* selfptr = obj2scalar(self); + s << *selfptr; + + VALUE param[3]; + param[0] = rb_str_new2("#<%s:%s>"); + param[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + param[2] = rb_str_new2(s.str().c_str()); + + int n = sizeof(param) / sizeof(param[0]); + return rb_f_sprintf(n, param); + } + + /* + * @overload to_a + * @return [Array] Values in Array + */ + VALUE rb_to_a(VALUE self) { + return rb_ary_new3(4, rb_aref(self, INT2FIX(0)), rb_aref(self, INT2FIX(1)), + rb_aref(self, INT2FIX(2)), rb_aref(self, INT2FIX(3))); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Scalar", rb_cData); + 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_s", RUBY_METHOD_FUNC(rb_to_s), 0); + rb_define_method(rb_klass, "to_a", RUBY_METHOD_FUNC(rb_to_a), 0); + rb_define_method(rb_klass, "[]", RUBY_METHOD_FUNC(rb_aref), 1); + rb_define_method(rb_klass, "[]=", RUBY_METHOD_FUNC(rb_aset), 2); + } + } +} diff --git a/ext/opencv/size.cpp b/ext/opencv/size.cpp index 8d5b189..c3c238d 100644 --- a/ext/opencv/size.cpp +++ b/ext/opencv/size.cpp @@ -129,7 +129,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Size", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/size.cppe b/ext/opencv/size.cppe new file mode 100644 index 0000000..8d5b189 --- /dev/null +++ b/ext/opencv/size.cppe @@ -0,0 +1,146 @@ +// -*- mode: c++; coding: utf-8 -*- +#include +#include "ruby.h" +#include "opencv2/core.hpp" + +#include "size.hpp" + +namespace rubyopencv { + namespace Size { + void free_size(void* ptr); + size_t memsize_size(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_size_type = { + "Size", + { 0, free_size, memsize_size, 0 }, + 0, + 0, + 0 + }; + + void free_size(void* ptr) { + delete (cv::Size*)ptr; + } + + size_t memsize_size(const void* ptr) { + return sizeof(cv::Size); + } + + cv::Size* obj2size(VALUE obj) { + cv::Size* ptr = NULL; + TypedData_Get_Struct(obj, cv::Size, &opencv_size_type, ptr); + return ptr; + } + + VALUE size2obj(cv::Size* ptr) { + return TypedData_Wrap_Struct(rb_klass, &opencv_size_type, (void*)ptr); + } + + VALUE rb_allocate(VALUE klass) { + cv::Size* ptr = new cv::Size(); + return TypedData_Wrap_Struct(klass, &opencv_size_type, ptr); + } + + /* + * Return width + * + * @overload width + * @return [Integer] Width + */ + VALUE rb_width(VALUE self) { + return INT2NUM(obj2size(self)->width); + } + + /* + * Set width + * + * @overload width=(value) + * @param value [Integer] Width + * @return [Mat] +self+ + */ + VALUE rb_set_width(VALUE self, VALUE width) { + obj2size(self)->width = NUM2INT(width); + return self; + } + + /* + * Return height + * + * @overload height + * @return [Integer] Height + */ + VALUE rb_height(VALUE self) { + return INT2NUM(obj2size(self)->height); + } + + /* + * Set height + * + * @overload height=(value) + * @param value [Integer] Height + * @return [Mat] +self+ + */ + VALUE rb_set_height(VALUE self, VALUE height) { + obj2size(self)->height = NUM2INT(height); + return self; + } + + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE v1, v2; + rb_scan_args(argc, argv, "02", &v1, &v2); + + cv::Size* selfptr = obj2size(self); + switch (argc) { + case 0: + selfptr->width = 0; + selfptr->height = 0; + break; + case 2: + selfptr->width = NUM2INT(v1); + selfptr->height = NUM2INT(v2); + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 2)", argc); + break; + } + + return self; + } + + /* + * Return size as an +String+. + * + * @overload to_s + * @return [String] String representation of the size + */ + VALUE rb_to_s(VALUE self) { + std::stringstream s; + cv::Size* selfptr = obj2size(self); + s << *selfptr; + + VALUE param[3]; + param[0] = rb_str_new2("#<%s:%s>"); + param[1] = rb_str_new2(rb_class2name(CLASS_OF(self))); + param[2] = rb_str_new2(s.str().c_str()); + + int n = sizeof(param) / sizeof(param[0]); + return rb_f_sprintf(n, param); + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Size", rb_cData); + 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, "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); + } + } +} diff --git a/ext/opencv/trackbar.cpp b/ext/opencv/trackbar.cpp index 031f495..c393b4b 100644 --- a/ext/opencv/trackbar.cpp +++ b/ext/opencv/trackbar.cpp @@ -116,7 +116,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Trackbar", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1); diff --git a/ext/opencv/trackbar.cppe b/ext/opencv/trackbar.cppe new file mode 100644 index 0000000..031f495 --- /dev/null +++ b/ext/opencv/trackbar.cppe @@ -0,0 +1,129 @@ +#include "opencv2/highgui.hpp" +#include "ruby.h" + +#include "trackbar.hpp" + +/* + * Document-class: OpenCV::Trackbar + */ +namespace rubyopencv { + namespace Trackbar { + void mark_trackbar(void *ptr); + void free_trackbar(void *ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_trackbar_type = { + "Trackbar", + { mark_trackbar, free_trackbar, 0, 0 }, + 0, + 0, + 0 + }; + + void mark_trackbar(void *ptr) { + trackbar_t* trackbar_ptr = (trackbar_t*)ptr; + rb_gc_mark(trackbar_ptr->block); + } + + void free_trackbar(void *ptr) { + xfree(((trackbar_t*)ptr)->name); + xfree(ptr); + } + + VALUE rb_allocate(VALUE klass) { + trackbar_t* ptr = NULL; + return TypedData_Make_Struct(klass, trackbar_t, &opencv_trackbar_type, ptr); + } + + void trackbar_mark(void *ptr) { + rb_gc_mark(((trackbar_t*)ptr)->block); + } + + trackbar_t* obj2trackbar(VALUE obj) { + trackbar_t* ptr = NULL; + TypedData_Get_Struct(obj, trackbar_t, &opencv_trackbar_type, ptr); + return ptr; + } + + /* + * Creates a new Trackbar. + * + * @overload new(name, count, value = 0, callback = nil) + * @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. + * @param [Proc] Function to be called every time the slider changes position. + * @return [Trackbar] Trackbar + * + * @overload new(name, count, value = 0) { |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. + * @return [Trackbar] Trackbar + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE name, maxval, value, block; + rb_scan_args(argc, argv, "21&", &name, &maxval, &value, &block); + Check_Type(name, T_STRING); + trackbar_t* selfptr = obj2trackbar(self); + selfptr->name = strcpy(ALLOC_N(char, RSTRING_LEN(name) + 1), StringValueCStr(name)); + selfptr->maxval = NUM2INT(maxval); + selfptr->value = NIL_P(value) ? 0 : NUM2INT(value); + selfptr->block = block; + + return self; + } + + VALUE newobj(int argc, VALUE *argv) { + VALUE obj = rb_allocate(rb_klass); + return rb_initialize(argc, argv, obj); + } + + /* + * Return trackbar name. + */ + VALUE rb_name(VALUE self) { + return rb_str_new2(obj2trackbar(self)->name); + } + + /* + * Return the maximum value that can be taken this trackbar. + */ + VALUE rb_max(VALUE self) { + return INT2NUM(obj2trackbar(self)->maxval); + } + + /* + * Return the value of this trackbar. + */ + VALUE rb_value(VALUE self) { + return INT2NUM(obj2trackbar(self)->value); + } + + /* + * call-seq: + * value = val + * + * Set trackbar value. + */ + VALUE rb_set_value(VALUE self, VALUE value) { + obj2trackbar(self)->value = NUM2INT(value); + return self; + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + rb_klass = rb_define_class_under(opencv, "Trackbar", rb_cData); + 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); + } + } +} diff --git a/ext/opencv/videocapture.cpp b/ext/opencv/videocapture.cpp index b3d4712..85de8fe 100644 --- a/ext/opencv/videocapture.cpp +++ b/ext/opencv/videocapture.cpp @@ -249,7 +249,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "VideoCapture", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/videocapture.cppe b/ext/opencv/videocapture.cppe new file mode 100644 index 0000000..b3d4712 --- /dev/null +++ b/ext/opencv/videocapture.cppe @@ -0,0 +1,266 @@ +// -*- mode: c++; coding: utf-8 -*- +#include "ruby.h" +#include "opencv2/core.hpp" +#include "opencv2/videoio.hpp" + +#include "videocapture.hpp" +#include "mat.hpp" +#include "error.hpp" + +/* + * Document-class: OpenCV::VideoCapture + */ +namespace rubyopencv { + namespace VideoCapture { + void free_videocapture(void* ptr); + size_t memsize_videocapture(const void* ptr); + + VALUE rb_klass = Qnil; + rb_data_type_t opencv_videocapture_type = { + "VideoCapture", + { 0, free_videocapture, memsize_videocapture, 0 }, + 0, + 0, + 0 + }; + + void free_videocapture(void* ptr) { + delete (cv::VideoCapture*)ptr; + } + + size_t memsize_videocapture(const void* ptr) { + return sizeof(cv::VideoCapture); + } + + cv::VideoCapture* obj2videocapture(VALUE obj) { + cv::VideoCapture* ptr = NULL; + TypedData_Get_Struct(obj, cv::VideoCapture, &opencv_videocapture_type, ptr); + return ptr; + } + + VALUE rb_allocate(VALUE klass) { + cv::VideoCapture* ptr = new cv::VideoCapture(); + return TypedData_Wrap_Struct(klass, &opencv_videocapture_type, ptr); + } + + /* + * Open video file or a capturing device for video capturing + * + * @scope class + * @overload new(device = 0) + * @param device [String, Fixnum, nil] Video capturing device + * * If dev is a string (i.e "stream.avi"), reads video stream from a file. + * * If dev is a number, reads video stream from a device. + * @return [VideoCapture] Opened capture instance + * @opencv_func cv::VideoCapture::open + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE value; + rb_scan_args(argc, argv, "01", &value); + + cv::VideoCapture* selfptr = obj2videocapture(self); + try { + if (TYPE(value) == T_STRING) { + char* filename = StringValueCStr(value); + selfptr->open(filename); + } + else { + int device = NIL_P(value) ? 0 : NUM2INT(value); + selfptr->open(device); + } + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + + /* + * Grabs, decodes and returns the next video frame. + * @overload query + * @return [Mat] Next video frame + * @opencv_func cv::VideoCapture::operator>> + */ + VALUE rb_read(VALUE self) { + cv::VideoCapture* selfptr = obj2videocapture(self); + cv::Mat* m = Mat::empty_mat(); + + try { + (*selfptr) >> (*m); + } + catch (cv::Exception& e) { + delete m; + Error::raise(e); + } + + return Mat::mat2obj(m); + } + + /* + * Returns true if video capturing has been initialized already. + * + * @overload opened? + * @return [Boolean] The video capturing has been initialized already or not. + * @opencv_func cv::VideoCapture::isOpened + */ + VALUE rb_is_opened(VALUE self) { + cv::VideoCapture* selfptr = obj2videocapture(self); + bool is_opened = false; + try { + is_opened = selfptr->isOpened(); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return is_opened ? Qtrue : Qfalse; + } + + /* + * Returns the specified VideoCapture property. + * + * @overload get(prop_id) + * @param prop_id [Integer] Property identifier. It can be one of the following: + * - CAP_PROP_POS_MSEC - Current position of the video file in milliseconds. + * - CAP_PROP_POS_FRAMES - 0-based index of the frame to be decoded/captured next. + * - CAP_PROP_POS_AVI_RATIO - Relative position of the video file: 0 - start of the film, 1 - end of the film. + * - CAP_PROP_FRAME_WIDTH - Width of the frames in the video stream. + * - CAP_PROP_FRAME_HEIGHT - Height of the frames in the video stream. + * - CAP_PROP_FPS - Frame rate. + * - CAP_PROP_FOURCC - 4-character code of codec. + * - CAP_PROP_FRAME_COUNT - Number of frames in the video file. + * - CAP_PROP_FORMAT - Format of the Mat objects returned by retrieve() . + * - CAP_PROP_MODE - Backend-specific value indicating the current capture mode. + * - CAP_PROP_BRIGHTNESS - Brightness of the image (only for cameras). + * - CAP_PROP_CONTRAST - Contrast of the image (only for cameras). + * - CAP_PROP_SATURATION - Saturation of the image (only for cameras). + * - CAP_PROP_HUE - Hue of the image (only for cameras). + * - CAP_PROP_GAIN - Gain of the image (only for cameras). + * - CAP_PROP_EXPOSURE - Exposure (only for cameras). + * - CAP_PROP_CONVERT_RGB - Boolean flags indicating whether images should be converted to RGB. + * - CAP_PROP_WHITE_BALANCE - Currently unsupported + * - CAP_PROP_RECTIFICATION - Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently) + * @return [Number] VideoCapture property + * @opencv_func cv::VideoCapture::get + */ + VALUE rb_get(VALUE self, VALUE prop_id) { + cv::VideoCapture* selfptr = obj2videocapture(self); + double ret = 0; + try { + ret = selfptr->get(NUM2INT(prop_id)); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return DBL2NUM(ret); + } + + /* + * Sets a property in the VideoCapture. + * + * @overload set(prop_id, value) + * @param prop_id [Integer] Property identifier. It can be one of the following: + * - CAP_PROP_POS_MSEC - Current position of the video file in milliseconds. + * - CAP_PROP_POS_FRAMES - 0-based index of the frame to be decoded/captured next. + * - CAP_PROP_POS_AVI_RATIO - Relative position of the video file: 0 - start of the film, 1 - end of the film. + * - CAP_PROP_FRAME_WIDTH - Width of the frames in the video stream. + * - CAP_PROP_FRAME_HEIGHT - Height of the frames in the video stream. + * - CAP_PROP_FPS - Frame rate. + * - CAP_PROP_FOURCC - 4-character code of codec. + * - CAP_PROP_FRAME_COUNT - Number of frames in the video file. + * - CAP_PROP_FORMAT - Format of the Mat objects returned by retrieve() . + * - CAP_PROP_MODE - Backend-specific value indicating the current capture mode. + * - CAP_PROP_BRIGHTNESS - Brightness of the image (only for cameras). + * - CAP_PROP_CONTRAST - Contrast of the image (only for cameras). + * - CAP_PROP_SATURATION - Saturation of the image (only for cameras). + * - CAP_PROP_HUE - Hue of the image (only for cameras). + * - CAP_PROP_GAIN - Gain of the image (only for cameras). + * - CAP_PROP_EXPOSURE - Exposure (only for cameras). + * - CAP_PROP_CONVERT_RGB - Boolean flags indicating whether images should be converted to RGB. + * - CAP_PROP_WHITE_BALANCE - Currently unsupported + * - CAP_PROP_RECTIFICATION - Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently) + * @param value [Number] Value of the property + * @return [Boolean] Result + * @opencv_func cv::VideoCapture::set + */ + VALUE rb_set(VALUE self, VALUE prop_id, VALUE value) { + cv::VideoCapture* selfptr = obj2videocapture(self); + double ret = 0; + try { + ret = selfptr->set(NUM2INT(prop_id), NUM2DBL(value)); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return ret ? Qtrue : Qfalse; + } + + /* + * 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 cv::VideCapture.grab + */ + VALUE rb_grab(VALUE self) { + cv::VideoCapture* selfptr = obj2videocapture(self); + bool ret = false; + try { + ret = selfptr->grab(); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return ret ? Qtrue : Qfalse; + } + + /* + * Decodes and returns the grabbed video frame. + * + * @overload retrieve + * @return [Mat] Grabbed video frame + * @return [nil] Failed to grabbing a frame + * @opencv_func cv::VideCapture::retrieve + */ + VALUE rb_retrieve(int argc, VALUE *argv, VALUE self) { + VALUE flag; + rb_scan_args(argc, argv, "01", &flag); + int flag_value = NIL_P(flag) ? 0 : NUM2INT(flag); + + cv::VideoCapture* selfptr = obj2videocapture(self); + bool ret = false; + cv::Mat* dstptr = Mat::empty_mat(); + try { + ret = selfptr->retrieve(*dstptr, flag_value); + if (!ret) { + delete dstptr; + } + } + catch (cv::Exception& e) { + delete dstptr; + Error::raise(e); + } + + return (ret) ? Mat::mat2obj(dstptr) : Qnil; + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "VideoCapture", rb_cData); + 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, "read", RUBY_METHOD_FUNC(rb_read), 0); + rb_define_method(rb_klass, "opened?", RUBY_METHOD_FUNC(rb_is_opened), 0); + rb_define_method(rb_klass, "get", RUBY_METHOD_FUNC(rb_get), 1); + rb_define_method(rb_klass, "set", RUBY_METHOD_FUNC(rb_set), 2); + rb_define_method(rb_klass, "grab", RUBY_METHOD_FUNC(rb_grab), 0); + rb_define_method(rb_klass, "retrieve", RUBY_METHOD_FUNC(rb_retrieve), -1); + } + } +} diff --git a/ext/opencv/window.cpp b/ext/opencv/window.cpp index 2acba7d..47ce09b 100644 --- a/ext/opencv/window.cpp +++ b/ext/opencv/window.cpp @@ -257,7 +257,7 @@ namespace rubyopencv { } void init() { - VALUE opencv = rb_define_module("OpenCV"); + VALUE opencv = rb_define_module("Cv"); rb_klass = rb_define_class_under(opencv, "Window", rb_cData); rb_define_alloc_func(rb_klass, rb_allocate); diff --git a/ext/opencv/window.cppe b/ext/opencv/window.cppe new file mode 100644 index 0000000..2acba7d --- /dev/null +++ b/ext/opencv/window.cppe @@ -0,0 +1,275 @@ +#include "opencv2/highgui.hpp" +#include "window.hpp" +#include "trackbar.hpp" +#include "error.hpp" +#include "mat.hpp" + +namespace rubyopencv { + namespace Window { + void mark_window(void *ptr); + void free_window(void *ptr); + + VALUE rb_klass; + rb_data_type_t opencv_window_type = { + "Window", + { mark_window, free_window, 0, 0 }, + 0, + 0, + 0 + }; + + void mark_window(void *ptr) { + window_t* window_ptr = (window_t*)ptr; + rb_gc_mark(window_ptr->name); + rb_gc_mark(window_ptr->trackbars); + } + + void free_window(void *ptr) { + xfree(ptr); + } + + VALUE rb_allocate(VALUE klass) { + window_t* ptr = NULL; + return TypedData_Make_Struct(klass, window_t, &opencv_window_type, ptr); + } + + window_t* obj2window(VALUE obj) { + window_t* ptr = NULL; + TypedData_Get_Struct(obj, window_t, &opencv_window_type, ptr); + return ptr; + } + + inline char* GET_WINDOW_NAME(VALUE obj) { + window_t* w = obj2window(obj); + return StringValueCStr(w->name); + } + + /* + * Creates a window. + * + * @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 cv::namedWindow + */ + VALUE rb_initialize(int argc, VALUE *argv, VALUE self) { + VALUE name, flags; + rb_scan_args(argc, argv, "11", &name, &flags); + Check_Type(name, T_STRING); + char* name_str = StringValueCStr(name); + if (cvGetWindowHandle(name_str) != NULL) { + rb_raise(rb_eStandardError, "window name should be unique."); + } + + int mode = CV_WINDOW_AUTOSIZE; + if (argc == 2) { + Check_Type(flags, T_FIXNUM); + mode = FIX2INT(flags); + } + + window_t* self_ptr = obj2window(self); + self_ptr->name = name; + self_ptr->trackbars = rb_ary_new(); + + try { + cv::namedWindow(name_str, mode); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + + /* + * Displays an image in the specified window. + * + * @overload show(image) + * @param image [Mat] Image to be shown. + * @opencv_func cv::imshow + */ + VALUE rb_show(VALUE self, VALUE img) { + try { + cv::Mat* m = Mat::obj2mat(img); + cv::imshow(GET_WINDOW_NAME(self), *m); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + + VALUE rb_wait_key(int argc, VALUE* argv, VALUE self) { + VALUE delay; + rb_scan_args(argc, argv, "01", &delay); + + int ret = 0; + int delay_value = NIL_P(delay) ? 0 : NUM2INT(delay); + try { + ret = cv::waitKey(delay_value); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return INT2NUM(ret); + } + + /* + * Destroys a window. alive status of window be false. + */ + VALUE + rb_destroy(VALUE self) { + try { + cv::destroyWindow(GET_WINDOW_NAME(self)); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return self; + } + + /* + * Destorys all the windows. + */ + VALUE rb_destroy_all(VALUE klass) { + try { + cv::destroyAllWindows(); + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return Qnil; + } + + /* + * Resizes window to the specified size. + * + * @overload resize(width, height) + * @param width [Integer] The new window width. + * @param height [Integer] The new window height. + * @opencv_func cv::resizeWindow + */ + VALUE rb_resize(VALUE self, VALUE width, VALUE height) { + try { + cv::resizeWindow(GET_WINDOW_NAME(self), NUM2INT(width), NUM2INT(height)); + } + catch (cv::Exception& e) { + Error::raise(e); + } + return self; + } + + /* + * Moves window to the specified position. + * + * @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(VALUE self, VALUE x, VALUE y) { + try { + cv::moveWindow(GET_WINDOW_NAME(self), NUM2INT(x), NUM2INT(y)); + } + catch (cv::Exception& e) { + Error::raise(e); + } + return self; + } + + void trackbar_callback(int value, void* block) { + rb_funcall((VALUE)block, rb_intern("call"), 1, INT2NUM(value)); + } + + /* + * Creates or sets a trackbar and attaches it to the specified window. + * + * @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) { + VALUE trackbar; + if (argc == 1) { + trackbar = argv[0]; + } + else { + trackbar = Trackbar::newobj(argc, argv); + } + Trackbar::trackbar_t *trackbar_ptr = Trackbar::obj2trackbar(trackbar); + try { + cv::TrackbarCallback callback = NULL; + void* block_ptr = NULL; + if (!NIL_P(trackbar_ptr->block)) { + block_ptr = (void*)(trackbar_ptr->block); + callback = (cv::TrackbarCallback)trackbar_callback; + } + cv::createTrackbar(trackbar_ptr->name, GET_WINDOW_NAME(self), &(trackbar_ptr->value), + trackbar_ptr->maxval, callback, block_ptr); + } + catch (cv::Exception& e) { + Error::raise(e); + } + rb_ary_push(obj2window(self)->trackbars, trackbar); + + return trackbar; + } + + void onMouse(int event, int x, int y, int flags, void* param) { + rb_funcall((VALUE)param, rb_intern("call"), 4, INT2FIX(event), INT2NUM(x), INT2NUM(y), INT2FIX(flags)); + } + + /* + * Sets mouse handler for the specified window. + * + * @overload set_mouse_callback { |event, x, y, flags| ... } + */ + VALUE rb_set_mouse_callback(int argc, VALUE* argv, VALUE self) { + window_t* selfptr = obj2window(self); + VALUE block = Qnil; + rb_scan_args(argc, argv, "0&", &block); + try { + if (rb_respond_to(block, rb_intern("call"))) { + cv::setMouseCallback(StringValueCStr(selfptr->name), onMouse, (void*)block); + } + } + catch (cv::Exception& e) { + Error::raise(e); + } + + return block; + } + + void init() { + VALUE opencv = rb_define_module("OpenCV"); + + rb_klass = rb_define_class_under(opencv, "Window", rb_cData); + 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, "show", RUBY_METHOD_FUNC(rb_show), 1); + 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), 2); + rb_define_method(rb_klass, "move", RUBY_METHOD_FUNC(rb_move), 2); + 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"); + } + } +} diff --git a/lib/opencv.rb b/lib/opencv.rb index 8a898c1..b81761d 100644 --- a/lib/opencv.rb +++ b/lib/opencv.rb @@ -3,4 +3,4 @@ require "opencv.so" require_relative "opencv/basic_structs" require_relative "opencv/cvmat" -Cv = OpenCV +OpenCV = Cv diff --git a/lib/opencv/basic_structs.rb b/lib/opencv/basic_structs.rb index 0d5d50e..aefc9e9 100644 --- a/lib/opencv/basic_structs.rb +++ b/lib/opencv/basic_structs.rb @@ -1,4 +1,4 @@ -module OpenCV +module Cv class CvScalar < Scalar; end class CvPoint < Point; end class CvRect < Rect; end diff --git a/lib/opencv/cvmat.rb b/lib/opencv/cvmat.rb index 1110975..afb8c91 100644 --- a/lib/opencv/cvmat.rb +++ b/lib/opencv/cvmat.rb @@ -1,4 +1,4 @@ -module OpenCV +module Cv class CvMat < Mat @@depth_table = { cv8u: CV_8U, diff --git a/lib/opencv/version.rb b/lib/opencv/version.rb index fe7eb35..0942f47 100644 --- a/lib/opencv/version.rb +++ b/lib/opencv/version.rb @@ -1,3 +1,3 @@ -module OpenCV +module Cv VERSION = '0.0.15' end diff --git a/ruby-opencv.gemspec b/ruby-opencv.gemspec index f42c8da..b47839e 100644 --- a/ruby-opencv.gemspec +++ b/ruby-opencv.gemspec @@ -5,7 +5,7 @@ require 'opencv/version' Gem::Specification.new do |spec| spec.name = "ruby-opencv" - spec.version = OpenCV::VERSION + spec.version = Cv::VERSION spec.authors = ["ser1zw"] spec.email = ["azariahsawtikes@gmail.com"] diff --git a/test/helper.rb b/test/helper.rb index 000fcc7..cced4d4 100755 --- a/test/helper.rb +++ b/test/helper.rb @@ -3,7 +3,7 @@ require 'test/unit' require 'digest/md5' require 'opencv' -include OpenCV +include Cv class OpenCVTestCase < Test::Unit::TestCase SAMPLE_DIR = File.expand_path(File.dirname(__FILE__)) + '/samples/' @@ -43,7 +43,7 @@ class OpenCVTestCase < Test::Unit::TestCase end } - OpenCV::wait_key + Cv::wait_key Window::destroy_all end diff --git a/test/legacy/test_cvmat.rb b/test/legacy/test_cvmat.rb index 9b2f85a..0f4ccba 100755 --- a/test/legacy/test_cvmat.rb +++ b/test/legacy/test_cvmat.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/../helper' -include OpenCV +include Cv -# Tests for OpenCV::CvMat +# Tests for Cv::CvMat module Legacy class TestCvMat < OpenCVTestCase def test_initialize @@ -179,7 +179,7 @@ module Legacy end def test_decode - data = OpenCV::imread(FILENAME_CAT, -1).imencode('.jpg') + data = Cv::imread(FILENAME_CAT, -1).imencode('.jpg') expected = CvMat.load(FILENAME_CAT) mat1 = CvMat.decode(data) diff --git a/test/legacy/test_cvmat.rbe b/test/legacy/test_cvmat.rbe new file mode 100755 index 0000000..08861d8 --- /dev/null +++ b/test/legacy/test_cvmat.rbe @@ -0,0 +1,213 @@ +#!/usr/bin/env ruby +# -*- mode: ruby; coding: utf-8 -*- +require 'test/unit' +require 'opencv' +require File.expand_path(File.dirname(__FILE__)) + '/../helper' + +include Cv + +# Tests for OpenCV::CvMat +module Legacy + class TestCvMat < OpenCVTestCase + def test_initialize + m = CvMat.new(10, 20) + assert_equal(10, m.rows) + assert_equal(20, m.cols) + assert_equal(:cv8u, m.depth) + assert_equal(3, m.channel) + + depth_table = { + CV_8U => :cv8u, + CV_8S => :cv8s, + CV_16U => :cv16u, + CV_16S => :cv16s, + CV_32S => :cv32s, + CV_32F => :cv32f, + CV_64F => :cv64f + } + + [CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F, + :cv8u, :cv8s, :cv16u, :cv16s, :cv32s, :cv32f, :cv64f].each { |depth| + [1, 2, 3, 4].each { |ch| + m = CvMat.new(10, 20, depth, ch) + assert_equal(10, m.rows) + assert_equal(20, m.cols) + depth = depth_table[depth] unless depth.is_a? Symbol + assert_equal(depth, m.depth) + assert_equal(ch, m.channel) + } + } + + assert_raise(TypeError) { + m = CvMat.new(DUMMY_OBJ, 20, :cv8u, 1) + } + assert_raise(TypeError) { + m = CvMat.new(10, DUMMY_OBJ, :cv8u, 1) + } + assert_raise(TypeError) { + m = CvMat.new(10, 20, :cv8u, DUMMY_OBJ) + } + end + + def test_load + mat = CvMat.load(FILENAME_CAT) + assert_equal(CvMat, mat.class) + assert_equal(375, mat.cols) + assert_equal(500, mat.rows) + assert_equal(:cv8u, mat.depth) + assert_equal(3, mat.channel) + + mat = CvMat.load(FILENAME_CAT, CV_LOAD_IMAGE_GRAYSCALE) + assert_equal(CvMat, mat.class) + assert_equal(375, mat.cols) + assert_equal(500, mat.rows) + assert_equal(:cv8u, mat.depth) + assert_equal(1, mat.channel) + + mat = CvMat.load(FILENAME_CAT, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR) + assert_equal(CvMat, mat.class) + assert_equal(375, mat.cols) + assert_equal(500, mat.rows) + assert_equal(:cv8u, mat.depth) + assert_equal(3, mat.channel) + + assert_raise(ArgumentError) { + CvMat.load + } + assert_raise(TypeError) { + CvMat.load(DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.load(FILENAME_CAT, DUMMY_OBJ) + } + assert_raise(StandardError) { + CvMat.load('file/does/not/exist') + } + end + + def test_save_image + filename_jpg = 'save_image_test.jpg' + filename_png = 'save_image_test.png' + m = CvMat.new(20, 20, :cv8u, 1) + + File.delete filename_jpg if File.exists? filename_jpg + m.save_image filename_jpg + assert(File.exists? filename_jpg) + + File.delete filename_jpg if File.exists? filename_jpg + m.save_image(filename_jpg, CV_IMWRITE_JPEG_QUALITY => 10) + assert(File.exists? filename_jpg) + + File.delete filename_png if File.exists? filename_png + m.save_image(filename_png, CV_IMWRITE_PNG_COMPRESSION => 9) + assert(File.exists? filename_png) + + # Alias + File.delete filename_jpg if File.exists? filename_jpg + m.save filename_jpg + assert(File.exists? filename_jpg) + + assert_raise(TypeError) { + m.save_image(DUMMY_OBJ) + } + assert_raise(TypeError) { + m.save_image(filename_jpg, DUMMY_OBJ) + } + + File.delete filename_jpg if File.exists? filename_jpg + File.delete filename_png if File.exists? filename_png + end + + def test_add_weighted + m1 = create_cvmat(3, 2, :cv8u) { |j, i, c| CvScalar.new(c + 1) } + m2 = create_cvmat(3, 2, :cv8u) { |j, i, c| CvScalar.new((c + 1) * 10) } + a = 2.0 + b = 0.1 + g = 100 + m3 = CvMat.add_weighted(m1, a, m2, b, g) + assert_equal(m1.class, m3.class) + assert_equal(m1.rows, m3.rows) + assert_equal(m1.cols, m3.cols) + assert_equal(m1.depth, m3.depth) + assert_equal(m1.channel, m3.channel) + + m1.rows.times { |j| + m1.cols.times { |i| + expected = m1[j, i][0] * a + m2[j, i][0] * b + g + assert_equal(expected, m3[j, i][0]) + } + } + + assert_raise(TypeError) { + CvMat.add_weighted(DUMMY_OBJ, a, m2, b, g) + } + assert_raise(TypeError) { + CvMat.add_weighted(m1, DUMMY_OBJ, m2, b, g) + } + assert_raise(TypeError) { + CvMat.add_weighted(m1, a, DUMMY_OBJ, b, g) + } + assert_raise(TypeError) { + CvMat.add_weighted(m1, a, m2, DUMMY_OBJ, g) + } + assert_raise(TypeError) { + CvMat.add_weighted(m1, a, m2, b, DUMMY_OBJ) + } + end + + def test_encode + mat = CvMat.load(FILENAME_CAT); + + jpg = mat.encode('.jpg') + assert_equal('JFIF', jpg[6, 4].map(&:chr).join) # Is jpeg format? + + jpg = mat.encode('.jpg', CV_IMWRITE_JPEG_QUALITY => 10) + assert_equal('JFIF', jpg[6, 4].map(&:chr).join) + + png = mat.encode('.png') + assert_equal('PNG', png[1, 3].map(&:chr).join) # Is png format? + + png = mat.encode('.png', CV_IMWRITE_PNG_COMPRESSION => 9) + assert_equal('PNG', png[1, 3].map(&:chr).join) + + assert_raise(TypeError) { + mat.encode(DUMMY_OBJ) + } + assert_raise(TypeError) { + mat.encode('.jpg', DUMMY_OBJ) + } + end + + def test_decode + data = OpenCV::imread(FILENAME_CAT, -1).imencode('.jpg') + expected = CvMat.load(FILENAME_CAT) + + mat1 = CvMat.decode(data) + mat2 = CvMat.decode(data, CV_LOAD_IMAGE_COLOR) + + [mat1, mat2].each { |mat| + assert_equal(CvMat, mat.class) + assert_equal(expected.rows, mat.rows) + assert_equal(expected.cols, mat.cols) + assert_equal(expected.channel, mat.channel) + } + + expected_c1 = CvMat.load(FILENAME_CAT, CV_LOAD_IMAGE_GRAYSCALE) + mat1c1 = CvMat.decode(data, CV_LOAD_IMAGE_GRAYSCALE) + + [mat1c1].each { |mat| + assert_equal(CvMat, mat.class) + assert_equal(expected_c1.rows, mat.rows) + assert_equal(expected_c1.cols, mat.cols) + assert_equal(expected_c1.channel, mat.channel) + } + + assert_raise(TypeError) { + CvMat.decode(DUMMY_OBJ) + } + assert_raise(TypeError) { + CvMat.decode(data, DUMMY_OBJ) + } + end + end +end diff --git a/test/legacy/test_cvmat_imageprocessing.rb b/test/legacy/test_cvmat_imageprocessing.rb index 3a68925..9158fa9 100755 --- a/test/legacy/test_cvmat_imageprocessing.rb +++ b/test/legacy/test_cvmat_imageprocessing.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/../helper' -include OpenCV +include Cv -# Tests for image processing functions of OpenCV::CvMat +# Tests for image processing functions of Cv::CvMat module Legacy class TestCvMat_imageprocessing < OpenCVTestCase DEPTH = [:cv8u, :cv8s, :cv16u, :cv16s, :cv32s, :cv32f, :cv64f] @@ -24,7 +24,7 @@ module Legacy assert_equal(:cv32f, CvMat.new(16, 16, :cv32f, 1).sobel(1, 1).depth) (DEPTH - [:cv8u, :cv16u, :cv16s, :cv32f]).each { |depth| - assert_raise(OpenCV::Error::StsNotImplemented) { + assert_raise(Cv::Error::StsNotImplemented) { CvMat.new(3, 3, depth).sobel(1, 1) } } @@ -51,11 +51,11 @@ module Legacy assert_equal(:cv32f, CvMat.new(16, 16, :cv32f, 1).laplace.depth) (DEPTH - [:cv8u, :cv16u, :cv16s, :cv32f, :cv64f]).each { |depth| - assert_raise(OpenCV::Error::StsNotImplemented) { + assert_raise(Cv::Error::StsNotImplemented) { CvMat.new(3, 3, depth).laplace } } - assert_raise(OpenCV::Error::StsAssert) { + assert_raise(Cv::Error::StsAssert) { CvMat.new(3, 3, :cv64f).laplace } diff --git a/test/legacy/test_cvmat_imageprocessing.rbe b/test/legacy/test_cvmat_imageprocessing.rbe new file mode 100755 index 0000000..53b4ac9 --- /dev/null +++ b/test/legacy/test_cvmat_imageprocessing.rbe @@ -0,0 +1,84 @@ +#!/usr/bin/env ruby +# -*- mode: ruby; coding: utf-8 -*- +require 'test/unit' +require 'opencv' +require File.expand_path(File.dirname(__FILE__)) + '/../helper' + +include Cv + +# Tests for image processing functions of OpenCV::CvMat +module Legacy + class TestCvMat_imageprocessing < OpenCVTestCase + DEPTH = [:cv8u, :cv8s, :cv16u, :cv16s, :cv32s, :cv32f, :cv64f] + + def test_sobel + mat0 = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE) + + mat1 = mat0.sobel(1, 0).convert_scale_abs(:scale => 1, :shift => 0) + mat2 = mat0.sobel(0, 1).convert_scale_abs(:scale => 1, :shift => 0) + mat3 = mat0.sobel(1, 1).convert_scale_abs(:scale => 1, :shift => 0) + mat4 = mat0.sobel(1, 1, 3).convert_scale_abs(:scale => 1, :shift => 0) + mat5 = mat0.sobel(1, 1, 5).convert_scale_abs(:scale => 1, :shift => 0) + + assert_equal(:cv16s, CvMat.new(16, 16, :cv8u, 1).sobel(1, 1).depth) + assert_equal(:cv32f, CvMat.new(16, 16, :cv32f, 1).sobel(1, 1).depth) + + (DEPTH - [:cv8u, :cv16u, :cv16s, :cv32f]).each { |depth| + assert_raise(OpenCV::Error::StsNotImplemented) { + CvMat.new(3, 3, depth).sobel(1, 1) + } + } + + assert_raise(TypeError) { + mat0.sobel(DUMMY_OBJ, 0) + } + assert_raise(TypeError) { + mat0.sobel(1, DUMMY_OBJ) + } + assert_raise(TypeError) { + mat0.sobel(1, 0, DUMMY_OBJ) + } + end + + def test_laplace + mat0 = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE) + + mat1 = mat0.laplace.convert_scale_abs(:scale => 1, :shift => 0) + mat2 = mat0.laplace(3).convert_scale_abs(:scale => 1, :shift => 0) + mat3 = mat0.laplace(5).convert_scale_abs(:scale => 1, :shift => 0) + + assert_equal(:cv16s, CvMat.new(16, 16, :cv8u, 1).laplace.depth) + assert_equal(:cv32f, CvMat.new(16, 16, :cv32f, 1).laplace.depth) + + (DEPTH - [:cv8u, :cv16u, :cv16s, :cv32f, :cv64f]).each { |depth| + assert_raise(OpenCV::Error::StsNotImplemented) { + CvMat.new(3, 3, depth).laplace + } + } + assert_raise(OpenCV::Error::StsAssert) { + CvMat.new(3, 3, :cv64f).laplace + } + + assert_raise(TypeError) { + mat0.laplace(DUMMY_OBJ) + } + end + + def test_canny + mat0 = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE) + mat1 = mat0.canny(50, 200) + mat2 = mat0.canny(50, 200, 3) + mat3 = mat0.canny(50, 200, 5) + + assert_raise(TypeError) { + mat0.canny(DUMMY_OBJ, 200) + } + assert_raise(TypeError) { + mat0.canny(50, DUMMY_OBJ) + } + assert_raise(TypeError) { + mat0.canny(50, 200, DUMMY_OBJ) + } + end + end +end diff --git a/test/test_cascadeclassifier.rb b/test/test_cascadeclassifier.rb index 7e271bf..eaf3505 100755 --- a/test/test_cascadeclassifier.rb +++ b/test/test_cascadeclassifier.rb @@ -3,7 +3,7 @@ require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv class TestCascadeClassifier < OpenCVTestCase def test_initialize @@ -34,7 +34,7 @@ class TestCascadeClassifier < OpenCVTestCase def test_detect_multi_scale c = CascadeClassifier.new(HAARCASCADE_FRONTALFACE_ALT) - m = OpenCV::imread(FILENAME_GIRLS_PLAY_AND_PLANT_FLOWERS_IN_THE_PARK, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) + m = Cv::imread(FILENAME_GIRLS_PLAY_AND_PLANT_FLOWERS_IN_THE_PARK, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) rects = c.detect_multi_scale(m) assert_equal(3, rects.size) diff --git a/test/test_mat.rb b/test/test_mat.rb index fb97d5c..47dc064 100755 --- a/test/test_mat.rb +++ b/test/test_mat.rb @@ -3,7 +3,7 @@ require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv class TestMat < OpenCVTestCase DEPTH = [CV_8U, CV_8S, CV_16U, CV_16S, CV_32F, CV_32S, CV_64F] @@ -20,7 +20,7 @@ class TestMat < OpenCVTestCase [CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F].each { |depth| [1, 2, 3, 4].each { |channel| - type = OpenCV::CV_MAKETYPE(depth, channel) + type = Cv::CV_MAKETYPE(depth, channel) m = Mat.new(10, 20, type) assert_equal(10, m.rows) assert_equal(20, m.cols) @@ -60,7 +60,7 @@ class TestMat < OpenCVTestCase # Alias File.delete filename_jpg if File.exists? filename_jpg - OpenCV::imwrite(filename_jpg, m) + Cv::imwrite(filename_jpg, m) assert(File.exists? filename_jpg) assert_raise(TypeError) { @@ -163,7 +163,7 @@ class TestMat < OpenCVTestCase } DEPTH.each { |depth| (1..4).each { |channel| - m = Mat.eye(3, 3, OpenCV::CV_MAKETYPE(depth, channel)) + m = Mat.eye(3, 3, Cv::CV_MAKETYPE(depth, channel)) 0.upto(m.rows - 1) { |r| 0.upto(m.cols - 1) { |c| s = m[r, c] @@ -192,7 +192,7 @@ class TestMat < OpenCVTestCase } DEPTH.each { |depth| (1..4).each { |channel| - type = OpenCV::CV_MAKETYPE(depth, channel) + type = Cv::CV_MAKETYPE(depth, channel) m = Mat.zeros(3, 3, type) 0.upto(m.rows - 1) { |r| 0.upto(m.cols - 1) { |c| @@ -364,18 +364,18 @@ class TestMat < OpenCVTestCase end def test_imencode - m = OpenCV::imread(FILENAME_LENA32x32, -1) + m = Cv::imread(FILENAME_LENA32x32, -1) results = [] results << m.imencode('.jpg') - results << m.imencode('.jpg', [OpenCV::IMWRITE_JPEG_QUALITY, 10]) + results << m.imencode('.jpg', [Cv::IMWRITE_JPEG_QUALITY, 10]) results.each { |jpg| assert_equal('JFIF', jpg[6, 4].map(&:chr).join) } results = [] results << m.imencode('.png') - results << m.imencode('.png', [OpenCV::IMWRITE_PNG_COMPRESSION, 9]) + results << m.imencode('.png', [Cv::IMWRITE_PNG_COMPRESSION, 9]) results.each { |png| assert_equal('PNG', png[1, 3].map(&:chr).join) } @@ -393,7 +393,7 @@ class TestMat < OpenCVTestCase s1 = Scalar.new(1, 1, 1, 1) DEPTH.each { |depth| (1..4).each { |channel| - type = OpenCV::CV_MAKETYPE(depth, channel) + type = Cv::CV_MAKETYPE(depth, channel) m = Mat::zeros(3, 3, type) a = m.set_to(s1) @@ -423,7 +423,7 @@ class TestMat < OpenCVTestCase } DEPTH.each { |depth| (1..4).each { |channel| - type = OpenCV::CV_MAKETYPE(depth, channel) + type = Cv::CV_MAKETYPE(depth, channel) m = Mat::zeros(3, 3, type) a = m.set_to(s1, mask) diff --git a/test/test_mat_imgproc.rb b/test/test_mat_imgproc.rb index 42fadce..1a1c316 100755 --- a/test/test_mat_imgproc.rb +++ b/test/test_mat_imgproc.rb @@ -3,11 +3,11 @@ require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv class TestCvMat < OpenCVTestCase def test_sobel - m0 = OpenCV::imread(FILENAME_LENA256x256, 0) + m0 = Cv::imread(FILENAME_LENA256x256, 0) sobel = [] sobel << m0.sobel(CV_32F, 1, 1) @@ -44,11 +44,11 @@ class TestCvMat < OpenCVTestCase # w = Window.new('Sobel') # w.show(m0.sobel(CV_32F, 1, 1)) - # OpenCV::wait_key + # Cv::wait_key end def test_canny - m0 = OpenCV::imread(FILENAME_LENA256x256, 0) + m0 = Cv::imread(FILENAME_LENA256x256, 0) canny = [] canny << m0.canny(50, 200) @@ -76,11 +76,11 @@ class TestCvMat < OpenCVTestCase # w = Window.new('Canny') # w.show(m0.canny(50, 200)) - # OpenCV::wait_key + # Cv::wait_key end def test_laplacian - m0 = OpenCV::imread(FILENAME_LENA256x256, 0) + m0 = Cv::imread(FILENAME_LENA256x256, 0) laplacian = [] laplacian << m0.laplacian(CV_32F) @@ -111,7 +111,7 @@ class TestCvMat < OpenCVTestCase # w = Window.new('Laplacian') # w.show(m0.laplacian(CV_32F)) - # OpenCV::wait_key + # Cv::wait_key end def test_add_weighted @@ -119,8 +119,8 @@ class TestCvMat < OpenCVTestCase m1 = Mat.ones(3, 3, CV_32F) * 64 results = [] - results << OpenCV::add_weighted(m0, 0.5, m1, 0.5, 0) - results << OpenCV::add_weighted(m0, 0.5, m1, 0.5, 32, CV_32F) + results << Cv::add_weighted(m0, 0.5, m1, 0.5, 0) + results << Cv::add_weighted(m0, 0.5, m1, 0.5, 32, CV_32F) results.each { |m| assert_equal(m0.rows, m.rows) assert_equal(m0.cols, m.cols) @@ -130,22 +130,22 @@ class TestCvMat < OpenCVTestCase } assert_raise(TypeError) { - OpenCV::add_weighted(DUMMY_OBJ, 0.5, m1, 0.5, 32, CV_32F) + Cv::add_weighted(DUMMY_OBJ, 0.5, m1, 0.5, 32, CV_32F) } assert_raise(TypeError) { - OpenCV::add_weighted(m0, DUMMY_OBJ, m1, 0.5, 32, CV_32F) + Cv::add_weighted(m0, DUMMY_OBJ, m1, 0.5, 32, CV_32F) } assert_raise(TypeError) { - OpenCV::add_weighted(m0, 0.5, DUMMY_OBJ, 0.5, 32, CV_32F) + Cv::add_weighted(m0, 0.5, DUMMY_OBJ, 0.5, 32, CV_32F) } assert_raise(TypeError) { - OpenCV::add_weighted(m0, 0.5, m1, DUMMY_OBJ, 32, CV_32F) + Cv::add_weighted(m0, 0.5, m1, DUMMY_OBJ, 32, CV_32F) } assert_raise(TypeError) { - OpenCV::add_weighted(m0, 0.5, m1, 0.5, DUMMY_OBJ, CV_32F) + Cv::add_weighted(m0, 0.5, m1, 0.5, DUMMY_OBJ, CV_32F) } assert_raise(TypeError) { - OpenCV::add_weighted(m0, 0.5, m1, 0.5, 32, DUMMY_OBJ) + Cv::add_weighted(m0, 0.5, m1, 0.5, 32, DUMMY_OBJ) } end end diff --git a/test/test_opencv.rb b/test/test_opencv.rb index a329918..1ef5679 100755 --- a/test/test_opencv.rb +++ b/test/test_opencv.rb @@ -3,18 +3,18 @@ require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv class TestOpenCV < OpenCVTestCase def test_imread - mat = OpenCV::imread(FILENAME_CAT, IMREAD_GRAYSCALE) + mat = Cv::imread(FILENAME_CAT, IMREAD_GRAYSCALE) assert_equal(Mat, mat.class) assert_equal(375, mat.cols) assert_equal(500, mat.rows) assert_equal(CV_8U, mat.depth) assert_equal(1, mat.channels) - mat = OpenCV::imread(FILENAME_CAT, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) + mat = Cv::imread(FILENAME_CAT, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) assert_equal(Mat, mat.class) assert_equal(375, mat.cols) assert_equal(500, mat.rows) @@ -22,31 +22,31 @@ class TestOpenCV < OpenCVTestCase assert_equal(3, mat.channels) assert_raise(ArgumentError) { - OpenCV::imread + Cv::imread } assert_raise(ArgumentError) { - OpenCV::imread(FILENAME_CAT) + Cv::imread(FILENAME_CAT) } assert_raise(TypeError) { - OpenCV::imread(FILENAME_CAT, DUMMY_OBJ) + Cv::imread(FILENAME_CAT, DUMMY_OBJ) } assert_raise(StandardError) { - OpenCV::imread('file/does/not/exist', 0) + Cv::imread('file/does/not/exist', 0) } end def test_imdecode - src = OpenCV::imread(FILENAME_LENA32x32, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) + src = Cv::imread(FILENAME_LENA32x32, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) buf = src.imencode('.jpg') - m = OpenCV::imdecode(buf, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) + m = Cv::imdecode(buf, IMREAD_ANYDEPTH | IMREAD_ANYCOLOR) assert_equal(src.class, m.class) assert_equal(src.rows, m.rows) assert_equal(src.cols, m.cols) assert_equal(src.depth, m.depth) assert_equal(src.channels, m.channels) - m = OpenCV::imdecode(buf, IMREAD_GRAYSCALE) + m = Cv::imdecode(buf, IMREAD_GRAYSCALE) assert_equal(src.class, m.class) assert_equal(src.rows, m.rows) assert_equal(src.cols, m.cols) @@ -54,10 +54,10 @@ class TestOpenCV < OpenCVTestCase assert_equal(1, m.channels) assert_raise(TypeError) { - OpenCV::imdecode(DUMMY_OBJ, IMREAD_GRAYSCALE) + Cv::imdecode(DUMMY_OBJ, IMREAD_GRAYSCALE) } assert_raise(TypeError) { - OpenCV::imdecode(buf, DUMMY_OBJ) + Cv::imdecode(buf, DUMMY_OBJ) } # w = Window.new('Decoded') diff --git a/test/test_point.rb b/test/test_point.rb index 7e7c948..4010988 100755 --- a/test/test_point.rb +++ b/test/test_point.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv -# Tests for OpenCV::Point +# Tests for Cv::Point class TestPoint < OpenCVTestCase def test_x point = Point.new @@ -61,7 +61,7 @@ class TestPoint < OpenCVTestCase def test_to_s point = Point.new(10, 20) - assert_equal('#', point.to_s) + assert_equal('#', point.to_s) end def test_to_a diff --git a/test/test_rect.rb b/test/test_rect.rb index f04e17b..fdcf136 100755 --- a/test/test_rect.rb +++ b/test/test_rect.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv -# Tests for OpenCV::Rect +# Tests for Cv::Rect class TestRect < OpenCVTestCase def test_x rect = Rect.new @@ -81,6 +81,6 @@ class TestRect < OpenCVTestCase def test_to_s rect = Rect.new(1, 2, 3, 4) - assert_equal('#', rect.to_s) + assert_equal('#', rect.to_s) end end diff --git a/test/test_scalar.rb b/test/test_scalar.rb index 9869021..26a8597 100755 --- a/test/test_scalar.rb +++ b/test/test_scalar.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv -# Tests for OpenCV::Scalar +# Tests for Cv::Scalar class TestScalar < OpenCVTestCase def test_initialize s = Scalar.new @@ -46,8 +46,8 @@ class TestScalar < OpenCVTestCase end def test_to_s - assert_equal('#', Scalar.new(10, 20, 30, 40).to_s) - assert_equal('#', Scalar.new(0.1, 0.2, 0.3, 0.4).to_s) + assert_equal('#', Scalar.new(10, 20, 30, 40).to_s) + assert_equal('#', Scalar.new(0.1, 0.2, 0.3, 0.4).to_s) end def test_to_ary diff --git a/test/test_size.rb b/test/test_size.rb index f60943d..3527a0e 100755 --- a/test/test_size.rb +++ b/test/test_size.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv -# Tests for OpenCV::Size +# Tests for Cv::Size class TestSize < OpenCVTestCase def test_width size = Size.new @@ -49,6 +49,6 @@ class TestSize < OpenCVTestCase def test_to_s size = Size.new(10, 20) - assert_equal('#', size.to_s) + assert_equal('#', size.to_s) end end diff --git a/test/test_videocapture.rb b/test/test_videocapture.rb index 118d800..df3bd9c 100755 --- a/test/test_videocapture.rb +++ b/test/test_videocapture.rb @@ -4,9 +4,9 @@ require 'test/unit' require 'opencv' require File.expand_path(File.dirname(__FILE__)) + '/helper' -include OpenCV +include Cv -# Tests for OpenCV::VideoCapture +# Tests for Cv::VideoCapture class TestVideoCapture < OpenCVTestCase def setup @cap = VideoCapture.new(AVI_SAMPLE)