2008-08-19 11:01:28 -04:00
|
|
|
|
/************************************************************
|
|
|
|
|
|
|
|
|
|
cvmat.cpp -
|
|
|
|
|
|
|
|
|
|
$Author: lsxi $
|
|
|
|
|
|
|
|
|
|
Copyright (C) 2005-2008 Masakazu Yonekura
|
|
|
|
|
|
|
|
|
|
************************************************************/
|
|
|
|
|
#include "cvmat.h"
|
|
|
|
|
/*
|
|
|
|
|
* Document-class: OpenCV::CvMat
|
|
|
|
|
*
|
|
|
|
|
* CvMat is basic 2D matrix class in OpenCV.
|
|
|
|
|
*
|
|
|
|
|
* C structure is here.
|
|
|
|
|
* typedef struct CvMat{
|
|
|
|
|
* int type;
|
|
|
|
|
* int step;
|
|
|
|
|
* int *refcount;
|
|
|
|
|
* union
|
|
|
|
|
* {
|
|
|
|
|
* uchar *ptr;
|
|
|
|
|
* short *s;
|
|
|
|
|
* int *i;
|
|
|
|
|
* float *fl;
|
|
|
|
|
* double *db;
|
|
|
|
|
* } data;
|
|
|
|
|
* #ifdef __cplusplus
|
|
|
|
|
* union
|
|
|
|
|
* {
|
|
|
|
|
* int rows;
|
|
|
|
|
* int height;
|
|
|
|
|
* };
|
|
|
|
|
* union
|
|
|
|
|
* {
|
|
|
|
|
* int cols;
|
|
|
|
|
* int width;
|
|
|
|
|
* };
|
|
|
|
|
* #else
|
|
|
|
|
* int rows; // number of row
|
|
|
|
|
* int cols; // number of columns
|
|
|
|
|
* }CvMat;
|
|
|
|
|
*/
|
|
|
|
|
__NAMESPACE_BEGIN_OPENCV
|
|
|
|
|
__NAMESPACE_BEGIN_CVMAT
|
|
|
|
|
|
|
|
|
|
#define SUPPORT_8UC1_ONLY(value) if (cvGetElemType(CVARR(value)) != CV_8UC1) {rb_raise(rb_eNotImpError, "support single-channel 8bit unsigned image only.");}
|
|
|
|
|
#define SUPPORT_8U_ONLY(value) if (CV_MAT_DEPTH(cvGetElemType(CVARR(value))) != CV_8U) {rb_raise(rb_eNotImpError, "support 8bit unsigned image only.");}
|
|
|
|
|
#define SUPPORT_C1_ONLY(value) if (CV_MAT_CN(cvGetElemType(CVARR(value))) != 1) {rb_raise(rb_eNotImpError, "support single-channel image only.");}
|
|
|
|
|
#define SUPPORT_C1C3_ONLY(value) if (CV_MAT_CN(cvGetElemType(CVARR(value))) != 1 && CV_MAT_CN(cvGetElemType(CVARR(value))) != 3) {rb_raise(rb_eNotImpError, "support single-channel or 3-channnel image only.");}
|
|
|
|
|
|
|
|
|
|
#define DRAWING_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("DRAWING_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("DRAWING_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define DO_COLOR(op) VALUE_TO_CVSCALAR(rb_hash_aref(op, ID2SYM(rb_intern("color"))))
|
|
|
|
|
#define DO_THICKNESS(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("thickness"))))
|
|
|
|
|
#define DO_LINE_TYPE(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("line_type"))) == ID2SYM("aa") ? INT2FIX(CV_AA) : rb_hash_aref(op, ID2SYM(rb_intern("line_type"))))
|
|
|
|
|
#define DO_SHIFT(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("shift"))))
|
|
|
|
|
#define DO_IS_CLOSED(op) ({VALUE _is_closed = rb_hash_aref(op, ID2SYM(rb_intern("is_closed"))); NIL_P(_is_closed) ? 0 : _is_closed == Qfalse ? 0 : 1;})
|
|
|
|
|
|
|
|
|
|
#define GOOD_FEATURES_TO_TRACK_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("GOOD_FEATURES_TO_TRACK_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("GOOD_FEATURES_TO_TRACK_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define GF_MAX(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("max"))))
|
|
|
|
|
#define GF_MASK(op) MASK(rb_hash_aref(op, ID2SYM(rb_intern("mask"))))
|
|
|
|
|
#define GF_BLOCK_SIZE(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("block_size"))))
|
|
|
|
|
#define GF_USE_HARRIS(op) TRUE_OR_FALSE(rb_hash_aref(op, ID2SYM(rb_intern("use_harris"))), 0)
|
|
|
|
|
#define GF_K(op) NUM2DBL(rb_hash_aref(op, ID2SYM(rb_intern("k"))))
|
|
|
|
|
|
|
|
|
|
#define FLOOD_FILL_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("FLOOD_FILL_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("FLOOD_FILL_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define FF_CONNECTIVITY(op) NUM2INT(rb_hash_aref(op, ID2SYM(rb_intern("connectivity"))))
|
|
|
|
|
#define FF_FIXED_RANGE(op) TRUE_OR_FALSE(rb_hash_aref(op, ID2SYM(rb_intern("fixed_range"))), 0)
|
|
|
|
|
#define FF_MASK_ONLY(op) TRUE_OR_FALSE(rb_hash_aref(op, ID2SYM(rb_intern("mask_only"))), 0)
|
|
|
|
|
|
|
|
|
|
#define FIND_CONTOURS_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("FIND_CONTOURS_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("FIND_CONTOURS_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define FC_MODE(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("mode"))))
|
|
|
|
|
#define FC_METHOD(op) FIX2INT(rb_hash_aref(op, ID2SYM(rb_intern("method"))))
|
|
|
|
|
#define FC_OFFSET(op)VALUE_TO_CVPOINT(rb_hash_aref(op, ID2SYM(rb_intern("offset"))))
|
|
|
|
|
|
|
|
|
|
#define OPTICAL_FLOW_HS_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("OPTICAL_FLOW_HS_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("OPTICAL_FLOW_HS_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define HS_LAMBDA(op) NUM2DBL(rb_hash_aref(op, ID2SYM(rb_intern("lambda"))))
|
|
|
|
|
#define HS_CRITERIA(op) VALUE_TO_CVTERMCRITERIA(rb_hash_aref(op, ID2SYM(rb_intern("criteria"))))
|
|
|
|
|
|
|
|
|
|
#define OPTICAL_FLOW_BM_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("OPTICAL_FLOW_BM_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("OPTICAL_FLOW_BM_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define BM_BLOCK_SIZE(op) VALUE_TO_CVSIZE(rb_hash_aref(op, ID2SYM(rb_intern("block_size"))))
|
|
|
|
|
#define BM_SHIFT_SIZE(op) VALUE_TO_CVSIZE(rb_hash_aref(op, ID2SYM(rb_intern("shift_size"))))
|
|
|
|
|
#define BM_MAX_RANGE(op) VALUE_TO_CVSIZE(rb_hash_aref(op, ID2SYM(rb_intern("max_range"))))
|
|
|
|
|
|
|
|
|
|
#define FIND_FUNDAMENTAL_MAT_OPTION(op) NIL_P(op) ? rb_const_get(rb_class(), rb_intern("FIND_FUNDAMENTAL_MAT_OPTION")) : rb_funcall(rb_const_get(rb_class(), rb_intern("FIND_FUNDAMENTAL_MAT_OPTION")), rb_intern("merge"), 1, op)
|
|
|
|
|
#define FFM_WITH_STATUS(op) TRUE_OR_FALSE(rb_hash_aref(op, ID2SYM(rb_intern("with_status"))), 0)
|
|
|
|
|
#define FFM_MAXIMUM_DISTANCE(op) NUM2DBL(rb_hash_aref(op, ID2SYM(rb_intern("maximum_distance"))))
|
|
|
|
|
#define FFM_DESIRABLE_LEVEL(op) NUM2DBL(rb_hash_aref(op, ID2SYM(rb_intern("desirable_level"))))
|
|
|
|
|
|
|
|
|
|
VALUE rb_klass;
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
rb_class()
|
|
|
|
|
{
|
|
|
|
|
return rb_klass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void define_ruby_class()
|
|
|
|
|
{
|
|
|
|
|
if (rb_klass)
|
|
|
|
|
return;
|
|
|
|
|
/*
|
|
|
|
|
* opencv = rb_define_module("OpenCV");
|
|
|
|
|
*
|
|
|
|
|
* note: this comment is used by rdoc.
|
|
|
|
|
*/
|
|
|
|
|
VALUE opencv = rb_module_opencv();
|
|
|
|
|
|
|
|
|
|
rb_klass = rb_define_class_under(opencv, "CvMat", rb_cObject);
|
|
|
|
|
rb_define_alloc_func(rb_klass, rb_allocate);
|
|
|
|
|
|
|
|
|
|
VALUE drawing_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "DRAWING_OPTION", drawing_option);
|
|
|
|
|
rb_hash_aset(drawing_option, ID2SYM(rb_intern("color")), cCvScalar::new_object(cvScalarAll(0)));
|
|
|
|
|
rb_hash_aset(drawing_option, ID2SYM(rb_intern("thickness")), INT2FIX(1));
|
|
|
|
|
rb_hash_aset(drawing_option, ID2SYM(rb_intern("line_type")), INT2FIX(8));
|
|
|
|
|
rb_hash_aset(drawing_option, ID2SYM(rb_intern("shift")), INT2FIX(0));
|
|
|
|
|
|
|
|
|
|
VALUE good_features_to_track_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "GOOD_FEATURES_TO_TRACK_OPTION", good_features_to_track_option);
|
|
|
|
|
rb_hash_aset(good_features_to_track_option, ID2SYM(rb_intern("max")), INT2FIX(0xFF));
|
|
|
|
|
rb_hash_aset(good_features_to_track_option, ID2SYM(rb_intern("mask")), Qnil);
|
|
|
|
|
rb_hash_aset(good_features_to_track_option, ID2SYM(rb_intern("block_size")), INT2FIX(3));
|
|
|
|
|
rb_hash_aset(good_features_to_track_option, ID2SYM(rb_intern("use_harris")), Qfalse);
|
|
|
|
|
rb_hash_aset(good_features_to_track_option, ID2SYM(rb_intern("k")), rb_float_new(0.04));
|
|
|
|
|
|
|
|
|
|
VALUE flood_fill_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "FLOOD_FILL_OPTION", flood_fill_option);
|
|
|
|
|
rb_hash_aset(flood_fill_option, ID2SYM(rb_intern("connectivity")), INT2FIX(4));
|
|
|
|
|
rb_hash_aset(flood_fill_option, ID2SYM(rb_intern("fixed_range")), Qfalse);
|
|
|
|
|
rb_hash_aset(flood_fill_option, ID2SYM(rb_intern("mask_only")), Qfalse);
|
|
|
|
|
|
|
|
|
|
VALUE find_contours_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "FIND_CONTOURS_OPTION", find_contours_option);
|
|
|
|
|
rb_hash_aset(find_contours_option, ID2SYM(rb_intern("mode")), INT2FIX(CV_RETR_LIST));
|
|
|
|
|
rb_hash_aset(find_contours_option, ID2SYM(rb_intern("method")), INT2FIX(CV_CHAIN_APPROX_SIMPLE));
|
|
|
|
|
rb_hash_aset(find_contours_option, ID2SYM(rb_intern("offset")), cCvPoint::new_object(cvPoint(0,0)));
|
|
|
|
|
|
|
|
|
|
VALUE optical_flow_hs_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "OPTICAL_FLOW_HS_OPTION", optical_flow_hs_option);
|
|
|
|
|
rb_hash_aset(optical_flow_hs_option, ID2SYM(rb_intern("lambda")), rb_float_new(0.0005));
|
|
|
|
|
rb_hash_aset(optical_flow_hs_option, ID2SYM(rb_intern("criteria")), cCvTermCriteria::new_object(cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1, 0.001)));
|
|
|
|
|
|
|
|
|
|
VALUE optical_flow_bm_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "OPTICAL_FLOW_BM_OPTION", optical_flow_bm_option);
|
|
|
|
|
rb_hash_aset(optical_flow_bm_option, ID2SYM(rb_intern("block_size")), cCvSize::new_object(cvSize(4, 4)));
|
|
|
|
|
rb_hash_aset(optical_flow_bm_option, ID2SYM(rb_intern("shift_size")), cCvSize::new_object(cvSize(1, 1)));
|
|
|
|
|
rb_hash_aset(optical_flow_bm_option, ID2SYM(rb_intern("max_range")), cCvSize::new_object(cvSize(4, 4)));
|
|
|
|
|
|
|
|
|
|
VALUE find_fundamental_matrix_option = rb_hash_new();
|
|
|
|
|
rb_define_const(rb_klass, "FIND_FUNDAMENTAL_MAT_OPTION", find_fundamental_matrix_option);
|
|
|
|
|
rb_hash_aset(find_fundamental_matrix_option, ID2SYM(rb_intern("with_status")), Qfalse);
|
|
|
|
|
rb_hash_aset(find_fundamental_matrix_option, ID2SYM(rb_intern("maximum_distance")), rb_float_new(1.0));
|
|
|
|
|
rb_hash_aset(find_fundamental_matrix_option, ID2SYM(rb_intern("desirable_level")), rb_float_new(0.99));
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
2011-01-15 06:15:49 -05:00
|
|
|
|
rb_define_singleton_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load_imageM), -1);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
// Ruby/OpenCV original functions
|
|
|
|
|
rb_define_method(rb_klass, "method_missing", RUBY_METHOD_FUNC(rb_method_missing), -1);
|
|
|
|
|
rb_define_method(rb_klass, "to_s", RUBY_METHOD_FUNC(rb_to_s), 0);
|
|
|
|
|
rb_define_method(rb_klass, "has_parent?", RUBY_METHOD_FUNC(rb_has_parent_q), 0);
|
|
|
|
|
rb_define_method(rb_klass, "parent", RUBY_METHOD_FUNC(rb_parent), 0);
|
|
|
|
|
rb_define_method(rb_klass, "inside?", RUBY_METHOD_FUNC(rb_inside_q), 1);
|
|
|
|
|
rb_define_method(rb_klass, "to_IplConvKernel", RUBY_METHOD_FUNC(rb_to_IplConvKernel), 1);
|
|
|
|
|
rb_define_method(rb_klass, "create_mask", RUBY_METHOD_FUNC(rb_create_mask), 0);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "width", RUBY_METHOD_FUNC(rb_width), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "columns", "width");
|
|
|
|
|
rb_define_alias(rb_klass, "cols", "width");
|
|
|
|
|
rb_define_method(rb_klass, "height", RUBY_METHOD_FUNC(rb_height), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "rows", "height");
|
|
|
|
|
rb_define_method(rb_klass, "depth", RUBY_METHOD_FUNC(rb_depth), 0);
|
|
|
|
|
rb_define_method(rb_klass, "channel", RUBY_METHOD_FUNC(rb_channel), 0);
|
|
|
|
|
rb_define_method(rb_klass, "data", RUBY_METHOD_FUNC(rb_data), 0);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "clone", RUBY_METHOD_FUNC(rb_clone), 0);
|
|
|
|
|
rb_define_method(rb_klass, "copy", RUBY_METHOD_FUNC(rb_copy), -1);
|
|
|
|
|
rb_define_method(rb_klass, "to_8u", RUBY_METHOD_FUNC(rb_to_8u), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_8s", RUBY_METHOD_FUNC(rb_to_8s), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_16u", RUBY_METHOD_FUNC(rb_to_16u), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_16s", RUBY_METHOD_FUNC(rb_to_16s), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_32s", RUBY_METHOD_FUNC(rb_to_32s), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_32f", RUBY_METHOD_FUNC(rb_to_32f), 0);
|
|
|
|
|
rb_define_method(rb_klass, "to_64f", RUBY_METHOD_FUNC(rb_to_64f), 0);
|
|
|
|
|
rb_define_method(rb_klass, "vector?", RUBY_METHOD_FUNC(rb_vector_q), 0);
|
|
|
|
|
rb_define_method(rb_klass, "square?", RUBY_METHOD_FUNC(rb_square_q), 0);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "to_CvMat", RUBY_METHOD_FUNC(rb_to_CvMat), 0);
|
|
|
|
|
rb_define_method(rb_klass, "sub_rect", RUBY_METHOD_FUNC(rb_sub_rect), -2);
|
|
|
|
|
rb_define_alias(rb_klass, "subrect", "sub_rect");
|
|
|
|
|
rb_define_method(rb_klass, "slice_width", RUBY_METHOD_FUNC(rb_slice_width), 1);
|
|
|
|
|
rb_define_method(rb_klass, "slice_height", RUBY_METHOD_FUNC(rb_slice_height), 1);
|
|
|
|
|
rb_define_method(rb_klass, "row", RUBY_METHOD_FUNC(rb_row), -2);
|
|
|
|
|
rb_define_method(rb_klass, "col", RUBY_METHOD_FUNC(rb_col), -2);
|
|
|
|
|
rb_define_alias(rb_klass, "column", "col");
|
|
|
|
|
rb_define_method(rb_klass, "each_row", RUBY_METHOD_FUNC(rb_each_row), 0);
|
|
|
|
|
rb_define_method(rb_klass, "each_col", RUBY_METHOD_FUNC(rb_each_col), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "each_column", "each_col");
|
|
|
|
|
rb_define_method(rb_klass, "diag", RUBY_METHOD_FUNC(rb_diag), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "diagonal", "diag");
|
|
|
|
|
rb_define_method(rb_klass, "size", RUBY_METHOD_FUNC(rb_size), 0);
|
|
|
|
|
rb_define_method(rb_klass, "dims", RUBY_METHOD_FUNC(rb_dims), 0);
|
|
|
|
|
rb_define_method(rb_klass, "dim_size", RUBY_METHOD_FUNC(rb_dim_size), 1);
|
|
|
|
|
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), -2);
|
|
|
|
|
rb_define_method(rb_klass, "fill", RUBY_METHOD_FUNC(rb_fill), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "set", "fill");
|
|
|
|
|
rb_define_method(rb_klass, "fill!", RUBY_METHOD_FUNC(rb_fill_bang), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "set!", "fill!");
|
|
|
|
|
rb_define_method(rb_klass, "clear", RUBY_METHOD_FUNC(rb_clear), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "set_zero", "clear");
|
|
|
|
|
rb_define_method(rb_klass, "clear!", RUBY_METHOD_FUNC(rb_clear_bang), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "set_zero!", "clear!");
|
|
|
|
|
rb_define_method(rb_klass, "identity", RUBY_METHOD_FUNC(rb_set_identity), -1);
|
|
|
|
|
rb_define_method(rb_klass, "identity!", RUBY_METHOD_FUNC(rb_set_identity_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "range", RUBY_METHOD_FUNC(rb_range), -1);
|
|
|
|
|
rb_define_method(rb_klass, "range!", RUBY_METHOD_FUNC(rb_range_bang), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "reshape", RUBY_METHOD_FUNC(rb_reshape), 1);
|
|
|
|
|
rb_define_method(rb_klass, "repeat", RUBY_METHOD_FUNC(rb_repeat), 1);
|
|
|
|
|
rb_define_method(rb_klass, "flip", RUBY_METHOD_FUNC(rb_flip), -1);
|
|
|
|
|
rb_define_method(rb_klass, "flip!", RUBY_METHOD_FUNC(rb_flip_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "split", RUBY_METHOD_FUNC(rb_split), 0);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "merge", RUBY_METHOD_FUNC(rb_merge), -2);
|
|
|
|
|
rb_define_method(rb_klass, "rand_shuffle", RUBY_METHOD_FUNC(rb_rand_shuffle), -1);
|
|
|
|
|
rb_define_method(rb_klass, "rand_shuffle!", RUBY_METHOD_FUNC(rb_rand_shuffle_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "lut", RUBY_METHOD_FUNC(rb_lut), 1);
|
|
|
|
|
rb_define_method(rb_klass, "convert_scale", RUBY_METHOD_FUNC(rb_convert_scale), 1);
|
|
|
|
|
rb_define_method(rb_klass, "convert_scale_abs", RUBY_METHOD_FUNC(rb_convert_scale_abs), 1);
|
|
|
|
|
rb_define_method(rb_klass, "add", RUBY_METHOD_FUNC(rb_add), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "+", "add");
|
|
|
|
|
rb_define_method(rb_klass, "sub", RUBY_METHOD_FUNC(rb_sub), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "-", "sub");
|
|
|
|
|
rb_define_method(rb_klass, "mul", RUBY_METHOD_FUNC(rb_mul), -1);
|
2011-01-09 10:27:30 -05:00
|
|
|
|
rb_define_method(rb_klass, "mat_mul", RUBY_METHOD_FUNC(rb_mat_mul), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "*", "mat_mul");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "div", RUBY_METHOD_FUNC(rb_div), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "/", "div");
|
|
|
|
|
rb_define_method(rb_klass, "and", RUBY_METHOD_FUNC(rb_and), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "&", "and");
|
|
|
|
|
rb_define_method(rb_klass, "or", RUBY_METHOD_FUNC(rb_or), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "|", "or");
|
|
|
|
|
rb_define_method(rb_klass, "xor", RUBY_METHOD_FUNC(rb_xor), -1);
|
|
|
|
|
rb_define_alias(rb_klass, "^", "xor");
|
|
|
|
|
rb_define_method(rb_klass, "not", RUBY_METHOD_FUNC(rb_not), 0);
|
|
|
|
|
rb_define_method(rb_klass, "not!", RUBY_METHOD_FUNC(rb_not_bang), 0);
|
|
|
|
|
rb_define_method(rb_klass, "eq", RUBY_METHOD_FUNC(rb_eq), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, "==", "eq");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "gt", RUBY_METHOD_FUNC(rb_gt), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, ">", "gt");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "ge", RUBY_METHOD_FUNC(rb_ge), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, ">=", "ge");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "lt", RUBY_METHOD_FUNC(rb_lt), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, "<", "lt");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "le", RUBY_METHOD_FUNC(rb_le), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, "<=", "le");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "ne", RUBY_METHOD_FUNC(rb_ne), 1);
|
2011-01-03 03:30:36 -05:00
|
|
|
|
// rb_define_alias(rb_klass, "!=", "ne");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_define_method(rb_klass, "in_range", RUBY_METHOD_FUNC(rb_in_range), 2);
|
|
|
|
|
rb_define_method(rb_klass, "abs_diff", RUBY_METHOD_FUNC(rb_abs_diff), 1);
|
|
|
|
|
rb_define_method(rb_klass, "count_non_zero", RUBY_METHOD_FUNC(rb_count_non_zero), 0);
|
|
|
|
|
rb_define_method(rb_klass, "sum", RUBY_METHOD_FUNC(rb_sum), 0);
|
|
|
|
|
rb_define_method(rb_klass, "avg", RUBY_METHOD_FUNC(rb_avg), -1);
|
|
|
|
|
rb_define_method(rb_klass, "avg_sdv", RUBY_METHOD_FUNC(rb_avg_sdv), -1);
|
|
|
|
|
rb_define_method(rb_klass, "sdv", RUBY_METHOD_FUNC(rb_sdv), -1);
|
|
|
|
|
rb_define_method(rb_klass, "min_max_loc", RUBY_METHOD_FUNC(rb_min_max_loc), -1);
|
|
|
|
|
rb_define_method(rb_klass, "dot_product", RUBY_METHOD_FUNC(rb_dot_product), 1);
|
|
|
|
|
rb_define_method(rb_klass, "cross_product", RUBY_METHOD_FUNC(rb_cross_product), 1);
|
|
|
|
|
rb_define_method(rb_klass, "transform", RUBY_METHOD_FUNC(rb_transform), -1);
|
|
|
|
|
rb_define_method(rb_klass, "perspective_transform", RUBY_METHOD_FUNC(rb_perspective_transform), 1);
|
|
|
|
|
rb_define_method(rb_klass, "mul_transposed", RUBY_METHOD_FUNC(rb_mul_transposed), -2);
|
|
|
|
|
rb_define_method(rb_klass, "trace", RUBY_METHOD_FUNC(rb_trace), 0);
|
|
|
|
|
rb_define_method(rb_klass, "transpose", RUBY_METHOD_FUNC(rb_transpose), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "t", "transpose");
|
|
|
|
|
rb_define_method(rb_klass, "transpose!", RUBY_METHOD_FUNC(rb_transpose_bang), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "t!", "transpose!");
|
|
|
|
|
rb_define_method(rb_klass, "det", RUBY_METHOD_FUNC(rb_det), 0);
|
|
|
|
|
rb_define_alias(rb_klass, "determinant", "det");
|
|
|
|
|
rb_define_method(rb_klass, "invert", RUBY_METHOD_FUNC(rb_invert), -1);
|
|
|
|
|
rb_define_method(rb_klass, "solve", RUBY_METHOD_FUNC(rb_solve), -1);
|
|
|
|
|
rb_define_method(rb_klass, "svd", RUBY_METHOD_FUNC(rb_svd), -1);
|
|
|
|
|
rb_define_method(rb_klass, "svbksb", RUBY_METHOD_FUNC(rb_svbksb), -1);
|
|
|
|
|
rb_define_method(rb_klass, "eigenvv", RUBY_METHOD_FUNC(rb_eigenvv), -1);
|
|
|
|
|
rb_define_method(rb_klass, "calc_covar_matrix", RUBY_METHOD_FUNC(rb_calc_covar_matrix), -1);
|
|
|
|
|
rb_define_method(rb_klass, "mahalonobis", RUBY_METHOD_FUNC(rb_mahalonobis), -1);
|
|
|
|
|
|
|
|
|
|
/* drawing function */
|
|
|
|
|
rb_define_method(rb_klass, "line", RUBY_METHOD_FUNC(rb_line), -1);
|
|
|
|
|
rb_define_method(rb_klass, "line!", RUBY_METHOD_FUNC(rb_line_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "rectangle", RUBY_METHOD_FUNC(rb_rectangle), -1);
|
|
|
|
|
rb_define_method(rb_klass, "rectangle!", RUBY_METHOD_FUNC(rb_rectangle_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "circle", RUBY_METHOD_FUNC(rb_circle), -1);
|
|
|
|
|
rb_define_method(rb_klass, "circle!", RUBY_METHOD_FUNC(rb_circle_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "ellipse", RUBY_METHOD_FUNC(rb_ellipse), -1);
|
|
|
|
|
rb_define_method(rb_klass, "ellipse!", RUBY_METHOD_FUNC(rb_ellipse_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "ellipse_box", RUBY_METHOD_FUNC(rb_ellipse_box), -1);
|
|
|
|
|
rb_define_method(rb_klass, "ellipse_box!", RUBY_METHOD_FUNC(rb_ellipse_box_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "fill_poly", RUBY_METHOD_FUNC(rb_fill_poly), -1);
|
|
|
|
|
rb_define_method(rb_klass, "fill_poly!", RUBY_METHOD_FUNC(rb_fill_poly_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "fill_convex_poly", RUBY_METHOD_FUNC(rb_fill_convex_poly), -1);
|
|
|
|
|
rb_define_method(rb_klass, "fill_convex_poly!", RUBY_METHOD_FUNC(rb_fill_convex_poly_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "poly_line", RUBY_METHOD_FUNC(rb_poly_line), -1);
|
|
|
|
|
rb_define_method(rb_klass, "poly_line!", RUBY_METHOD_FUNC(rb_poly_line_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "put_text", RUBY_METHOD_FUNC(rb_put_text), -1);
|
|
|
|
|
rb_define_method(rb_klass, "put_text!", RUBY_METHOD_FUNC(rb_put_text_bang), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "dft", RUBY_METHOD_FUNC(rb_dft), -1);
|
|
|
|
|
rb_define_method(rb_klass, "dct", RUBY_METHOD_FUNC(rb_dct), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "sobel", RUBY_METHOD_FUNC(rb_sobel), -1);
|
|
|
|
|
rb_define_method(rb_klass, "laplace", RUBY_METHOD_FUNC(rb_laplace), -1);
|
|
|
|
|
rb_define_method(rb_klass, "canny", RUBY_METHOD_FUNC(rb_canny), -1);
|
|
|
|
|
rb_define_method(rb_klass, "pre_corner_detect", RUBY_METHOD_FUNC(rb_pre_corner_detect), -1);
|
|
|
|
|
rb_define_method(rb_klass, "corner_eigenvv", RUBY_METHOD_FUNC(rb_corner_eigenvv), -1);
|
|
|
|
|
rb_define_method(rb_klass, "corner_min_eigen_val", RUBY_METHOD_FUNC(rb_corner_min_eigen_val), -1);
|
|
|
|
|
rb_define_method(rb_klass, "corner_harris", RUBY_METHOD_FUNC(rb_corner_harris), -1);
|
|
|
|
|
rb_define_private_method(rb_klass, "__find_corner_sub_pix", RUBY_METHOD_FUNC(rbi_find_corner_sub_pix), -1);
|
|
|
|
|
rb_define_method(rb_klass, "good_features_to_track", RUBY_METHOD_FUNC(rb_good_features_to_track), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "sample_line", RUBY_METHOD_FUNC(rb_sample_line), 2);
|
|
|
|
|
rb_define_method(rb_klass, "rect_sub_pix", RUBY_METHOD_FUNC(rb_rect_sub_pix), 2);
|
|
|
|
|
rb_define_method(rb_klass, "quadrangle_sub_pix", RUBY_METHOD_FUNC(rb_quadrangle_sub_pix), 2);
|
|
|
|
|
rb_define_method(rb_klass, "resize", RUBY_METHOD_FUNC(rb_resize), -1);
|
|
|
|
|
rb_define_method(rb_klass, "warp_affine", RUBY_METHOD_FUNC(rb_warp_affine), -1);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "rotation", RUBY_METHOD_FUNC(rb_rotation), 3);
|
|
|
|
|
rb_define_method(rb_klass, "warp_perspective", RUBY_METHOD_FUNC(rb_warp_perspective), -1);
|
|
|
|
|
//rb_define_method(rb_klass, "get_perspective_transform", RUBY_METHOD_FUNC(rb_get_perspective_transform), -1);
|
|
|
|
|
//rb_define_alias(rb_klass, "warp_perspective_q_matrix", "get_perspective_transform");
|
|
|
|
|
rb_define_method(rb_klass, "remap", RUBY_METHOD_FUNC(rb_remap), -1);
|
|
|
|
|
//rb_define_method(rb_klass, "log_polar", RUBY_METHOD_FUNC(rb_log_polar), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "erode", RUBY_METHOD_FUNC(rb_erode), -1);
|
|
|
|
|
rb_define_method(rb_klass, "erode!", RUBY_METHOD_FUNC(rb_erode_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "dilate", RUBY_METHOD_FUNC(rb_dilate), -1);
|
|
|
|
|
rb_define_method(rb_klass, "dilate!", RUBY_METHOD_FUNC(rb_dilate_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "morphology_open", RUBY_METHOD_FUNC(rb_morphology_open), -1);
|
|
|
|
|
rb_define_method(rb_klass, "morphology_close", RUBY_METHOD_FUNC(rb_morphology_close), -1);
|
|
|
|
|
rb_define_method(rb_klass, "morphology_gradient", RUBY_METHOD_FUNC(rb_morphology_gradient), -1);
|
|
|
|
|
rb_define_method(rb_klass, "morphology_tophat", RUBY_METHOD_FUNC(rb_morphology_tophat), -1);
|
|
|
|
|
rb_define_method(rb_klass, "morphology_blackhat", RUBY_METHOD_FUNC(rb_morphology_blackhat), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "smooth_blur_no_scale", RUBY_METHOD_FUNC(rb_smooth_blur_no_scale), -1);
|
|
|
|
|
rb_define_method(rb_klass, "smooth_blur", RUBY_METHOD_FUNC(rb_smooth_blur), -1);
|
|
|
|
|
rb_define_method(rb_klass, "smooth_gaussian", RUBY_METHOD_FUNC(rb_smooth_gaussian), -1);
|
|
|
|
|
rb_define_method(rb_klass, "smooth_median", RUBY_METHOD_FUNC(rb_smooth_median), -1);
|
|
|
|
|
rb_define_method(rb_klass, "smooth_bilateral", RUBY_METHOD_FUNC(rb_smooth_bilateral), -1);
|
|
|
|
|
rb_define_method(rb_klass, "filter2d", RUBY_METHOD_FUNC(rb_filter2d), -1);
|
|
|
|
|
rb_define_method(rb_klass, "copy_make_border_constant", RUBY_METHOD_FUNC(rb_copy_make_border_constant), -1);
|
|
|
|
|
rb_define_method(rb_klass, "copy_make_border_replicate", RUBY_METHOD_FUNC(rb_copy_make_border_replicate), -1);
|
|
|
|
|
rb_define_method(rb_klass, "integral", RUBY_METHOD_FUNC(rb_integral), -1);
|
|
|
|
|
rb_define_method(rb_klass, "threshold_binary", RUBY_METHOD_FUNC(rb_threshold_binary), -1);
|
|
|
|
|
rb_define_method(rb_klass, "threshold_binary_inverse", RUBY_METHOD_FUNC(rb_threshold_binary_inverse), -1);
|
|
|
|
|
rb_define_method(rb_klass, "threshold_trunc", RUBY_METHOD_FUNC(rb_threshold_trunc), -1);
|
|
|
|
|
rb_define_method(rb_klass, "threshold_to_zero", RUBY_METHOD_FUNC(rb_threshold_to_zero), -1);
|
|
|
|
|
rb_define_method(rb_klass, "threshold_to_zero_inverse", RUBY_METHOD_FUNC(rb_threshold_to_zero_inverse), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "pyr_down", RUBY_METHOD_FUNC(rb_pyr_down), -1);
|
|
|
|
|
rb_define_method(rb_klass, "pyr_up", RUBY_METHOD_FUNC(rb_pyr_up), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "flood_fill", RUBY_METHOD_FUNC(rb_flood_fill), -1);
|
|
|
|
|
rb_define_method(rb_klass, "flood_fill!", RUBY_METHOD_FUNC(rb_flood_fill_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "find_contours", RUBY_METHOD_FUNC(rb_find_contours), -1);
|
|
|
|
|
rb_define_method(rb_klass, "find_contours!", RUBY_METHOD_FUNC(rb_find_contours_bang), -1);
|
|
|
|
|
rb_define_method(rb_klass, "pyr_segmentation", RUBY_METHOD_FUNC(rb_pyr_segmentation), -1);
|
|
|
|
|
rb_define_method(rb_klass, "pyr_mean_shift_filtering", RUBY_METHOD_FUNC(rb_pyr_mean_shift_filtering), -1);
|
|
|
|
|
rb_define_method(rb_klass, "watershed", RUBY_METHOD_FUNC(rb_watershed), 0);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "moments", RUBY_METHOD_FUNC(rb_moments), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "hough_lines_standard", RUBY_METHOD_FUNC(rb_hough_lines_standard), -1);
|
|
|
|
|
rb_define_method(rb_klass, "hough_lines_probabilistic", RUBY_METHOD_FUNC(rb_hough_lines_probabilistic), -1);
|
|
|
|
|
rb_define_method(rb_klass, "hough_lines_multi_scale", RUBY_METHOD_FUNC(rb_hough_lines_multi_scale), -1);
|
|
|
|
|
rb_define_method(rb_klass, "hough_circles_gradient", RUBY_METHOD_FUNC(rb_hough_circles_gradient), -1);
|
|
|
|
|
//rb_define_method(rb_klass, "dist_transform", RUBY_METHOD_FUNC(rb_dist_transform), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "inpaint_ns", RUBY_METHOD_FUNC(rb_inpaint_ns), 2);
|
|
|
|
|
rb_define_method(rb_klass, "inpaint_telea", RUBY_METHOD_FUNC(rb_inpaint_telea), 2);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "equalize_hist", RUBY_METHOD_FUNC(rb_equalize_hist), 0);
|
|
|
|
|
rb_define_method(rb_klass, "match_template", RUBY_METHOD_FUNC(rb_match_template), -1);
|
|
|
|
|
rb_define_method(rb_klass, "match_shapes_i1", RUBY_METHOD_FUNC(rb_match_shapes_i1), -1);
|
|
|
|
|
rb_define_method(rb_klass, "match_shapes_i2", RUBY_METHOD_FUNC(rb_match_shapes_i2), -1);
|
|
|
|
|
rb_define_method(rb_klass, "match_shapes_i3", RUBY_METHOD_FUNC(rb_match_shapes_i3), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "mean_shift", RUBY_METHOD_FUNC(rb_mean_shift), 2);
|
|
|
|
|
rb_define_method(rb_klass, "cam_shift", RUBY_METHOD_FUNC(rb_cam_shift), 2);
|
|
|
|
|
rb_define_method(rb_klass, "snake_image", RUBY_METHOD_FUNC(rb_snake_image), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "optical_flow_hs", RUBY_METHOD_FUNC(rb_optical_flow_hs), -1);
|
|
|
|
|
rb_define_method(rb_klass, "optical_flow_lk", RUBY_METHOD_FUNC(rb_optical_flow_lk), -1);
|
|
|
|
|
rb_define_method(rb_klass, "optical_flow_bm", RUBY_METHOD_FUNC(rb_optical_flow_bm), -1);
|
|
|
|
|
|
|
|
|
|
rb_define_singleton_method(rb_klass, "find_fundamental_mat_7point", RUBY_METHOD_FUNC(rb_find_fundamental_mat_7point), -1);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "find_fundamental_mat_8point", RUBY_METHOD_FUNC(rb_find_fundamental_mat_8point), -1);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "find_fundamental_mat_ransac", RUBY_METHOD_FUNC(rb_find_fundamental_mat_ransac), -1);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "find_fundamental_mat_lmeds", RUBY_METHOD_FUNC(rb_find_fundamental_mat_lmeds), -1);
|
|
|
|
|
rb_define_singleton_method(rb_klass, "compute_correspond_epilines", RUBY_METHOD_FUNC(rb_compute_correspond_epilines), 3);
|
|
|
|
|
|
|
|
|
|
rb_define_method(rb_klass, "save_image", RUBY_METHOD_FUNC(rb_save_image), 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
rb_allocate(VALUE klass)
|
|
|
|
|
{
|
|
|
|
|
return OPENCV_OBJECT(klass, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.new(<i>row, col[, depth = CV_8U][, channel = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Create col * row matrix. Each element set 0.
|
|
|
|
|
*
|
|
|
|
|
* Each element possigle range is set by <i>depth</i>. Default is unsigned 8bit.
|
|
|
|
|
*
|
|
|
|
|
* Number of channel is set by <i>channel</i>. <i>channel</i> should be 1..4.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE row, column, depth, channel;
|
|
|
|
|
rb_scan_args(argc, argv, "22", &row, &column, &depth, &channel);
|
2011-01-05 11:16:10 -05:00
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
DATA_PTR(self) = cvCreateMat(FIX2INT(row), FIX2INT(column),
|
|
|
|
|
CV_MAKETYPE(CVMETHOD("DEPTH", depth, CV_8U), argc < 4 ? 3 : FIX2INT(channel)));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-15 06:15:49 -05:00
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat::load(<i>filename[,iscolor = CV_LOAD_IMAGE_COLOR]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Load an image from file.
|
|
|
|
|
* iscolor = CV_LOAD_IMAGE_COLOR, the loaded image is forced to be a 3-channel color image
|
|
|
|
|
* iscolor = CV_LOAD_IMAGE_GRAYSCALE, the loaded image is forced to be grayscale
|
|
|
|
|
* iscolor = CV_LOAD_IMAGE_UNCHANGED, the loaded image will be loaded as is.
|
|
|
|
|
* Currently the following file format are supported.
|
|
|
|
|
* * Windows bitmaps - BMP,DIB
|
|
|
|
|
* * JPEG files - JPEG,JPG,JPE
|
|
|
|
|
* * Portable Network Graphics - PNG
|
|
|
|
|
* * Portable image format - PBM,PGM,PPM
|
|
|
|
|
* * Sun rasters - SR,RAS
|
|
|
|
|
* * TIFF files - TIFF,TIF
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_load_imageM(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE filename, iscolor;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &filename, &iscolor);
|
|
|
|
|
Check_Type(filename, T_STRING);
|
|
|
|
|
|
|
|
|
|
int _iscolor;
|
|
|
|
|
if (TYPE(iscolor) == T_NIL) {
|
|
|
|
|
_iscolor = CV_LOAD_IMAGE_COLOR;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Check_Type(iscolor, T_FIXNUM);
|
|
|
|
|
_iscolor = FIX2INT(iscolor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CvMat *mat;
|
|
|
|
|
if ((mat = cvLoadImageM(StringValueCStr(filename), _iscolor)) == NULL) {
|
|
|
|
|
rb_raise(rb_eStandardError, "file does not exist or invalid format image.");
|
|
|
|
|
}
|
|
|
|
|
return OPENCV_OBJECT(rb_klass, mat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
/*
|
|
|
|
|
* nodoc
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_method_missing(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
const char *to_str = "\\Ato_(\\w+)";
|
|
|
|
|
VALUE name, args, str[3], method;
|
|
|
|
|
rb_scan_args(argc, argv, "1*", &name, &args);
|
2010-12-29 13:39:15 -05:00
|
|
|
|
if (RARRAY_LEN(args) != 0)
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return rb_call_super(argc, argv);
|
|
|
|
|
if(rb_reg_match(rb_reg_new(to_str, strlen(to_str), 0), rb_funcall(name, rb_intern("to_s"), 0)) == Qnil)
|
|
|
|
|
return rb_call_super(argc, argv);
|
|
|
|
|
str[0] = rb_str_new2("%s2%s");
|
|
|
|
|
str[1] = rb_color_model(self);
|
|
|
|
|
str[2] = rb_reg_nth_match(1, rb_backref_get());
|
|
|
|
|
method = rb_f_sprintf(3, str);
|
|
|
|
|
if (rb_respond_to(rb_module_opencv(), rb_intern(StringValuePtr(method))))
|
|
|
|
|
return rb_funcall(rb_module_opencv(), rb_intern(StringValuePtr(method)), 1, self);
|
|
|
|
|
return rb_call_super(argc, argv);
|
|
|
|
|
*/
|
|
|
|
|
VALUE name, args, method;
|
|
|
|
|
rb_scan_args(argc, argv, "1*", &name, &args);
|
|
|
|
|
method = rb_funcall(name, rb_intern("to_s"), 0);
|
2010-12-29 13:39:15 -05:00
|
|
|
|
if (RARRAY_LEN(args) != 0 || !rb_respond_to(rb_module_opencv(), rb_intern(StringValuePtr(method))))
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return rb_call_super(argc, argv);
|
|
|
|
|
return rb_funcall(rb_module_opencv(), rb_intern(StringValuePtr(method)), 1, self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_s -> string
|
|
|
|
|
*
|
|
|
|
|
* Return following string.
|
|
|
|
|
* m = CvMat.new(100, 100, :cv8u, 3)
|
|
|
|
|
* m.to_s # => <CvMat:100x100,depth=cv8u,channel=3>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_s(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
const int i = 6;
|
|
|
|
|
VALUE str[i];
|
|
|
|
|
str[0] = rb_str_new2("<%s:%dx%d,depth=%s,channel=%d>");
|
|
|
|
|
str[1] = rb_str_new2(rb_class2name(CLASS_OF(self)));
|
|
|
|
|
str[2] = rb_width(self);
|
|
|
|
|
str[3] = rb_height(self);
|
|
|
|
|
str[4] = rb_depth(self);
|
|
|
|
|
str[5] = rb_channel(self);
|
|
|
|
|
return rb_f_sprintf(i, str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* has_parent? -> true or false
|
|
|
|
|
*
|
|
|
|
|
* Return <tt>true</tt> if this matrix has parent object, otherwise <tt>false</tt>.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_has_parent_q(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return lookup_root_object(CVMAT(self)) ? Qtrue : Qfalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* parent -> obj or nil
|
|
|
|
|
*
|
|
|
|
|
* Return root object that refer this object.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_parent(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE root = lookup_root_object(CVMAT(self));
|
|
|
|
|
return root ? root : Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* inside?(obj) -> true or false
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_inside_q(VALUE self, VALUE object)
|
|
|
|
|
{
|
|
|
|
|
if (cCvPoint::rb_compatible_q(cCvPoint::rb_class(), object)) {
|
|
|
|
|
CvMat *mat = CVMAT(self);
|
|
|
|
|
int x = NUM2INT(rb_funcall(object, rb_intern("x"), 0));
|
|
|
|
|
int y = NUM2INT(rb_funcall(object, rb_intern("y"), 0));
|
|
|
|
|
if (cCvRect::rb_compatible_q(cCvRect::rb_class(), object)) {
|
|
|
|
|
int width = NUM2INT(rb_funcall(object, rb_intern("width"), 0));
|
|
|
|
|
int height = NUM2INT(rb_funcall(object, rb_intern("height"), 0));
|
|
|
|
|
return x >= 0 && y >= 0 && x < mat->width && x + width < mat->width && y < mat->height && y + height < mat->height ? Qtrue : Qfalse;
|
|
|
|
|
} else {
|
|
|
|
|
return x >= 0 && y >= 0 && x < mat->width && y < mat->height ? Qtrue : Qfalse;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rb_raise(rb_eArgError, "argument 1 should have method \"x\", \"y\"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_IplConvKernel -> iplconvkernel
|
|
|
|
|
*
|
|
|
|
|
* Create IplConvKernel from this matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_IplConvKernel(VALUE self, VALUE anchor)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
CvPoint p = VALUE_TO_CVPOINT(anchor);
|
|
|
|
|
IplConvKernel *kernel = cvCreateStructuringElementEx(src->cols, src->rows, p.x, p.y, CV_SHAPE_CUSTOM, src->data.i);
|
|
|
|
|
return DEPEND_OBJECT(cIplConvKernel::rb_class(), kernel, self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* create_mask -> cvmat(single-channel 8bit unsinged image)
|
|
|
|
|
*
|
|
|
|
|
* Create single-channel 8bit unsinged image that filled 0.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_create_mask(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mask = cCvMat::new_object(cvGetSize(CVARR(self)), CV_8UC1);
|
|
|
|
|
cvZero(CVARR(self));
|
|
|
|
|
return mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* width -> int
|
|
|
|
|
*
|
|
|
|
|
* Return number of columns.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_width(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return INT2FIX(CVMAT(self)->width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* height -> int
|
|
|
|
|
*
|
|
|
|
|
* Return number of rows.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_height(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return INT2FIX(CVMAT(self)->height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* depth -> symbol
|
|
|
|
|
*
|
|
|
|
|
* Return depth symbol. (see OpenCV::DEPTH)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_depth(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_hash_aref(rb_funcall(rb_const_get(rb_module_opencv(), rb_intern("DEPTH")), rb_intern("invert"), 0), INT2FIX(CV_MAT_DEPTH(CVMAT(self)->type)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* channel -> int (1 < channel < 4)
|
|
|
|
|
*
|
|
|
|
|
* Return number of channel.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_channel(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return INT2FIX(CV_MAT_CN(CVMAT(self)->type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* data -> binary (by String class)
|
|
|
|
|
*
|
|
|
|
|
* Return raw data of matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_data(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
IplImage *image = IPLIMAGE(self);
|
|
|
|
|
return rb_str_new((char *)image->imageData, image->imageSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* clone -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Clone matrix. The parent and child relation is not succeeded.
|
|
|
|
|
* Instance-specific method is succeeded.
|
|
|
|
|
*
|
|
|
|
|
* module M
|
|
|
|
|
* def example
|
|
|
|
|
* true
|
|
|
|
|
* end
|
|
|
|
|
* end
|
|
|
|
|
*
|
|
|
|
|
* mat.extend M
|
|
|
|
|
* mat.example #=> true
|
|
|
|
|
* clone = mat.clone
|
|
|
|
|
* clone.example #=> true
|
|
|
|
|
* copy = mat.copy
|
|
|
|
|
* copy.example #=> raise NoMethodError
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_clone(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE clone = rb_obj_clone(self);
|
|
|
|
|
DATA_PTR(clone) = cvClone(CVARR(self));
|
|
|
|
|
return clone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* copy() -> cvmat
|
|
|
|
|
* copy(<i>mat</i>) -> mat
|
|
|
|
|
* copy(<i>val</i>) -> array(include cvmat)
|
|
|
|
|
*
|
|
|
|
|
* Copy matrix. The parent and child relation is not succeeded.
|
|
|
|
|
* Instance-specific method is *NOT* succeeded. see also #clone.
|
|
|
|
|
*
|
|
|
|
|
* There are 3 kind behavior depending on the argument.
|
|
|
|
|
*
|
|
|
|
|
* copy()
|
|
|
|
|
* Return one copied matrix.
|
|
|
|
|
* copy(mat)
|
|
|
|
|
* Copy own elements to target matrix. Return nil.
|
|
|
|
|
* Size (or ROI) and channel and depth should be match.
|
|
|
|
|
* If own width or height does not match target matrix, raise CvUnmatchedSizes
|
|
|
|
|
* If own channel or depth does not match target matrix, raise CvUnmatchedFormats
|
|
|
|
|
* copy(val)
|
|
|
|
|
* The amounts of the specified number are copied. Return Array with copies.
|
|
|
|
|
* If you give the 0 or negative value. Return nil.
|
|
|
|
|
* mat.copy(3) #=> [mat1, mat2, mat3]
|
|
|
|
|
* mat.copy(-1) #=> nil
|
|
|
|
|
*
|
|
|
|
|
* When not apply to any, raise ArgumentError
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_copy(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
2011-01-01 16:25:38 -05:00
|
|
|
|
VALUE value, copied, tmp;
|
2008-08-19 11:01:28 -04:00
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
rb_scan_args(argc, argv, "01", &value);
|
|
|
|
|
if (argc == 0) {
|
|
|
|
|
CvSize size = cvGetSize(src);
|
|
|
|
|
copied = new_object(cvGetSize(src), cvGetElemType(src));
|
|
|
|
|
cvCopy(src, CVMAT(copied));
|
|
|
|
|
return copied;
|
|
|
|
|
}else{
|
|
|
|
|
if (rb_obj_is_kind_of(value, rb_klass)) {
|
|
|
|
|
cvCopy(src, CVMAT(value));
|
|
|
|
|
return Qnil;
|
|
|
|
|
}else if (rb_obj_is_kind_of(value, rb_cFixnum)) {
|
|
|
|
|
int n = FIX2INT(value);
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
copied = rb_ary_new2(n);
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
2011-01-01 16:25:38 -05:00
|
|
|
|
tmp = new_object(src->rows, src->cols, cvGetElemType(src));
|
|
|
|
|
cvCopy(src, CVMAT(tmp));
|
|
|
|
|
rb_ary_store(copied, i, tmp);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
return copied;
|
|
|
|
|
}else{
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
}else
|
|
|
|
|
rb_raise(rb_eArgError, "");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
copy(VALUE mat)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(mat);
|
|
|
|
|
VALUE copied = new_object(cvGetSize(src), cvGetElemType(src));
|
|
|
|
|
cvCopy(src, CVMAT(copied));
|
|
|
|
|
return copied;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_8u -> cvmat(depth = CV_8U)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to unsigned 8bit.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_8u(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_8U, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_8s -> cvmat(depth = CV_8S)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to signed 8bit.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_8s(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_8S, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_16u -> cvmat(depth = CV_16U)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to unsigned 16bit.
|
|
|
|
|
*/
|
|
|
|
|
VALUE rb_to_16u(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_16U, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_16s -> cvmat(depth = CV_16s)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to signed 16bit.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_16s(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
2011-01-01 07:16:27 -05:00
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_16S, CV_MAT_CN(src->type)));
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_32s -> cvmat(depth = CV_32S)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to signed 32bit.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_32s(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_32S, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_32f -> cvmat(depth = CV_32F)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to 32bit floating-point.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_32f(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_32F, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* to_64F -> cvmat(depth = CV_64F)
|
|
|
|
|
*
|
|
|
|
|
* Return the new matrix that elements is converted to 64bit floating-point.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_64f(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
VALUE dest = new_object(src->rows, src->cols, CV_MAKETYPE(CV_64F, CV_MAT_CN(src->type)));
|
|
|
|
|
cvConvert(src, CVMAT(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* vector? -> true or false
|
|
|
|
|
*
|
|
|
|
|
* If #width or #height is 1, return true. Otherwise return false.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_vector_q(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *mat = CVMAT(self);
|
|
|
|
|
return (mat->width == 1|| mat->height == 1) ? Qtrue : Qfalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* square? -> true or false
|
|
|
|
|
*
|
|
|
|
|
* If #width == #height return true. Otherwise return false.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_square_q(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvMat *mat = CVMAT(self);
|
|
|
|
|
return mat->width == mat->height ? Qtrue : Qfalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************
|
|
|
|
|
cxcore function
|
|
|
|
|
************************************************************/
|
|
|
|
|
/*
|
|
|
|
|
* Return CvMat object with reference to caller-object.
|
|
|
|
|
*
|
|
|
|
|
* src = CvMat.new(10, 10)
|
|
|
|
|
* src.has_parent? #=> false
|
|
|
|
|
* src.parent #=> nil
|
|
|
|
|
* mat = src.to_CvMat
|
|
|
|
|
* mat.has_parent? #=> true
|
|
|
|
|
* mat.parent #=> CvMat object "src"
|
|
|
|
|
*
|
|
|
|
|
* This case, 'src' is root-object. and 'mat' is child-object refer to 'src'.
|
|
|
|
|
* src <=refer= mat
|
|
|
|
|
* In C, 'src->data' and 'mat->data' is common. Therefore, they cause the change each other.
|
|
|
|
|
* object 'src' don't GC.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_to_CvMat(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return DEPEND_OBJECT(rb_klass, cvGetMat(CVARR(self), CVALLOC(CvMat)), self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sub_rect(<i>rect</i>) -> cvmat
|
|
|
|
|
* sub_rect(<i>topleft</i>, <i>size</i>) -> cvmat
|
|
|
|
|
* sub_rect(<i>x, y, width, height</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return parts of self as CvMat.
|
|
|
|
|
*
|
|
|
|
|
* <i>p</i> or <i>x</i>,<i>y</i> mean top-left coordinate.
|
|
|
|
|
* <i>size</i> or <i>width</i>,<i>height</i> is size.
|
|
|
|
|
*
|
|
|
|
|
* link:../images/CvMat_sub_rect.png
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sub_rect(VALUE self, VALUE args)
|
|
|
|
|
{
|
|
|
|
|
CvRect area;
|
|
|
|
|
CvPoint topleft;
|
|
|
|
|
CvSize size;
|
2010-12-29 13:39:15 -05:00
|
|
|
|
switch(RARRAY_LEN(args)) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
case 1:
|
2010-12-29 13:39:15 -05:00
|
|
|
|
area = VALUE_TO_CVRECT(RARRAY_PTR(args)[0]);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2010-12-29 13:39:15 -05:00
|
|
|
|
topleft = VALUE_TO_CVPOINT(RARRAY_PTR(args)[0]);
|
|
|
|
|
size = VALUE_TO_CVSIZE(RARRAY_PTR(args)[1]);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
area.x = topleft.x;
|
|
|
|
|
area.y = topleft.y;
|
|
|
|
|
area.width = size.width;
|
|
|
|
|
area.height = size.height;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
2010-12-29 13:39:15 -05:00
|
|
|
|
area.x = NUM2INT(RARRAY_PTR(args)[0]);
|
|
|
|
|
area.y = NUM2INT(RARRAY_PTR(args)[1]);
|
|
|
|
|
area.width = NUM2INT(RARRAY_PTR(args)[2]);
|
|
|
|
|
area.height = NUM2INT(RARRAY_PTR(args)[3]);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2011-01-01 15:57:46 -05:00
|
|
|
|
rb_raise(rb_eArgError, "wrong number of arguments (%ld of 1 or 2 or 4)", RARRAY_LEN(args));
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
return DEPEND_OBJECT(rb_klass,
|
|
|
|
|
cvGetSubRect(CVARR(self), CVALLOC(CvMat), area),
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* slice_width(<i>n</i>)
|
|
|
|
|
*
|
|
|
|
|
* The matrix is divided into <i>n</i> piece by the width.
|
|
|
|
|
* If it cannot be just divided, warning is displayed.
|
|
|
|
|
*
|
|
|
|
|
* e.g.
|
|
|
|
|
* m = OpenCV::CvMat.new(10, 10) #=> size 10x10 matrix
|
|
|
|
|
* ml, mr = m.slice_width(2) #=> 5x10 and 5x10 matrix
|
|
|
|
|
*
|
2010-12-31 07:28:25 -05:00
|
|
|
|
* ml, mm, mr = m.slice_width(3)#=> 3x10 3x10 3x10 matrix
|
2008-08-19 11:01:28 -04:00
|
|
|
|
* warning : width does not div correctly.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_slice_width(VALUE self, VALUE num)
|
|
|
|
|
{
|
|
|
|
|
int n = NUM2INT(num);
|
|
|
|
|
if (n < 1) {rb_raise(rb_eArgError, "number of piece should be > 0");}
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
if (size.width % n != 0) {rb_warn("width does not div correctly.");}
|
|
|
|
|
int div_x = size.width / n;
|
|
|
|
|
VALUE ary = rb_ary_new2(n);
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
CvRect rect = {div_x * i, 0, div_x, size.height};
|
|
|
|
|
rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), CVALLOC(CvMat), rect), self));
|
|
|
|
|
}
|
|
|
|
|
return ary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* slice_height(<i>n</i>)
|
|
|
|
|
*
|
|
|
|
|
* The matrix is divided into <i>n</i> piece by the height.
|
|
|
|
|
* If it cannot be just divided, warning is displayed.
|
|
|
|
|
*
|
|
|
|
|
* see also #slice_width.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_slice_height(VALUE self, VALUE num)
|
|
|
|
|
{
|
|
|
|
|
int n = NUM2INT(num);
|
|
|
|
|
if (n < 1) {rb_raise(rb_eArgError, "number of piece should be > 0");}
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
if (size.height % n != 0) {rb_warn("height does not div correctly.");}
|
|
|
|
|
int div_y = size.height / n;
|
|
|
|
|
VALUE ary = rb_ary_new2(n);
|
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
CvRect rect = {0, div_y * i, size.width, div_y};
|
|
|
|
|
rb_ary_push(ary, DEPEND_OBJECT(rb_klass, cvGetSubRect(CVARR(self), CVALLOC(CvMat), rect), self));
|
|
|
|
|
}
|
|
|
|
|
return ary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* row(<i>n</i>) -> Return row
|
|
|
|
|
* row(<i>n1, n2, ...</i>) -> Return Array of row
|
|
|
|
|
*
|
|
|
|
|
* Return row(or rows) of matrix.
|
|
|
|
|
* argument should be Fixnum or CvSlice compatible object.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_row(VALUE self, VALUE args)
|
|
|
|
|
{
|
2010-12-29 13:39:15 -05:00
|
|
|
|
int len = RARRAY_LEN(args);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (len < 1) {rb_raise(rb_eArgError, "wrong number of argument.(more than 1)");}
|
|
|
|
|
VALUE ary = rb_ary_new2(len);
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
VALUE value = rb_ary_entry(args, i);
|
|
|
|
|
if (FIXNUM_P(value)) {
|
|
|
|
|
rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), CVALLOC(CvMat), FIX2INT(value)), self));
|
|
|
|
|
}else{
|
|
|
|
|
CvSlice slice = VALUE_TO_CVSLICE(value);
|
|
|
|
|
rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetRows(CVARR(self), CVALLOC(CvMat), slice.start_index, slice.end_index), self));
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-29 13:39:15 -05:00
|
|
|
|
return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* col(<i>n</i>) -> Return column
|
|
|
|
|
* col(<i>n1, n2, ...</i>) -> Return Array of columns
|
|
|
|
|
*
|
|
|
|
|
* Return column(or columns) of matrix.
|
|
|
|
|
* argument should be Fixnum or CvSlice compatible object.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_col(VALUE self, VALUE args)
|
|
|
|
|
{
|
2010-12-29 13:39:15 -05:00
|
|
|
|
int len = RARRAY_LEN(args);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (len < 1) {rb_raise(rb_eArgError, "wrong number of argument.(more than 1)");}
|
|
|
|
|
VALUE ary = rb_ary_new2(len);
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
VALUE value = rb_ary_entry(args, i);
|
|
|
|
|
if (FIXNUM_P(value)) {
|
|
|
|
|
rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), CVALLOC(CvMat), FIX2INT(value)), self));
|
|
|
|
|
}else{
|
|
|
|
|
CvSlice slice = VALUE_TO_CVSLICE(value);
|
|
|
|
|
rb_ary_store(ary, i, DEPEND_OBJECT(rb_klass, cvGetCols(CVARR(self), CVALLOC(CvMat), slice.start_index, slice.end_index), self));
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-29 13:39:15 -05:00
|
|
|
|
return RARRAY_LEN(ary) > 1 ? ary : rb_ary_entry(ary, 0);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* each_row{|row| ... } -> self
|
|
|
|
|
*
|
|
|
|
|
* Calls block once for each row in self, passing that element as a parameter.
|
|
|
|
|
*
|
|
|
|
|
* see also CvMat#each_col
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_each_row(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int rows = CVMAT(self)->rows;
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
rb_yield(DEPEND_OBJECT(rb_klass, cvGetRow(CVARR(self), CVALLOC(CvMat), i), self));
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* each_col{|col| ... } -> self
|
|
|
|
|
*
|
|
|
|
|
* Calls block once for each column in self, passing that element as a parameter.
|
|
|
|
|
*
|
|
|
|
|
* see also CvMat#each_row
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_each_col(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int cols = CVMAT(self)->cols;
|
|
|
|
|
for (int i = 0; i < cols; i++) {
|
|
|
|
|
rb_yield(DEPEND_OBJECT(rb_klass, cvGetCol(CVARR(self), CVALLOC(CvMat), i), self));
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* diag(<i>[val = 0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return one of array diagonals.
|
|
|
|
|
* <i>val</i> is zeo corresponds to the main diagonal, -1 corresponds to the diagonal above the main etc, 1 corresponds to the diagonal below the main etc.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_diag(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val;
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &val) < 1) {
|
|
|
|
|
val = INT2FIX(0);
|
|
|
|
|
}
|
|
|
|
|
return DEPEND_OBJECT(rb_klass, cvGetDiag(CVARR(self), CVALLOC(CvMat), NUM2INT(val)), self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* size -> cvsize
|
|
|
|
|
*
|
|
|
|
|
* Return size by CvSize
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_size(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return cCvSize::new_object(cvGetSize(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
VALUE rb_elem_type(VALUE self) {
|
|
|
|
|
return INT2FIX(cvGetElemType(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dims -> array(int, int, ...)
|
|
|
|
|
*
|
|
|
|
|
* Return number of array dimensions and their sizes or the size of particular dimension.
|
|
|
|
|
* In case of CvMat it always returns 2 regardless of number of matrix rows.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dims(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int size[CV_MAX_DIM];
|
|
|
|
|
int dims = cvGetDims(CVARR(self), size);
|
|
|
|
|
VALUE ary = rb_ary_new2(dims);
|
|
|
|
|
for (int i = 0; i < dims; i++) {
|
|
|
|
|
rb_ary_store(ary, i, INT2FIX(size[i]));
|
|
|
|
|
}
|
|
|
|
|
return ary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dim_size(<i>index</i>) -> int
|
|
|
|
|
*
|
|
|
|
|
* Return number of dimension.
|
|
|
|
|
* almost same as CvMat#dims[<i>index</i>].
|
|
|
|
|
* If the dimension specified with index doesn't exist, CvStatusOutOfRange raise.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dim_size(VALUE self, VALUE index)
|
|
|
|
|
{
|
|
|
|
|
return INT2FIX(cvGetDimSize(CVARR(self), FIX2INT(index)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* [<i>idx1[,idx2]...</i>]
|
|
|
|
|
*
|
|
|
|
|
* Return value of the particular array element as CvScalar.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_aref(VALUE self, VALUE args)
|
|
|
|
|
{
|
|
|
|
|
int index[CV_MAX_DIM];
|
2010-12-29 13:39:15 -05:00
|
|
|
|
for (int i = 0; i < RARRAY_LEN(args); i++) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
index[i] = NUM2INT(rb_ary_entry(args, i));
|
|
|
|
|
}
|
|
|
|
|
CvScalar scalar = cvScalarAll(0);
|
2010-12-29 13:39:15 -05:00
|
|
|
|
switch(RARRAY_LEN(args)) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
case 1:
|
|
|
|
|
scalar = cvGet1D(CVARR(self), index[0]);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2011-01-03 01:46:21 -05:00
|
|
|
|
scalar = cvGet2D(CVARR(self), index[0], index[1]);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
2011-01-05 11:57:33 -05:00
|
|
|
|
/*
|
|
|
|
|
// cvGet3D should not be used in this method.
|
|
|
|
|
// "self" is always an instance of CvMat, and its data are 1D or 2D array.
|
2008-08-19 11:01:28 -04:00
|
|
|
|
case 3:
|
2011-01-03 01:46:21 -05:00
|
|
|
|
scalar = cvGet3D(CVARR(self), index[0], index[1], index[2]);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
2011-01-05 11:57:33 -05:00
|
|
|
|
*/
|
2008-08-19 11:01:28 -04:00
|
|
|
|
default:
|
|
|
|
|
scalar = cvGetND(CVARR(self), index);
|
|
|
|
|
}
|
2011-01-05 13:55:34 -05:00
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return cCvScalar::new_object(scalar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* [<i>idx1[,idx2]...</i>] = <i>value</i>
|
|
|
|
|
*
|
|
|
|
|
* Set value of the particular array element to <i>value</i>.
|
|
|
|
|
* <i>value</i> should be CvScalar.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_aset(VALUE self, VALUE args)
|
|
|
|
|
{
|
|
|
|
|
CvScalar scalar = VALUE_TO_CVSCALAR(rb_ary_pop(args));
|
|
|
|
|
int index[CV_MAX_DIM];
|
2010-12-29 13:39:15 -05:00
|
|
|
|
for (int i = 0; i < RARRAY_LEN(args); i++) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
index[i] = NUM2INT(rb_ary_entry(args, i));
|
|
|
|
|
}
|
2010-12-29 13:39:15 -05:00
|
|
|
|
switch(RARRAY_LEN(args)) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
case 1:
|
|
|
|
|
cvSet1D(CVARR(self), index[0], scalar);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2011-01-03 01:46:21 -05:00
|
|
|
|
cvSet2D(CVARR(self), index[0], index[1], scalar);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
2011-01-05 11:57:33 -05:00
|
|
|
|
// cvGet3D should not be used in this method.
|
|
|
|
|
// "self" is always an instance of CvMat, and its data are 1D or 2D array.
|
|
|
|
|
/*
|
2008-08-19 11:01:28 -04:00
|
|
|
|
case 3:
|
2011-01-05 11:57:33 -05:00
|
|
|
|
cvSet3D(CVARR(self), index[0], index[1], index[2], scalar);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
break;
|
2011-01-05 11:57:33 -05:00
|
|
|
|
*/
|
2008-08-19 11:01:28 -04:00
|
|
|
|
default:
|
|
|
|
|
cvSetND(CVARR(self), index, scalar);
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill(<i>value[, mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return CvMat copied value to every selected element. value should be CvScalar or compatible object.
|
|
|
|
|
* self[I] = value if mask(I)!=0
|
|
|
|
|
*
|
|
|
|
|
* note: This method support ROI on IplImage class. but COI not support. COI should not be set.
|
|
|
|
|
* image = IplImage.new(10, 20) #=> create 3 channel image.
|
|
|
|
|
* image.coi = 1 #=> set COI
|
|
|
|
|
* image.fill(CvScalar.new(10, 20, 30)) #=> raise CvBadCOI error.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_fill_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill!(<i>value[, mask]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Copie value to every selected element.
|
|
|
|
|
* self[I] = value if mask(I)!=0
|
|
|
|
|
*
|
|
|
|
|
* see also #fill.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE value, mask;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &value, &mask);
|
|
|
|
|
cvSet(CVARR(self), VALUE_TO_CVSCALAR(value), MASK(mask));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* save_image(<i>filename</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Saves an image to file. The image format is chosen depending on the filename extension.
|
|
|
|
|
* Only 8bit single-channel or 3-channel(with 'BGR' channel order) image can be saved.
|
|
|
|
|
*
|
|
|
|
|
* e.g.
|
|
|
|
|
* image = OpenCV::CvMat.new(10, 10, CV_8U, 3)
|
|
|
|
|
* image.save_image("image.jpg") #=> save as JPEG format
|
|
|
|
|
* image.save_image("image.png") #=> save as PNG format
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_save_image(VALUE self, VALUE filename)
|
|
|
|
|
{
|
|
|
|
|
Check_Type(filename, T_STRING);
|
|
|
|
|
cvSaveImage(StringValueCStr(filename), CVARR(self));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* clear -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix all element-value cleared.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_clear(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_clear_bang(copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* clear! -> self
|
|
|
|
|
*
|
|
|
|
|
* Clear all element-value. Return self.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_clear_bang(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
cvSetZero(CVARR(self));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* identity(<i>[val = [1]]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return initializes scaled identity matrix.
|
|
|
|
|
* <i>val</i> should be CvScalar.
|
|
|
|
|
*
|
|
|
|
|
* arr(i, j) = val if i = j, 0 otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_set_identity(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_set_identity_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* identity!(<i>[val = [1]]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Initialize scaled identity matrix.
|
|
|
|
|
* <i>val</i> should be CvScalar.
|
|
|
|
|
*
|
|
|
|
|
* arr(i, j) = val if i = j, 0 otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_set_identity_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val;
|
|
|
|
|
CvScalar value;
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &val) < 1) {
|
|
|
|
|
value = cvRealScalar(1);
|
|
|
|
|
}else{
|
|
|
|
|
value = VALUE_TO_CVSCALAR(val);
|
|
|
|
|
}
|
|
|
|
|
cvSetIdentity(CVARR(self), value);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* range(start, end) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Create and return filled matrix with given range of numbers.
|
|
|
|
|
*
|
|
|
|
|
* see range!
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_range(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_range_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* range!(start, end) -> self
|
|
|
|
|
*
|
|
|
|
|
* Fills matrix with given range of numbers.
|
|
|
|
|
*
|
|
|
|
|
* initializes the matrix as following:
|
|
|
|
|
* arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr))
|
|
|
|
|
* For example, the following code will initilize 1D vector with subsequent integer numbers.
|
|
|
|
|
* m = CvMat.new(1, 10, :cv32s)
|
|
|
|
|
* m.range!(0, m.cols); // m will be initialized as [0,1,2,3,4,5,6,7,8,9]
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_range_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE start, end;
|
|
|
|
|
rb_scan_args(argc, argv, "20", &start, &end);
|
|
|
|
|
cvRange(CVARR(self), NUM2DBL(start), NUM2DBL(end));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* reshape(<i>[:rows => num][, :channel => cn]</i>) -> cvmat(refer self)
|
|
|
|
|
*
|
|
|
|
|
* Change shape of matrix/image without copying data.
|
|
|
|
|
*
|
|
|
|
|
* e.g.
|
|
|
|
|
* mat = CvMat.new(3, 3, CV_8U, 3) #=> 3x3 3-channel matrix
|
|
|
|
|
* vec = mat.reshape(:rows => 1) #=> 1x9 3-channel matrix
|
|
|
|
|
* ch1 = mat.reshape(:channel => 1) #=> 9x9 1-channel matrix
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_reshape(VALUE self, VALUE hash)
|
|
|
|
|
{
|
|
|
|
|
if (TYPE(hash) != T_HASH)
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be Hash that contaion key (:row, :channel).");
|
|
|
|
|
VALUE channel = rb_hash_aref(hash, ID2SYM(rb_intern("channel")));
|
|
|
|
|
VALUE rows = rb_hash_aref(hash, ID2SYM(rb_intern("rows")));
|
2011-01-01 07:29:35 -05:00
|
|
|
|
return DEPEND_OBJECT(rb_klass, cvReshape(CVARR(self), CVALLOC(CvMat), NIL_P(channel) ? 0 : FIX2INT(channel), NIL_P(rows) ? 0 : FIX2INT(rows)), self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* repeat(<i>mat</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Tiled <i>mat</i> by self.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_repeat(VALUE self, VALUE object)
|
|
|
|
|
{
|
2011-01-01 17:07:02 -05:00
|
|
|
|
if (!rb_obj_is_kind_of(object, rb_class()))
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_raise(rb_eTypeError, "argument should be CvMat subclass.");
|
|
|
|
|
cvRepeat(CVARR(self), CVARR(object));
|
|
|
|
|
return object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
2011-01-01 14:06:12 -05:00
|
|
|
|
* flip(:x) -> cvmat
|
|
|
|
|
* flip(:y) -> cvmat
|
|
|
|
|
* flip(:xy) -> cvmat
|
|
|
|
|
* flip -> cvmat
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
|
|
|
|
* Return new flipped 2D array.
|
2011-01-01 14:06:12 -05:00
|
|
|
|
* * flip(:x) - flip around horizontal
|
|
|
|
|
* * flip(:y) - flip around vertical
|
|
|
|
|
* * flip(:xy) - flip around both axises
|
|
|
|
|
* * flip - flip around vertical
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_flip(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_flip_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
2011-01-01 14:06:12 -05:00
|
|
|
|
* flip!(:x) -> self
|
|
|
|
|
* flip!(:y) -> self
|
|
|
|
|
* flip!(:xy) -> self
|
|
|
|
|
* flip! -> self
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
|
|
|
|
* Flip 2D array. Return self.
|
|
|
|
|
*
|
|
|
|
|
* see also CvMat#flip
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_flip_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE format;
|
2011-01-01 14:06:12 -05:00
|
|
|
|
int mode = 0;
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (rb_scan_args(argc, argv, "01", &format) > 0) {
|
|
|
|
|
if (rb_to_id(format) == rb_intern("x"))
|
|
|
|
|
mode = 1;
|
|
|
|
|
else if (rb_to_id(format) == rb_intern("y"))
|
|
|
|
|
mode = 0;
|
2011-01-01 14:06:12 -05:00
|
|
|
|
else if (rb_to_id(format) == rb_intern("xy"))
|
|
|
|
|
mode = -1;
|
2008-08-19 11:01:28 -04:00
|
|
|
|
else
|
2011-01-01 14:06:12 -05:00
|
|
|
|
rb_warn("argument may be :x or :y or :xy");
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
|
|
|
|
cvFlip(CVARR(self), NULL, mode);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* split -> array(include cvmat)
|
|
|
|
|
*
|
|
|
|
|
* Divides multi-channel array into several single-chanel arrays.
|
|
|
|
|
*
|
|
|
|
|
* e.g.
|
|
|
|
|
* image = CvMat.new 640, 480, CV_8U, 3 #=> 3-channel image
|
|
|
|
|
* image.split #=> [image1, image2, image3] : each image have single-channel
|
|
|
|
|
*
|
|
|
|
|
* e.g. switch red <-> blue channel.
|
|
|
|
|
* image = IplImage.load "sample.bmp"
|
|
|
|
|
* i = image.split
|
|
|
|
|
* new_image = CvMat.merge i[2], i[1], i[0]
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_split(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int type = CVMAT(self)->type, depth = CV_MAT_DEPTH(type), channel = CV_MAT_CN(type);
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
CvMat *dest[] = {NULL, NULL, NULL, NULL};
|
|
|
|
|
for (int i = 0; i < channel; i++)
|
|
|
|
|
dest[i] = cvCreateMat(size.height, size.width, CV_MAKETYPE(depth, 1));
|
|
|
|
|
cvSplit(CVARR(self), dest[0], dest[1], dest[2], dest[3]);
|
|
|
|
|
VALUE ary = rb_ary_new2(channel);
|
|
|
|
|
for (int i = 0; i < channel; i++)
|
|
|
|
|
rb_ary_store(ary, i, OPENCV_OBJECT(rb_klass, dest[i]));
|
|
|
|
|
return ary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.merge(<i>mat1[,mat2][,mat3][,mat4]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Composes multi-channel array from several single-channel arrays.
|
|
|
|
|
* Each argument should be single-channel image(CvMat or subclass).
|
|
|
|
|
* All image should be same size and same depth.
|
|
|
|
|
*
|
|
|
|
|
* see also CvMat#split
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_merge(VALUE klass, VALUE args)
|
|
|
|
|
{
|
|
|
|
|
VALUE object, dest;
|
2010-12-29 13:39:15 -05:00
|
|
|
|
int len = RARRAY_LEN(args);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (!(len > 0) || len > CV_CN_MAX) {
|
|
|
|
|
rb_raise(rb_eArgError, "wrong number of argument (%d for 1..4)", len);
|
|
|
|
|
}
|
|
|
|
|
CvMat *src[] = {NULL, NULL, NULL, NULL}, *tmp = 0;
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
if (rb_obj_is_kind_of((object = rb_ary_entry(args, i)), rb_klass)) {
|
|
|
|
|
src[i] = CVMAT(object);
|
|
|
|
|
if (CV_MAT_CN(src[i]->type) != 1) {
|
|
|
|
|
rb_raise(rb_eStandardError, "image should be single-channel CvMat.");
|
|
|
|
|
}
|
|
|
|
|
if (!tmp)
|
|
|
|
|
tmp = src[i];
|
|
|
|
|
else{
|
|
|
|
|
if (!CV_ARE_SIZES_EQ(tmp, src[i]))
|
|
|
|
|
rb_raise(rb_eStandardError, "image size should be same.");
|
|
|
|
|
if (!CV_ARE_DEPTHS_EQ(tmp, src[i]))
|
|
|
|
|
rb_raise(rb_eStandardError, "image depth should be same.");
|
|
|
|
|
}
|
|
|
|
|
}else if (NIL_P(object)) {
|
|
|
|
|
src[i] = NULL;
|
|
|
|
|
}else
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be CvMat or subclass of it.");
|
|
|
|
|
}
|
|
|
|
|
dest = new_object(cvGetSize(tmp), CV_MAKETYPE(CV_MAT_DEPTH(tmp->type), len));
|
|
|
|
|
cvMerge(src[0], src[1], src[2], src[3], CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.mix_channels(srcs,dests,from_to = {1 => 1, 2 => 2, 3 => 3, 4 => 4}) -> dests
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mix_channels(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE srcs, dests, from_to;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &srcs, &dests, &from_to);
|
|
|
|
|
/* not yet */
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
2011-01-01 14:59:19 -05:00
|
|
|
|
* rand_shuffle([seed = nil][,iter_factor = 1]) -> cvmat
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
2011-01-01 14:59:19 -05:00
|
|
|
|
* Return shuffled matrix
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
|
|
|
|
* see rand_shuffle!
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rand_shuffle(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_rand_shuffle_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
2011-01-01 14:59:19 -05:00
|
|
|
|
* rand_shuffle!([seed = nil][,iter_factor = 1]) -> cvmat
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
2011-01-01 14:59:19 -05:00
|
|
|
|
* Shuffles the matrix by swapping randomly chosen pairs of the matrix elements on each iteration
|
|
|
|
|
* (where each element may contain several components in case of multi-channel arrays). The number of
|
|
|
|
|
* iterations (i.e. pairs swapped) is (iter_factor*mat.rows*mat.cols).round, so iter_factor=0 means
|
|
|
|
|
* that no shuffling is done, iter_factor=1 means that the function swaps rows(mat)*cols(mat) random
|
|
|
|
|
* pairs etc.
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rand_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE seed, iter;
|
|
|
|
|
CvRNG rng;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &seed, &iter);
|
|
|
|
|
if(NIL_P(seed))
|
|
|
|
|
cvRandShuffle(CVARR(self), NULL, IF_INT(iter, 1));
|
|
|
|
|
else{
|
|
|
|
|
rng = cvRNG(rb_num2ll(seed));
|
|
|
|
|
cvRandShuffle(CVARR(self), &rng, IF_INT(iter, 1));
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* lut(<i>lookup_table</i>) -> cvmat
|
|
|
|
|
*
|
2011-01-05 13:55:34 -05:00
|
|
|
|
* Return new matrix performed lookup-table transform.
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*
|
|
|
|
|
* <i>lookup_table</i> should be CvMat that have 256 element (e.g. 1x256 matrix).
|
|
|
|
|
* Otherwise, raise CvStatusBadArgument error.
|
|
|
|
|
*
|
|
|
|
|
* And <i>lookup_table</i> should either have a single-channel, or the same number of channels.
|
|
|
|
|
* When single-channel lookup-table given, same table is used for all channels.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_lut(VALUE self, VALUE lut)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = copy(self);
|
|
|
|
|
cvLUT(CVARR(self), CVARR(dest), CVARR(lut));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* convert_scale(<i>:depth => nil, :scale => 1.0, :shift => 0.0</i>)
|
|
|
|
|
*
|
|
|
|
|
* Return new array with optional linear transformation.
|
|
|
|
|
* mat(I) = src(I) * scale + (shift, shift, ...)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_convert_scale(VALUE self, VALUE hash)
|
|
|
|
|
{
|
|
|
|
|
if (TYPE(hash) != T_HASH)
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be Hash that contaion key [:depth, :scale, :shift].");
|
|
|
|
|
VALUE depth = rb_hash_aref(hash, ID2SYM(rb_intern("depth"))),
|
|
|
|
|
scale = rb_hash_aref(hash, ID2SYM(rb_intern("scale"))),
|
|
|
|
|
shift = rb_hash_aref(hash, ID2SYM(rb_intern("shift"))),
|
2011-01-01 15:51:53 -05:00
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CVMETHOD("DEPTH", depth, CV_MAT_DEPTH(CVMAT(self)->type)), CV_MAT_CN(CVMAT(self)->type)));
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvConvertScale(CVARR(self), CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* convert_scale_abs(<i>:scale => 1.0, :shift => 0.0</i>)
|
|
|
|
|
*
|
|
|
|
|
* Return new array with optional linear transformation.
|
|
|
|
|
* It is similar to CvMat#convert_scale, but it stores absolute values of the conversion result
|
|
|
|
|
* mat(I) = (src(I) * scale + (shift, shift, ...)).abs
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_convert_scale_abs(VALUE self, VALUE hash)
|
|
|
|
|
{
|
|
|
|
|
if (TYPE(hash) != T_HASH)
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be Hash that contaion key [:depth, :scale, :shift].");
|
|
|
|
|
VALUE
|
|
|
|
|
scale = rb_hash_aref(hash, ID2SYM(rb_intern("scale"))),
|
|
|
|
|
shift = rb_hash_aref(hash, ID2SYM(rb_intern("shift"))),
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_8U, CV_MAT_CN(CVMAT(self)->type)));
|
|
|
|
|
cvConvertScale(CVARR(self), CVARR(dest), IF_DBL(scale, 1.0), IF_DBL(shift, 0.0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* add(<i>val[,mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element sum.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* <i>mask</i> should be CvMat(8bit single-channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = src1(I) + src2(I) if mask(I) != 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_add(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, mask, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &mask);
|
2011-01-05 11:16:10 -05:00
|
|
|
|
dest = copy(self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass))
|
|
|
|
|
cvAdd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
else
|
|
|
|
|
cvAddS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sub(<i>val[,mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element difference.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* <i>mask</i> should be CvMat(8bit single-channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = src1(I) - src2(I) if mask(I) != 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sub(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, mask, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &mask);
|
2011-01-05 11:16:10 -05:00
|
|
|
|
|
|
|
|
|
dest = copy(self);
|
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass)) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvSub(CVARR(self), CVARR(val), CVARR(dest), MASK(mask));
|
2011-01-05 11:16:10 -05:00
|
|
|
|
}
|
|
|
|
|
else {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvSubS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask));
|
2011-01-05 11:16:10 -05:00
|
|
|
|
}
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* mul(<i>val[,scale = 1.0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element product.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = scale * src1(I) * src2(I)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mul(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, scale, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &val, &scale) < 2)
|
|
|
|
|
scale = rb_float_new(1.0);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
2011-01-09 10:27:30 -05:00
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass)) {
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvMul(CVARR(self), CVARR(val), CVARR(dest), NUM2DBL(scale));
|
|
|
|
|
}else{
|
|
|
|
|
CvScalar scl = VALUE_TO_CVSCALAR(val);
|
|
|
|
|
VALUE mat = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSet(CVARR(mat), scl);
|
|
|
|
|
cvMul(CVARR(self), CVARR(mat), CVARR(dest), NUM2DBL(scale));
|
|
|
|
|
}
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-09 10:27:30 -05:00
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* mat_mul(<i>val[,shiftvec]</i>) -> cvmat
|
|
|
|
|
* Performs matrix multiplication
|
|
|
|
|
* dst = src1 * src2 + shiftvec
|
|
|
|
|
* <i>val</i> and <i>shiftvec</i> should be CvMat
|
|
|
|
|
* All the matrices should have the same data type and coordinated sizes.
|
|
|
|
|
* Real or complex floating-point matrices are supported.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mat_mul(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, shiftvec, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &shiftvec);
|
|
|
|
|
dest = new_object(CVMAT(self)->rows, CVMAT(val)->cols, cvGetElemType(CVARR(self)));
|
|
|
|
|
if (NIL_P(shiftvec))
|
|
|
|
|
cvMatMul(CVARR(self), CVARR(val), CVARR(dest));
|
|
|
|
|
else
|
|
|
|
|
cvMatMulAdd(CVARR(self), CVARR(val), CVARR(shiftvec), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* div(<i>val[,scale = 1.0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element division.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = scale * src1(I) / src2(I)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_div(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, scale, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &val, &scale) < 2)
|
|
|
|
|
scale = rb_float_new(1.0);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass)) {
|
|
|
|
|
cvDiv(CVARR(self), CVARR(val), CVARR(dest), NUM2DBL(scale));
|
|
|
|
|
}else{
|
|
|
|
|
CvScalar scl = VALUE_TO_CVSCALAR(val);
|
|
|
|
|
VALUE mat = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSet(CVARR(mat), scl);
|
|
|
|
|
cvDiv(CVARR(self), CVARR(mat), CVARR(dest), NUM2DBL(scale));
|
|
|
|
|
}
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* and(<i>val[,mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element bit-wise conjunction.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = src1(I) & src2(I) if mask(I) != 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_and(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, mask, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &mask);
|
2011-01-02 23:47:34 -05:00
|
|
|
|
dest = copy(self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass))
|
|
|
|
|
cvAnd(CVARR(self), CVARR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
else
|
|
|
|
|
cvAndS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* or(<i>val[,mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element bit-wise disjunction.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = src1(I) | src2(I) if mask(I) != 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_or(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, mask, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &mask);
|
2011-01-02 23:54:27 -05:00
|
|
|
|
dest = copy(self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass))
|
|
|
|
|
cvOr(CVARR(self), CVARR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
else
|
|
|
|
|
cvOrS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* xor(<i>val[,mask]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix computed per-element bit-wise "exclusive or" operation.
|
|
|
|
|
* <i>val</i> should be CvMat or CvScalar.
|
|
|
|
|
* If <i>val</i> is CvMat, it must have same type (depth and channel).
|
|
|
|
|
* For each element (I)
|
|
|
|
|
* dst(I) = src1(I) ^ src2(I) if mask(I) != 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_xor(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE val, mask, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &val, &mask);
|
2011-01-03 00:21:38 -05:00
|
|
|
|
dest = copy(self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass))
|
|
|
|
|
cvXor(CVARR(self), CVARR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
else
|
|
|
|
|
cvXorS(CVARR(self), VALUE_TO_CVSCALAR(val), CVARR(dest), MASK(mask));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* not -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element bit-wise inversion.
|
|
|
|
|
* dst(I) =~ src(I)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_not(VALUE self)
|
|
|
|
|
{
|
2011-01-03 00:21:38 -05:00
|
|
|
|
VALUE dest = copy(self);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvNot(CVARR(self), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* not! -> self
|
|
|
|
|
*
|
|
|
|
|
* Performe per-element bit-wise inversion.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_not_bang(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
cvNot(CVARR(self), CVARR(self));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
rb_cmp_internal(VALUE self, VALUE val, int operand)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), CV_8U);
|
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass))
|
|
|
|
|
cvCmp(CVARR(self), CVARR(val), CVARR(dest), operand);
|
|
|
|
|
else if (CV_MAT_CN(cvGetElemType(CVARR(self))) == 1 && rb_obj_is_kind_of(val, rb_cNumeric)) {
|
|
|
|
|
cvCmpS(CVARR(self), NUM2DBL(val), CVARR(dest), operand);
|
|
|
|
|
}else{
|
|
|
|
|
VALUE mat = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSet(CVARR(mat), VALUE_TO_CVSCALAR(val));
|
|
|
|
|
cvCmp(CVARR(self), CVARR(mat), CVARR(dest), operand);
|
|
|
|
|
}
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* eq(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "equal".
|
|
|
|
|
* dst(I) = (self(I) == val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_eq(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_EQ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* gt(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "greater than".
|
|
|
|
|
* dst(I) = (self(I) > val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_gt(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_GT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ge(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "greater or equal".
|
|
|
|
|
* dst(I) = (self(I) >= val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ge(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_GE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* lt(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "less than".
|
|
|
|
|
* dst(I) = (self(I) < val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_lt(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_LT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* le(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "less or equal".
|
|
|
|
|
* dst(I) = (self(I) <= val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_le(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_LE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ne(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return new matrix performed per-element comparision "not equal".
|
|
|
|
|
* dst(I) = (self(I) != val(I) ? 0xFF : 0)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ne(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
return rb_cmp_internal(self, val, CV_CMP_NE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* in_range(<i>min, max</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Check that element lie between two object.
|
|
|
|
|
* <i>min</i> and <i>max</i> should be CvMat that have same size and type, or CvScalar.
|
|
|
|
|
* Return new matrix performed per-element,
|
|
|
|
|
* dst(I) = within the range ? 0xFF : 0
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_in_range(VALUE self, VALUE min, VALUE max)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = dest = new_object(cvGetSize(CVARR(self)), CV_8UC1), tmp;
|
|
|
|
|
if (rb_obj_is_kind_of(min, rb_klass) && rb_obj_is_kind_of(max, rb_klass)) {
|
|
|
|
|
cvInRange(CVARR(self), CVARR(min), CVARR(max), CVARR(dest));
|
|
|
|
|
}else if (rb_obj_is_kind_of(min, rb_klass)) {
|
|
|
|
|
tmp = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(max));
|
|
|
|
|
cvInRange(CVARR(self), CVARR(min), CVARR(tmp), CVARR(dest));
|
|
|
|
|
}else if (rb_obj_is_kind_of(max, rb_klass)) {
|
|
|
|
|
tmp = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSet(CVARR(tmp), VALUE_TO_CVSCALAR(min));
|
|
|
|
|
cvInRange(CVARR(self), CVARR(tmp), CVARR(max), CVARR(dest));
|
|
|
|
|
}else
|
|
|
|
|
cvInRangeS(CVARR(self), VALUE_TO_CVSCALAR(min), VALUE_TO_CVSCALAR(max), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* abs_diff(<i>val</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculate absolute difference between two.
|
|
|
|
|
* <i>val</i> should be CvMat that have same size and same type, or CvScalar.
|
|
|
|
|
* dst(I) = (src(I) - val(I)).abs
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_abs_diff(VALUE self, VALUE val)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
if (rb_obj_is_kind_of(val, rb_klass)) {
|
|
|
|
|
cvAbsDiff(CVARR(self), CVARR(val), CVARR(dest));
|
|
|
|
|
}else{
|
|
|
|
|
cvAbsDiffS(CVARR(self), CVARR(dest), VALUE_TO_CVSCALAR(val));
|
|
|
|
|
}
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* count_non_zero -> int
|
|
|
|
|
*
|
|
|
|
|
* Returns the number of non-zero elements.
|
|
|
|
|
* result = sumI arr(I)!=0
|
|
|
|
|
*
|
|
|
|
|
* In case of IplImage both ROI and COI are supported.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_count_non_zero(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return INT2FIX(cvCountNonZero(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sum -> scalar
|
|
|
|
|
*
|
|
|
|
|
* Return summerizes elements as CvScalar. Independently for each channel.
|
|
|
|
|
*
|
|
|
|
|
* note: If COI is setted in IplImage, the method processes the selected channel only and store the sum to the first component scalar[0].
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sum(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return cCvScalar::new_object(cvSum(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* avg(<i>[mask]</i>) -> mean(as scalar)
|
|
|
|
|
*
|
|
|
|
|
* Return the average(mean) of elements as CvScalar. Independently for each channel.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_avg(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mask, mean;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &mask);
|
|
|
|
|
|
|
|
|
|
return cCvScalar::new_object(cvAvg(CVARR(self), MASK(mask)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* avg_sdv(<i>mask</i>) -> [mean(as scalar), std_dev(as scalar)]
|
|
|
|
|
*
|
|
|
|
|
* Calculates the average value and standard deviation of array elements, independently for each channel.
|
|
|
|
|
*
|
|
|
|
|
* note: same as [CvMat#avg, CvMat#sdv]
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_avg_sdv(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mask, mean, std_dev;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &mask);
|
|
|
|
|
mean = cCvScalar::new_object();
|
|
|
|
|
std_dev = cCvScalar::new_object();
|
|
|
|
|
cvAvgSdv(CVARR(self), CVSCALAR(mean), CVSCALAR(std_dev), MASK(mask));
|
|
|
|
|
return rb_ary_new3(2, mean, std_dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sdv(<i>[mask]</i>) -> std_dev(as scalar)
|
|
|
|
|
*
|
|
|
|
|
* Return the standard deviation of elements as CvScalar. Independently for each channel.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sdv(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mask, std_dev;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &mask);
|
|
|
|
|
std_dev = cCvScalar::new_object();
|
|
|
|
|
cvAvgSdv(CVARR(self), NULL, CVSCALAR(std_dev), MASK(mask));
|
|
|
|
|
return std_dev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* min_max_loc(<i>[mask]</i>) -> [min_val, max_val, min_loc(as point), max_loc(as point)]
|
|
|
|
|
*
|
|
|
|
|
* Finds minimum and maximum element values and their positions.
|
|
|
|
|
* The extremums are searched over the whole array, selected ROI(in case of IplImage) or, if mask is not NULL, in the specified array region.
|
|
|
|
|
* If the array has more than one channel, it must be IplImage with COI set.
|
|
|
|
|
* In case if multi-dimensional arrays min_loc.x and max_loc.x will contain raw (linear) positions of the extremums.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_min_max_loc(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mask, min_loc, max_loc;
|
|
|
|
|
double min_val = 0.0, max_val = 0.0;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &mask);
|
|
|
|
|
min_loc = cCvPoint::new_object();
|
|
|
|
|
max_loc = cCvPoint::new_object();
|
|
|
|
|
cvMinMaxLoc(CVARR(self), &min_val, &max_val, CVPOINT(min_loc), CVPOINT(max_loc), MASK(mask));
|
|
|
|
|
return rb_ary_new3(4,
|
|
|
|
|
rb_float_new(min_val),
|
|
|
|
|
rb_float_new(max_val),
|
|
|
|
|
min_loc,
|
|
|
|
|
max_loc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dot_product(<i>mat</i>) -> float
|
|
|
|
|
*
|
|
|
|
|
* Calculates dot product of two arrays in Euclidian metrics.
|
|
|
|
|
* <i>mat</i> should be CvMat have same size and same type.
|
|
|
|
|
*
|
|
|
|
|
* src1.src2 = sum(src1(I) * src2(I))
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dot_product(VALUE self, VALUE mat)
|
|
|
|
|
{
|
|
|
|
|
if (!rb_obj_is_kind_of(mat, rb_klass))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be CvMat.");
|
|
|
|
|
return rb_float_new(cvDotProduct(CVARR(self), CVARR(mat)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* cross_product(<i>mat</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculate cross product of two 3D vectors.
|
|
|
|
|
* <i>mat</i> should be CvMat have same size and same type.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_cross_product(VALUE self, VALUE mat)
|
|
|
|
|
{
|
|
|
|
|
if (!rb_obj_is_kind_of(mat, rb_klass))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument should be CvMat.");
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvCrossProduct(CVARR(self), CVARR(mat), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* transform(<i>transmat[,shiftvec]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* performs matrix transform of every element.
|
|
|
|
|
* dst(I) = transmat * src(I) + shiftvec
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_transform(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE transmat, shiftvec;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &transmat, &shiftvec);
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
2011-01-05 13:55:34 -05:00
|
|
|
|
if (NIL_P(shiftvec))
|
|
|
|
|
cvTransform(CVARR(self), CVARR(dest), CVMAT(transmat), NULL);
|
|
|
|
|
else
|
|
|
|
|
cvTransform(CVARR(self), CVARR(dest), CVMAT(transmat), CVMAT(shiftvec));
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* perspective_transform(<i>mat</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return performed perspective matrix transform of vector array.
|
|
|
|
|
* <i>mat</i> should be 3x3 or 4x4 transform matrix (CvMat).
|
|
|
|
|
* Every element (by treating it as 2D or 3D vector) in the following way:
|
|
|
|
|
* (x, y, z) -> (x'/w, y'/w, z'/w) or
|
|
|
|
|
* (x, y) -> (x'/w, y'/w)
|
|
|
|
|
* where
|
|
|
|
|
* (x', y', z', w') = mat4x4*(x, y, z, 1) or
|
|
|
|
|
* (x', y', w') = mat3x3*(x, y, 1)
|
|
|
|
|
* and
|
|
|
|
|
* w = w' if w'!=0, inf otherwise.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_perspective_transform(VALUE self, VALUE mat)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvPerspectiveTransform(CVARR(self), CVARR(dest), CVMAT(mat));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* mul_transposed(<i>:order => :default or :inverse, :delta => nil or cvmat</i>)
|
|
|
|
|
*
|
|
|
|
|
* Calculates the product of self and its transposition.
|
|
|
|
|
*
|
|
|
|
|
* options
|
|
|
|
|
* * :order -> should be :default or :inverse (default is :default)
|
|
|
|
|
* see below.
|
|
|
|
|
* * :delta -> should be nil or CvMat (default is nil)
|
|
|
|
|
* An optional array, subtracted from source before multiplication.
|
|
|
|
|
*
|
|
|
|
|
* mul_transposed evaluates:
|
|
|
|
|
* :order => :default
|
|
|
|
|
* dst = (self - delta) * (self - delta)T
|
|
|
|
|
* :order => :inverse
|
|
|
|
|
* dst = (self - delta)T * (self - delta)
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mul_transposed(VALUE self, VALUE args)
|
|
|
|
|
{
|
|
|
|
|
//VALUE options = extract_options_from_args_bang(args);
|
|
|
|
|
//assert_valid_keys(options, 2, "order", "delta");
|
|
|
|
|
//VALUE order;
|
|
|
|
|
//OPTIONS(order, options, "order", ID2SYM(rb_intern("default")));
|
|
|
|
|
//ID2SYM(rb_intern("order")), rb_intern("")
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* trace -> scalar
|
|
|
|
|
*
|
|
|
|
|
* Returns trace of matrix. "trace" is sum of diagonal elements of the matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_trace(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return cCvScalar::new_object(cvTrace(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* transpose -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return transposed matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_transpose(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
VALUE dest = new_object(size.width, size.height, cvGetElemType(CVARR(self)));
|
|
|
|
|
cvTranspose(CVARR(self), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* transpose! -> self
|
|
|
|
|
*
|
|
|
|
|
* Transposed matrix.
|
|
|
|
|
*
|
|
|
|
|
* <b>rectangular matrix only (CvMat#square? = true).</b>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_transpose_bang(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
cvTranspose(CVARR(self), CVARR(self));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* det -> float
|
|
|
|
|
*
|
|
|
|
|
* Return determinant of matrix.
|
|
|
|
|
* <i>self</i> should be single-channel and floating-point depth.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_det(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_float_new(cvDet(CVARR(self)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* invert(<i>inversion_method=:lu[,delta]</i>) -> float
|
|
|
|
|
*
|
|
|
|
|
* Finds inverse or pseudo-inverse of matrix.
|
|
|
|
|
* <i>inversion_method</i> should be following symbol.
|
|
|
|
|
* * :lu
|
|
|
|
|
* Gaussian elimincation with optimal pivot element chose.
|
|
|
|
|
* Return self determinant (self must be square).
|
|
|
|
|
* * :svd
|
|
|
|
|
* Singular value decomposition(SVD) method.
|
|
|
|
|
* Return the inversed condition number of self(ratio of the smallest singular value to the largest singular value)
|
|
|
|
|
* and 0 if self is all zeros. The SVD method calculate a pseudo-inverse matrix if self is singular.
|
|
|
|
|
* * :svd_sym or :svd_symmetric
|
|
|
|
|
* SVD method for a symmetric positively-defined matrix.
|
|
|
|
|
*
|
|
|
|
|
* <i>self</i> type should be single-channel and floating-point matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_invert(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE symbol;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &symbol);
|
|
|
|
|
int method = CVMETHOD("INVERSION_METHOD", symbol, CV_LU);
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvInvert(CVARR(self), CVARR(dest), method);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* solve(<i>mat, inversion_method=:lu</i>)
|
|
|
|
|
*
|
|
|
|
|
* Solves linear system or least-squares problem (the latter is possible with SVD method).
|
|
|
|
|
*
|
|
|
|
|
* <i>inversion_method</i> should be following symbol.
|
|
|
|
|
* * :lu
|
|
|
|
|
* Gaussian elimincation with optimal pivot element chose.
|
|
|
|
|
* Return self determinant (self must be square).
|
|
|
|
|
* * :svd
|
|
|
|
|
* Singular value decomposition(SVD) method.
|
|
|
|
|
* Return the inversed condition number of self(ratio of the smallest singular value to the largest singular value)
|
|
|
|
|
* and 0 if self is all zeros. The SVD method calculate a pseudo-inverse matrix if self is singular.
|
|
|
|
|
* * :svd_sym or :svd_symmetric
|
|
|
|
|
* SVD method for a symmetric positively-defined matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_solve(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mat, symbol;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &mat, &symbol);
|
|
|
|
|
if (!rb_obj_is_kind_of(mat, rb_klass))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (right-hand part of the linear system) should be %s.)", rb_class2name(rb_klass));
|
2011-01-08 12:09:40 -05:00
|
|
|
|
VALUE dest = new_object(CVMAT(self)->rows, CVMAT(mat)->cols, cvGetElemType(CVARR(self)));
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvSolve(CVARR(self), CVARR(mat), CVARR(dest), CVMETHOD("INVERSION_METHOD", symbol, CV_LU));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* svd(u = nil, v = nil</i>)
|
|
|
|
|
*
|
|
|
|
|
* not implementated.
|
|
|
|
|
* Performs singular value decomposition of real floating-point matrix.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_svd(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
rb_raise(rb_eNotImpError, "");
|
|
|
|
|
/*
|
|
|
|
|
VALUE u = Qnil, v = Qnil;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &u, &v);
|
|
|
|
|
CvMat
|
|
|
|
|
*matU = NIL_P(u) ? NULL : CVARR(u),
|
|
|
|
|
*matV = NIL_P(v) ? NULL : CVARR(v);
|
|
|
|
|
cvSVD(CVARR(self), matU, matV);
|
|
|
|
|
return dest;
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* svbksb
|
|
|
|
|
*
|
|
|
|
|
* not yet.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_svbksb(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
rb_raise(rb_eNotImpError, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* eigenvv!(<i>[eps = 0.0]</i>) -> [eigen_vectors(cvmat), eigen_values(cvmat)]
|
|
|
|
|
*
|
|
|
|
|
* Computes eigenvalues and eigenvectors of symmetric matrix.
|
|
|
|
|
* <i>self</i> should be symmetric square matrix. <i>self</i> is modified during the processing.
|
|
|
|
|
*
|
|
|
|
|
* self * eigen_vectors(i,:)' = eigen_values(i) * eigen_vectors(i,:)'
|
|
|
|
|
*
|
|
|
|
|
* Currently the function is slower than #svd yet less accurate, so if <i>self</i> is known to be positively-defined
|
|
|
|
|
* (e.g., it is a convariation matrix), it is recommanded to use #svd to find eigenvalues and eigenvectors of <i>self</i>,
|
|
|
|
|
* especially if eigenvectors are not required.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
2011-01-08 13:05:52 -05:00
|
|
|
|
rb_eigenvv(int argc, VALUE *argv, VALUE self)
|
2008-08-19 11:01:28 -04:00
|
|
|
|
{
|
2011-01-08 13:05:52 -05:00
|
|
|
|
VALUE epsilon, lowindex, highindex;
|
|
|
|
|
rb_scan_args(argc, argv, "03", &epsilon, &lowindex, &highindex);
|
|
|
|
|
double eps = (NIL_P(epsilon)) ? 0.0 : NUM2DBL(epsilon);
|
|
|
|
|
int lowidx = (NIL_P(lowindex)) ? -1 : NUM2INT(lowindex);
|
|
|
|
|
int highidx = (NIL_P(highindex)) ? -1 : NUM2INT(highindex);
|
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
int type = cvGetElemType(CVARR(self));
|
|
|
|
|
VALUE eigen_vectors = new_object(size, type), eigen_values = new_object(size.height, 1, type);
|
2011-01-08 13:05:52 -05:00
|
|
|
|
cvEigenVV(CVARR(self), CVARR(eigen_vectors), CVARR(eigen_values), eps, lowidx, highidx);
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return rb_ary_new3(2, eigen_vectors, eigen_values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* calc_covar_matrix()
|
|
|
|
|
*
|
|
|
|
|
* not yet.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_calc_covar_matrix(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
rb_raise(rb_eNotImpError, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* mahalonobis(vec, mat) -> float
|
|
|
|
|
*
|
|
|
|
|
* not yet.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mahalonobis(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
rb_raise(rb_eNotImpError, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dft(<i>anyflags...</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs forward or inverse Discrete Fourier Transform(DFT) of 1D or 2D floating-point array.
|
|
|
|
|
* Argument should be following symbol or combination of these.
|
|
|
|
|
*
|
|
|
|
|
* * :forward or :inverse
|
|
|
|
|
* Do forward or inverse transform. The result is not scaled.
|
|
|
|
|
* * :scale
|
|
|
|
|
* Scale the result: divide it by the number of array elements.
|
|
|
|
|
* * :rows
|
|
|
|
|
* Do forward or inverse transform of every individual row of the self.
|
|
|
|
|
* This flag allow user to transofrm multiple vectors simulaneously and can be used to decrease the overhand
|
|
|
|
|
* (which sometimes several times larger then the processing itself), to do 3D and higher-dimensional transforms etc.
|
|
|
|
|
*
|
|
|
|
|
* e.g.
|
|
|
|
|
* mat.dft(:inverse)
|
|
|
|
|
* mat.dft(:forward, :scale) etc...
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dft(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int type = CV_DXT_FORWARD;
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
|
type |= CVMETHOD("DXT_FLAG", argv[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvDFT(CVARR(self), CVARR(dest), type);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dct(<i>anyflags...</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs forward or inverse Discrete Cosine Transform(DCT) of 1D or 2D floating-point array.
|
|
|
|
|
* Argument should be following symbol or combination of these.
|
|
|
|
|
*
|
|
|
|
|
* * :forward or :inverse
|
|
|
|
|
* Do forward or inverse transform.
|
|
|
|
|
* * :rows
|
|
|
|
|
* Do forward or inverse transform of every individual row of the self.
|
|
|
|
|
* This flag allow user to transofrm multiple vectors simulaneously and can be used to decrease the overhand
|
|
|
|
|
* (which sometimes several times larger then the processing itself), to do 3D and higher-dimensional transforms etc.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dct(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
int type = CV_DXT_FORWARD;
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
|
type |= CVMETHOD("DXT_FLAG", argv[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvDCT(CVARR(self), CVARR(dest), type);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* line(<i>p1, p2[, drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn a line segment connecting two points.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_option</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Line color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Line Thickness.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the line:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the point coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*
|
|
|
|
|
* for example
|
|
|
|
|
* mat = CvMat.new(100, 100)
|
|
|
|
|
* mat.line(CvPoint.new(10, 10), CvPoint.new(90, 90), :thickness => 3, :line_type => :aa)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_line(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_line_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* line!(<i>p1, p2[, drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws a line segment connecting two points.
|
|
|
|
|
* Same as CvMat#line, but modifies the receiver in place.
|
|
|
|
|
* see CvMat#line
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_line_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE p1, p2, drawing_option;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option);
|
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
|
|
|
|
cvLine(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2),
|
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* rectangle(<i>p1, p2[, drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn a rectangle with two opposite corners <i>p1</i> and <i>p2</i>.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_options</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Line color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Thickness of lines that make up the rectangle.
|
|
|
|
|
* Negative values make the function to draw a filled rectangle.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the line:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the point coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rectangle(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_rectangle_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* rectangle!(<i>p1, p2[, drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws simple, thick or filled rectangle.
|
|
|
|
|
* Same as CvMat#rectangle, but modifies the receiver in place.
|
|
|
|
|
* see CvMat#rectangle
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rectangle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE p1, p2, drawing_option;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &p1, &p2, &drawing_option);
|
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
|
|
|
|
cvRectangle(CVARR(self), VALUE_TO_CVPOINT(p1), VALUE_TO_CVPOINT(p2),
|
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* circle(<i>center, radius[,drawing_option]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn a simple or filled circle with given center and radius.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_options</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Circle color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Thickness of the circle outline if positive, otherwise that a filled circle has to be drawn.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the circle boundary:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the center coordinates and radius value.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_circle(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_circle_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* circle!(<i>center, radius[,drawing_option]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Draw a circle.
|
|
|
|
|
* Same as CvMat#circle, but modifies the receiver in place.
|
|
|
|
|
*
|
|
|
|
|
* see CvMat#circle
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_circle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE center, radius, drawing_option;
|
|
|
|
|
rb_scan_args(argc, argv, "21", ¢er, &radius, &drawing_option);
|
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
|
|
|
|
cvCircle(CVARR(self), VALUE_TO_CVPOINT(center), NUM2INT(radius),
|
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ellipse(<i>center, axis, angle, start_angle, end_angle[,drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn a simple or thick elliptic arc or fills an ellipse sector.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_options</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Ellipse color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Thickness of the ellipse arc.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the ellipse boundary:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the center coordinates and axes' value.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ellipse(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_ellipse_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ellipse!(<i>center, axis, angle, start_angle, end_angle[,drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws simple or thick elliptic arc or fills ellipse sector.
|
|
|
|
|
* Same as CvMat#ellipse, but modifies the receiver in place.
|
|
|
|
|
*
|
|
|
|
|
* see CvMat#ellipse
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ellipse_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE center, axis, angle, start_angle, end_angle, drawing_option;
|
|
|
|
|
rb_scan_args(argc, argv, "51", ¢er, &axis, &angle, &start_angle, &end_angle, &drawing_option);
|
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
|
|
|
|
cvEllipse(CVARR(self), VALUE_TO_CVPOINT(center),
|
|
|
|
|
VALUE_TO_CVSIZE(axis),
|
|
|
|
|
NUM2DBL(angle), NUM2DBL(start_angle), NUM2DBL(end_angle),
|
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ellipse_box(<i>box[, drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn a simple or thick ellipse outline, or fills an ellipse.
|
|
|
|
|
* The method provides a convenient way to draw an ellipse approximating some shape.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_options</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Ellipse color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Thickness of the ellipse drawn.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the ellipse boundary:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the box vertex coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ellipse_box(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_ellipse_box_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* ellipse_box!(<i>box[, drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws simple or thick elliptic arc or fills ellipse sector.
|
|
|
|
|
* Same as CvMat#ellipse_box, but modifies the receiver in place.
|
|
|
|
|
*
|
|
|
|
|
* see CvMat#ellipse_box
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_ellipse_box_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE box, drawing_option;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &box, &drawing_option);
|
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
|
|
|
|
cvEllipseBox(CVARR(self), VALUE_TO_CVBOX2D(box),
|
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill_poly(<i>points[,drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is filled an area bounded by several polygonal contours.
|
|
|
|
|
* The method fills complex areas, for example, areas with holes, contour self-intersection, etc.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill_poly(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_fill_poly_bang(argc, argv, self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill_poly!(<i>points[,drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Fills polygons interior.
|
|
|
|
|
* Same as CvMat#fill_poly, but modifies the receiver in place.
|
|
|
|
|
*
|
|
|
|
|
* drawing_options should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Polygon color.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the polygon boundaries:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the vertex coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill_poly_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
2011-01-09 16:42:55 -05:00
|
|
|
|
VALUE polygons, drawing_option;
|
|
|
|
|
VALUE points;
|
|
|
|
|
int i, j;
|
|
|
|
|
int num_polygons;
|
|
|
|
|
int *num_points;
|
|
|
|
|
CvPoint **p;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &polygons, &drawing_option);
|
|
|
|
|
// TODO: Check type of argument
|
2008-08-19 11:01:28 -04:00
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
2011-01-09 16:42:55 -05:00
|
|
|
|
num_polygons = RARRAY_LEN(polygons);
|
|
|
|
|
num_points = ALLOCA_N(int, num_polygons);
|
|
|
|
|
p = ALLOCA_N(CvPoint*, num_polygons);
|
|
|
|
|
for (j = 0; j < num_polygons; j++) {
|
|
|
|
|
points = rb_ary_entry(polygons, j);
|
|
|
|
|
num_points[j] = RARRAY_LEN(points);
|
|
|
|
|
p[j] = ALLOCA_N(CvPoint, num_points[j]);
|
|
|
|
|
for (i = 0; i < num_points[j]; i++) {
|
|
|
|
|
p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i));
|
|
|
|
|
}
|
2008-08-19 11:01:28 -04:00
|
|
|
|
}
|
2011-01-09 16:42:55 -05:00
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvFillPoly(CVARR(self),
|
2011-01-09 16:42:55 -05:00
|
|
|
|
p,
|
|
|
|
|
num_points,
|
|
|
|
|
num_polygons,
|
2008-08-19 11:01:28 -04:00
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
2011-01-09 16:42:55 -05:00
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill_convex_poly(<i>points[,drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image is filled convex polygon interior.
|
|
|
|
|
* This method is much faster than The function CvMat#fill_poly
|
|
|
|
|
* and can fill not only the convex polygons but any monotonic polygon,
|
|
|
|
|
* i.e. a polygon whose contour intersects every horizontal line (scan line)
|
|
|
|
|
* twice at the most.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_options</i> should be Hash include these keys.
|
|
|
|
|
* :color
|
|
|
|
|
* Polygon color.
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of the polygon boundaries:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the vertex coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill_convex_poly(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_fill_convex_poly_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* fill_convex_poly!(<i>points[,drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Fills convex polygon.
|
|
|
|
|
* Same as CvMat#fill_convex_poly, but modifies the receiver in place.
|
|
|
|
|
*
|
2011-01-09 16:42:55 -05:00
|
|
|
|
* see CvMat#fill_convex_poly
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_fill_convex_poly_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE points, drawing_option;
|
2011-01-09 16:42:55 -05:00
|
|
|
|
int i, num_points;
|
|
|
|
|
CvPoint *p;
|
2008-08-19 11:01:28 -04:00
|
|
|
|
rb_scan_args(argc, argv, "11", &points, &drawing_option);
|
2011-01-09 16:42:55 -05:00
|
|
|
|
// TODO: Check type of argument
|
2008-08-19 11:01:28 -04:00
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
2011-01-09 16:42:55 -05:00
|
|
|
|
num_points = RARRAY_LEN(points);
|
|
|
|
|
p = ALLOCA_N(CvPoint, num_points);
|
|
|
|
|
for (i = 0; i < num_points; i++)
|
|
|
|
|
p[i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i));
|
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvFillConvexPoly(CVARR(self),
|
|
|
|
|
p,
|
2011-01-09 16:42:55 -05:00
|
|
|
|
num_points,
|
2008-08-19 11:01:28 -04:00
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* poly_line(<i>points[,drawing_option]</i>) -> mat
|
|
|
|
|
*
|
|
|
|
|
* Return image drawed a single or multiple polygonal curves.
|
|
|
|
|
*
|
|
|
|
|
* <i>drawing_option</i> should be Hash include these keys.
|
|
|
|
|
* :is_closed
|
|
|
|
|
* Indicates whether the polylines must be drawn closed.
|
|
|
|
|
* If closed, the method draws the line from the last vertex
|
|
|
|
|
* of every contour to the first vertex.
|
|
|
|
|
* :color
|
|
|
|
|
* Polyline color.
|
|
|
|
|
* :thickness
|
|
|
|
|
* Thickness of the polyline edges
|
|
|
|
|
* :line_type
|
|
|
|
|
* Type of line segments:
|
|
|
|
|
* * 0 or 8 - 8-connected line(default).
|
|
|
|
|
* * 4 - 4-connected line.
|
|
|
|
|
* * negative-value - antialiased line.
|
|
|
|
|
* :shift
|
|
|
|
|
* Number of fractional bits in the vertex coordinates.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>drawing_option</i>'s default value is CvMat::DRAWING_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_poly_line(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_poly_line_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* poly_line!(<i>points[,drawing_option]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws simple or thick polygons.
|
|
|
|
|
*
|
|
|
|
|
* Same as CvMat#poly_line, but modifies the receiver in place.
|
|
|
|
|
*
|
|
|
|
|
* see CvMat#poly_line
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_poly_line_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
2011-01-09 16:42:55 -05:00
|
|
|
|
VALUE polygons, drawing_option;
|
|
|
|
|
VALUE points;
|
|
|
|
|
int i, j;
|
|
|
|
|
int num_polygons;
|
|
|
|
|
int *num_points;
|
|
|
|
|
CvPoint **p;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &polygons, &drawing_option);
|
|
|
|
|
// TODO: Check type of argument
|
2008-08-19 11:01:28 -04:00
|
|
|
|
drawing_option = DRAWING_OPTION(drawing_option);
|
2011-01-09 16:42:55 -05:00
|
|
|
|
num_polygons = RARRAY_LEN(polygons);
|
|
|
|
|
num_points = ALLOCA_N(int, num_polygons);
|
|
|
|
|
p = ALLOCA_N(CvPoint*, num_polygons);
|
|
|
|
|
for (j = 0; j < num_polygons; j++) {
|
|
|
|
|
points = rb_ary_entry(polygons, j);
|
|
|
|
|
num_points[j] = RARRAY_LEN(points);
|
|
|
|
|
p[j] = ALLOCA_N(CvPoint, num_points[j]);
|
|
|
|
|
for (i = 0; i < num_points[j]; i++) {
|
|
|
|
|
p[j][i] = VALUE_TO_CVPOINT(rb_ary_entry(points, i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
cvPolyLine(CVARR(self),
|
2011-01-09 16:42:55 -05:00
|
|
|
|
p,
|
|
|
|
|
num_points,
|
|
|
|
|
num_polygons,
|
2008-08-19 11:01:28 -04:00
|
|
|
|
DO_IS_CLOSED(drawing_option),
|
2011-01-09 16:42:55 -05:00
|
|
|
|
DO_COLOR(drawing_option),
|
|
|
|
|
DO_THICKNESS(drawing_option),
|
2008-08-19 11:01:28 -04:00
|
|
|
|
DO_LINE_TYPE(drawing_option),
|
|
|
|
|
DO_SHIFT(drawing_option));
|
|
|
|
|
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-09 16:42:55 -05:00
|
|
|
|
|
2008-08-19 11:01:28 -04:00
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* put_text(<i>str, point, font[,color]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return image is drawn text string.
|
|
|
|
|
* <i>font</i> should be CvFont object.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_put_text(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_put_text_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* put_text!(<i>str, point ,font[,color]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Draws text string. Return self.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_put_text_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE text, point, font, color;
|
|
|
|
|
rb_scan_args(argc, argv, "22", &text, &point, &font, &color);
|
|
|
|
|
cvPutText(CVARR(self), StringValueCStr(text), VALUE_TO_CVPOINT(point), CVFONT(font), *CVSCALAR(color));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sobel(<i>xorder,yorder[,aperture_size=3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculates first, second, third or mixed image derivatives using extended Sobel operator.
|
|
|
|
|
* <i>self</i> should be single-channel 8bit signed/unsigned or 32bit floating-point.
|
|
|
|
|
*
|
|
|
|
|
* link:../images/CvMat_sobel.png
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sobel(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE xorder, yorder, aperture_size, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "21", &xorder, &yorder, &aperture_size) < 3)
|
|
|
|
|
aperture_size = INT2FIX(3);
|
|
|
|
|
switch(CV_MAT_DEPTH(CVMAT(self)->type)) {
|
|
|
|
|
case CV_8U:
|
|
|
|
|
case CV_8S:
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_16S, 1));
|
|
|
|
|
break;
|
|
|
|
|
case CV_32F:
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eNotImpError, "source depth should be CV_8U or CV_8S or CV_32F.");
|
|
|
|
|
}
|
|
|
|
|
cvSobel(CVARR(self), CVARR(dest), NUM2INT(xorder), NUM2INT(yorder), NUM2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* laplace(<i>[aperture_size = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculates Laplacian of the image.
|
|
|
|
|
* <i>self</i> should be single-channel 8bit signed/unsigned or 32bit floating-point.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_laplace(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE aperture_size, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &aperture_size) < 1)
|
|
|
|
|
aperture_size = INT2FIX(3);
|
|
|
|
|
switch(CV_MAT_DEPTH(CVMAT(self)->type)) {
|
|
|
|
|
case CV_8U:
|
|
|
|
|
case CV_8S:
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_16S, 1));
|
|
|
|
|
break;
|
|
|
|
|
case CV_32F:
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eNotImpError, "source depth should be CV_8U or CV_8S or CV_32F.");
|
|
|
|
|
}
|
|
|
|
|
cvLaplace(CVARR(self), CVARR(dest), NUM2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* canny(<i>thresh1,thresh2[,aperture_size = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Canny algorithm for edge detection.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_canny(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE thresh1, thresh2, aperture_size;
|
|
|
|
|
if (rb_scan_args(argc, argv, "21", &thresh1, &thresh2, &aperture_size) < 3)
|
|
|
|
|
aperture_size = INT2FIX(3);
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvCanny(CVARR(self), CVARR(dest), NUM2INT(thresh1), NUM2INT(thresh2), NUM2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* pre_corner_detect(<i>[aperture_size = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculates feature map for corner detection.
|
|
|
|
|
* <i>aperture_size</i> is parameter for sobel operator(see #sobel).
|
|
|
|
|
*
|
|
|
|
|
* The corners can be found as local maximums of the function.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_pre_corner_detect(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE aperture_size, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &aperture_size) < 1)
|
|
|
|
|
aperture_size = INT2FIX(3);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cvPreCornerDetect(CVARR(self), CVARR(dest), NUM2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* corner_eigenvv(<i>block_size[,aperture_size]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* For every pixel considers <i>block_size x block_size</i> neighborhood S(p).
|
|
|
|
|
* It calculates convariation matrix of derivatives over the neighborhood.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_corner_eigenvv(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE block_size, aperture_size, dest;
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &block_size, &aperture_size) < 1)
|
|
|
|
|
aperture_size = INT2FIX(3);
|
|
|
|
|
Check_Type(block_size, T_FIXNUM);
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
dest = new_object(cvSize(size.width * 6, size.height), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cvCornerEigenValsAndVecs(CVARR(self), CVARR(dest), NUM2INT(block_size), NUM2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* corner_min_eigen_val(<i>block_size[,aperture_size = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Calculates minimal eigenvalue of gradient matrices for corner detection.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_corner_min_eigen_val(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE block_size, aperture_size, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &block_size, &aperture_size);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cvCornerMinEigenVal(CVARR(self), CVARR(dest), FIX2INT(block_size), FIX2INT(aperture_size));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* corner_harris(<i>block_size[,aperture_size = 3][,k = 0.04]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return image Applied Harris edge detector.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_corner_harris(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE block_size, aperture_size, k, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "12", &block_size, &aperture_size, &k);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cvCornerHarris(CVARR(self), CVARR(dest), FIX2INT(block_size), IF_INT(aperture_size, 3), IF_DBL(k, 0.04));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* find_corner_sub_pix(<i></i>)
|
|
|
|
|
*
|
|
|
|
|
* Refines corner locations.
|
|
|
|
|
* This method iterates to find the sub-pixel accurate location of corners,
|
|
|
|
|
* or radial saddle points, as shown in on the picture below.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rbi_find_corner_sub_pix(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
VALUE corners, win, zero_zone, criteria;
|
|
|
|
|
rb_scan_args(argc, argv, "13", &corners, &win, &zero_zone, &criteria);
|
|
|
|
|
if (!rb_obj_is_kind_of(corners, mPointSet::rb_module()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (corners) should be %s.", rb_class2name(mPointSet::rb_module()));
|
|
|
|
|
int count = CVSEQ(corners)->total;
|
|
|
|
|
VALUE storage = cCvMemStorage::new_object();
|
|
|
|
|
CvPoint2D32f *pointset = POINTSET2D32f(corners);
|
|
|
|
|
//cvFindCornerSubPix(CVARR(self), pointset, count, VALUE_TO_CVSIZE(win), VALUE_TO_CVSIZE(zero_zone), VALUE_TO_CVTERMCRITERIA(criteria));
|
|
|
|
|
//return cCvSeq::new_sequence();
|
|
|
|
|
*/
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
rb_good_features_to_track(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE quality_level, min_distance, good_features_to_track_option, eigen, tmp, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &quality_level, &min_distance, &good_features_to_track_option);
|
|
|
|
|
good_features_to_track_option = GOOD_FEATURES_TO_TRACK_OPTION(good_features_to_track_option);
|
|
|
|
|
CvMat *src = CVMAT(self);
|
|
|
|
|
eigen = cCvMat::new_object(cvGetSize(src), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
tmp = cCvMat::new_object(cvGetSize(src), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
int np = GF_MAX(good_features_to_track_option);
|
|
|
|
|
if(!(np > 0))
|
|
|
|
|
rb_raise(rb_eArgError, "option :max should be positive value.");
|
|
|
|
|
CvPoint2D32f *p32 = (CvPoint2D32f*)cvAlloc(sizeof(CvPoint2D32f) * np);
|
|
|
|
|
if(!p32)
|
|
|
|
|
rb_raise(rb_eNoMemError, "failed allocate memory.");
|
|
|
|
|
cvGoodFeaturesToTrack(src, CVARR(eigen), CVARR(tmp), p32, &np, NUM2DBL(quality_level), NUM2DBL(min_distance),
|
|
|
|
|
GF_MASK(good_features_to_track_option),
|
|
|
|
|
GF_BLOCK_SIZE(good_features_to_track_option),
|
|
|
|
|
GF_USE_HARRIS(good_features_to_track_option),
|
|
|
|
|
GF_K(good_features_to_track_option));
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
CvSeq *pseq = cvCreateSeq(CV_SEQ_POINT_SET, sizeof(CvSeq), sizeof(CvPoint2D32f), CVMEMSTORAGE(storage));
|
|
|
|
|
cvSeqPushMulti(pseq, p32, np);
|
|
|
|
|
cvFree(&p32);
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), pseq, cCvPoint2D32f::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* sample_line(p1, p2[,connectivity = 8]) {|pixel| }
|
|
|
|
|
*
|
|
|
|
|
* not yet.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_sample_line(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
VALUE p1, p2, connectivity;
|
|
|
|
|
if (rb_scan_args(argc, argv, "21", &p1, &p2, &connectivity) < 3)
|
|
|
|
|
connectivity = INT2FIX(8);
|
|
|
|
|
CvPoint point1 = VALUE_TO_CVPOINT(p1), point2 = VALUE_TO_CVPOINT(p2);
|
|
|
|
|
int size;
|
|
|
|
|
switch(FIX2INT(connectivity)) {
|
|
|
|
|
case 4:
|
|
|
|
|
size = abs(point2.x - point1.x) + abs(point2.y - point1.y) + 1;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
size = maxint(abs(point2.x - point1.x) + 1, abs(point2.y - point1.y) + 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eArgError, "argument 3(connectivity) should be 4 or 8. 8 is default.");
|
|
|
|
|
}
|
|
|
|
|
VALUE buf = cCvMat::new_object(1, size, cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSampleLine(CVARR(self), point1, point2, CVMAT(buf)->data.ptr, FIX2INT(connectivity));
|
|
|
|
|
if (rb_block_given_p()) {
|
|
|
|
|
for(int i = 0; i < size; i++) {
|
|
|
|
|
//Data_Wrap_Struct(cCvScalar::rb_class(), 0, 0, CVMAT(buf)->data.ptr[]);
|
|
|
|
|
//rb_yield(cCvScalar::new_object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return buf;
|
|
|
|
|
*/
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* rect_sub_pix(<i>center,size</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Retrieves pixel rectangle from image with sub-pixel accuracy.
|
|
|
|
|
* Extracts pixels from <i>self</i>.
|
|
|
|
|
* dst(x,y) = self(x + center.x - (size.width - 1) * 0.5, y + center.y - (size.height - 1) * 0.5)
|
|
|
|
|
* where the values of pixels at non-integer coordinates are retrived using bilinear iterpolation.
|
|
|
|
|
* Every channel of multiple-channel images is processed independently.
|
|
|
|
|
* Whereas the rectangle center must be inside the image, the whole rectangle may be partially occludedl.
|
|
|
|
|
* In this case, the replication border mode is used to get pixel values beyond the image boundaries.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rect_sub_pix(VALUE self, VALUE center, VALUE size)
|
|
|
|
|
{
|
|
|
|
|
VALUE dest = new_object(VALUE_TO_CVSIZE(size), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvGetRectSubPix(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT2D32F(center));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* quandrangle_sub_pix(<i>map_matrix</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Retrives pixel quadrangle from image with sub-pixel accuracy.
|
|
|
|
|
* Extracts pixel from <i>self</i> at sub-pixel accuracy and store them:
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_quadrangle_sub_pix(VALUE self, VALUE map_matrix, VALUE size)
|
|
|
|
|
{
|
|
|
|
|
if (!rb_obj_is_kind_of(map_matrix, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (map matrix) should be %s (2x3).", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
VALUE dest = new_object(VALUE_TO_CVSIZE(size), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvGetQuadrangleSubPix(CVARR(self), CVARR(dest), CVMAT(map_matrix));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* resize(<i>size[,interpolation = :linear]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Resize image.
|
|
|
|
|
* <i>interpolation</i> is interpolation method:
|
|
|
|
|
* * :nn
|
|
|
|
|
* nearest-neighbor interpolation.
|
|
|
|
|
* * :linear
|
|
|
|
|
* bilinear interpolation (used by default)
|
|
|
|
|
* * :area
|
|
|
|
|
* resampling using pixel area relation. It is preferred method for image decimation that give moire-free results.
|
|
|
|
|
* In case of zooming it is similar to NN method.
|
|
|
|
|
* * :cubic
|
|
|
|
|
* bicubic interpolation.
|
|
|
|
|
* Return <i>self</i> resized image that it fits exactly to <i>size</i>. If ROI is set, the method consideres the ROI as supported as usual.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_resize(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE size, interpolation;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &size, &interpolation);
|
|
|
|
|
VALUE dest = new_object(VALUE_TO_CVSIZE(size), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvResize(CVARR(self), CVARR(dest), CVMETHOD("INTERPOLATION_METHOD", interpolation, CV_INTER_LINEAR));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* warp_affine(<i>map_matrix[,interpolation = :linear][,option = :fill_outliers][,fillval = 0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Applies affine transformation to the image.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_warp_affine(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE map_matrix, interpolation, option, fill_value;
|
|
|
|
|
if (rb_scan_args(argc, argv, "13", &map_matrix, &interpolation, &option, &fill_value) < 4)
|
|
|
|
|
fill_value = INT2FIX(0);
|
|
|
|
|
if (!rb_obj_is_kind_of(map_matrix, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (map matrix) should be %s (2x3).", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvWarpAffine(CVARR(self), CVARR(dest), CVMAT(map_matrix),
|
|
|
|
|
CVMETHOD("INTERPOLATION_METHOD", interpolation, CV_INTER_LINEAR) | CVMETHOD("WARP_FLAG", option, CV_WARP_FILL_OUTLIERS), VALUE_TO_CVSCALAR(fill_value));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.rotation(<i>center,angle,scale</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Create new affine matrix of 2D rotation (2x3 32bit floating-point matrix).
|
|
|
|
|
* <i>center</i> is center of rotation (x, y).
|
|
|
|
|
* <i>angle</i> is rotation angle in degrees.
|
|
|
|
|
* Positive values mean counter-clockwise rotation
|
|
|
|
|
* (the coordinate origin is assumed at top-left corner).
|
|
|
|
|
* <i>scale</i> is isotropic scale factor.
|
|
|
|
|
*
|
|
|
|
|
* [ a b | (1 - a) * center.x - b * center.y ]
|
|
|
|
|
* [-b a | (b * center.x + (1 + a) * center.y ]
|
|
|
|
|
* where a = scale * cos(angle), b = scale * sin(angle)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_rotation(VALUE self, VALUE center, VALUE angle, VALUE scale)
|
|
|
|
|
{
|
|
|
|
|
VALUE map_matrix = new_object(cvSize(3,2), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cv2DRotationMatrix(VALUE_TO_CVPOINT2D32F(center), NUM2DBL(angle), NUM2DBL(scale), CVMAT(map_matrix));
|
|
|
|
|
return map_matrix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* warp_perspective(<i>map_matrix[,interpolation=:linear][,option =:fill_outliers][,fillval=0])</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Applies perspective transformation to the image.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_warp_perspective(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE map_matrix, interpolation, option, fillval;
|
|
|
|
|
if (rb_scan_args(argc, argv, "13", &map_matrix, &interpolation, &option, &fillval) < 4)
|
|
|
|
|
fillval = INT2FIX(0);
|
|
|
|
|
if (!rb_obj_is_kind_of(map_matrix, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (map matrix) should be %s (3x3).", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvWarpPerspective(CVARR(self), CVARR(dest), CVMAT(map_matrix),
|
|
|
|
|
CVMETHOD("INTERPOLATION_METHOD", interpolation, CV_INTER_LINEAR) | CVMETHOD("WARP_FLAG", option, CV_WARP_FILL_OUTLIERS), VALUE_TO_CVSCALAR(fillval));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* remap(<i>mapx,mapy[,interpolation=:linear][,option=:fill_outliers][,fillval=0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Applies generic geometrical transformation to the image.
|
|
|
|
|
* Transforms source image using the specified map:
|
|
|
|
|
* dst(x,y)<-src(mapx(x,y),mapy(x,y))
|
|
|
|
|
* Similar to other geometrical transformations, some interpolation method (specified by user) is used to
|
|
|
|
|
* extract pixels with non-integer coordinates.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_remap(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE mapx, mapy, interpolation, option, fillval;
|
|
|
|
|
if (rb_scan_args(argc, argv, "23", &mapx, &mapy, &interpolation, &option, &fillval) < 5)
|
|
|
|
|
fillval = INT2FIX(0);
|
|
|
|
|
if (!rb_obj_is_kind_of(mapx, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (map of x-coordinates) should be %s(CV_32F and single-channel).", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
if (!rb_obj_is_kind_of(mapy, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 2 (map of y-coordinates) should be %s(CV_32F and single-channel).", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
VALUE dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvRemap(CVARR(self), CVARR(dest), CVARR(mapx), CVARR(mapy),
|
|
|
|
|
CVMETHOD("INTERPOLATION_METHOD", interpolation, CV_INTER_LINEAR) | CVMETHOD("WARP_FLAG", option, CV_WARP_FILL_OUTLIERS), VALUE_TO_CVSCALAR(fillval));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* log_polar(<i>center, magnitude, </i>)
|
|
|
|
|
*
|
|
|
|
|
* Remaps image to log-polar space.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_log_polar(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
VALUE size, center, m, flags, fillval, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "3*", &size, ¢er, &m, &flags);
|
|
|
|
|
dest = cCvMat::new_object();
|
|
|
|
|
cvLogPolar(CVARR(self), CVARR(dest),
|
|
|
|
|
VALUE_TO_CVPOINT2D32F(center), NUM2DBL(m),
|
|
|
|
|
CVMETHOD("INTERPOLATION_METHOD", interpolation, CV_INTER_LINEAR) | CVMETHOD("WARP_FLAG", option, CV_WARP_FILL_OUTLIEARS), VALUE_TO_CVSCALAR(fillval));
|
|
|
|
|
return dest;
|
|
|
|
|
*/
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* erode(<i>[element = nil, iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Create erodes image by using arbitrary structuring element.
|
|
|
|
|
* <i>element</i> is structuring element used for erosion.
|
|
|
|
|
* <i>element</i> should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used.
|
|
|
|
|
* <i>iterations</i> is number of times erosion is applied.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_erode(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_erode_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* erode!(<i>[element = nil][,iteration = 1]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Erodes image by using arbitrary structuring element.
|
|
|
|
|
* see also #erode.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_erode_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
cvErode(CVARR(self), CVARR(self), IPLCONVKERNEL(element), IF_INT(iteration, 1));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dilate(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Create dilates image by using arbitrary structuring element.
|
|
|
|
|
* <i>element</i> is structuring element used for erosion.
|
|
|
|
|
* <i>element</i> should be IplConvKernel. If it is nil, a 3x3 rectangular structuring element is used.
|
|
|
|
|
* <i>iterations</i> is number of times erosion is applied.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dilate(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_dilate_bang(argc, argv, rb_clone(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* dilate!(<i>[element = nil][,iteration = 1]</i>) -> self
|
|
|
|
|
*
|
|
|
|
|
* Dilate image by using arbitrary structuring element.
|
|
|
|
|
* see also #dilate.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_dilate_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
cvDilate(CVARR(self), CVARR(self), IPLCONVKERNEL(element), IF_INT(iteration, 1));
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* morpholohy_open(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs advanced morphological transformations "Opening".
|
|
|
|
|
* dilate(erode(src,element),element)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_morphology_open(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvMorphologyEx(CVARR(self), CVARR(dest), 0, IPLCONVKERNEL(element), CV_MOP_OPEN, IF_INT(iteration, 1));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* morpholohy_close(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs advanced morphological transformations "Closing".
|
|
|
|
|
* erode(dilate(src,element),element)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_morphology_close(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvMorphologyEx(CVARR(self), CVARR(dest), 0, IPLCONVKERNEL(element), CV_MOP_CLOSE, IF_INT(iteration, 1));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* morpholohy_gradient(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs advanced morphological transformations "Morphological gradient".
|
|
|
|
|
* dilate(src,element)-erode(src,element)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_morphology_gradient(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration, temp, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
temp = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvMorphologyEx(CVARR(self), CVARR(dest), CVARR(temp), IPLCONVKERNEL(element), CV_MOP_GRADIENT, IF_INT(iteration, 1));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* morpholohy_tophat(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs advanced morphological transformations "tophat".
|
|
|
|
|
* src-open(src,element)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_morphology_tophat(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvMorphologyEx(CVARR(self), CVARR(dest), 0, IPLCONVKERNEL(element), CV_MOP_TOPHAT, IF_INT(iteration, 1));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* morpholohy_blackhat(<i>[element = nil][,iteration = 1]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Performs advanced morphological transformations "blackhat".
|
|
|
|
|
* close(src,element)-src
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_morphology_blackhat(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE element, iteration, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &element, &iteration);
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvMorphologyEx(CVARR(self), CVARR(dest), 0, IPLCONVKERNEL(element), CV_MOP_BLACKHAT, IF_INT(iteration, 1));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* smooth_blur_no_scale(<i>[p1 = 3, p2 = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Smooths the image by simple blur with no scaling.
|
|
|
|
|
* * 8bit unsigned -> return 16bit unsigned
|
|
|
|
|
* * 8bit signed -> return 16bit signed
|
|
|
|
|
* * 32bit floating point -> return 32bit floating point
|
|
|
|
|
* <b>support single-channel image only.</b>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_smooth_blur_no_scale(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_C1_ONLY(self);
|
|
|
|
|
VALUE p1, p2, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &p1, &p2);
|
|
|
|
|
int type = cvGetElemType(CVARR(self)), dest_type;
|
|
|
|
|
switch (CV_MAT_DEPTH(type)) {
|
|
|
|
|
case CV_8U:
|
|
|
|
|
dest_type = CV_16U;
|
|
|
|
|
break;
|
|
|
|
|
case CV_8S:
|
|
|
|
|
dest_type = CV_16S;
|
|
|
|
|
break;
|
|
|
|
|
case CV_32F:
|
|
|
|
|
dest_type = CV_32F;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eNotImpError, "unsupport format. (support 8bit unsigned/signed or 32bit floating point only)");
|
|
|
|
|
}
|
|
|
|
|
dest = new_object(cvGetSize(CVARR(self)), dest_type);
|
|
|
|
|
cvSmooth(CVARR(self), CVARR(dest), CV_BLUR_NO_SCALE, IF_INT(p1, 3), IF_INT(p2, 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* smooth_blur(<i>[p1 = 3, p2 = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Smooths the image by simple blur.
|
|
|
|
|
* Summation over a pixel <i>p1</i> x <i>p2</i> neighborhood with subsequent scaling by 1 / (p1*p2).
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_smooth_blur(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE p1, p2, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &p1, &p2);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSmooth(CVARR(self), CVARR(dest), CV_BLUR, IF_INT(p1, 3), IF_INT(p2, 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* smooth_gaussian(<i>[p1 = 3, p2 = 3, p3 = 0.0, p4 = 0.0]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Smooths the image by gaussian blur.
|
|
|
|
|
* Convolving image with <i>p1</i> x <i>p2</i> Gaussian kernel.
|
|
|
|
|
*
|
|
|
|
|
* <i>p3</i> may specify Gaussian sigma (standard deviation).
|
|
|
|
|
* If it is zero, it is calculated from the kernel size:
|
|
|
|
|
* sigma = (n/2 - 1)*0.3 + 0.8, where n = p1 for horizontal kernel,
|
|
|
|
|
* n = p2 for vertical kernel.
|
|
|
|
|
*
|
|
|
|
|
* <i>p4</i> is in case of non-square Gaussian kernel the parameter.
|
|
|
|
|
* It may be used to specify a different (from p3) sigma in the vertical direction.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_smooth_gaussian(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE p1, p2, p3, p4, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "04", &p1, &p2, &p3, p4);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSmooth(CVARR(self), CVARR(dest), CV_GAUSSIAN, IF_INT(p1, 3), IF_INT(p2, 0), IF_DBL(p3, 0.0), IF_DBL(p4, 0.0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* smooth_median(<i>[p1 = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Smooths the image by median blur.
|
|
|
|
|
* Finding median of <i>p1</i> x <i>p1</i> neighborhood (i.e. the neighborhood is square).
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_smooth_median(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8U_ONLY(self);
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE p1, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &p1);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSmooth(CVARR(self), CVARR(dest), CV_MEDIAN, IF_INT(p1, 3));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* smooth_bilateral(<i>[p1 = 3][p2 = 3]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Smooths the image by bilateral filter.
|
|
|
|
|
* Applying bilateral 3x3 filtering with color sigma=<i>p1</i> and space sigma=<i>p2</i>.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_smooth_bilateral(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8U_ONLY(self);
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE p1, p2, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &p1, &p2);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvSmooth(CVARR(self), CVARR(dest), CV_BILATERAL, IF_INT(p1, 3), IF_INT(p2, 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* filter2d(<i>kernel[,anchor]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Convolves image with the kernel.
|
|
|
|
|
* Convolution kernel, single-channel floating point matrix (or same depth of self's).
|
|
|
|
|
* If you want to apply different kernels to different channels,
|
|
|
|
|
* split the image using CvMat#split into separate color planes and process them individually.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_filter2d(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE kernel, anchor, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &kernel, &anchor);
|
|
|
|
|
if (!rb_obj_is_kind_of(kernel, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (kernel) should be %s.", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
int type = cvGetElemType(CVARR(kernel));
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvFilter2D(CVARR(self), CVARR(dest), CVMAT(kernel), NIL_P(anchor) ? cvPoint(-1,-1) : VALUE_TO_CVPOINT(anchor));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* copy_make_border_constant(<i>size, offset[,value = CvScalar.new(0)]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Copies image and makes border around it.
|
|
|
|
|
* Border is filled with the fixed value, passed as last parameter of the function.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_copy_make_border_constant(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE size, offset, value, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &size, &offset, &value);
|
|
|
|
|
dest = cCvMat::new_object(VALUE_TO_CVSIZE(size), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvCopyMakeBorder(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT(offset), IPL_BORDER_CONSTANT, NIL_P(value) ? cvScalar(0) : VALUE_TO_CVSCALAR(value));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* copy_make_border_replicate(<i>size, offset</i>)
|
|
|
|
|
*
|
|
|
|
|
* Copies image and makes border around it.
|
|
|
|
|
* The pixels from the top and bottom rows,
|
|
|
|
|
* the left-most and right-most columns are replicated to fill the border.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_copy_make_border_replicate(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE size, offset, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "20", &size, &offset);
|
|
|
|
|
dest = cCvMat::new_object(VALUE_TO_CVSIZE(size), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvCopyMakeBorder(CVARR(self), CVARR(dest), VALUE_TO_CVPOINT(offset), IPL_BORDER_REPLICATE);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* integral(<i>need_sqsum = false, need_tilted_sum = false</i>) -> [cvmat, cvmat or nil, cvmat or nil]
|
|
|
|
|
*
|
|
|
|
|
* Calculates integral images.
|
|
|
|
|
* If <i>need_sqsum</i> = true, calculate the integral image for squared pixel values.
|
|
|
|
|
* If <i>need_tilted_sum</i> = true, calculate the integral for the image rotated by 45 degrees.
|
|
|
|
|
*
|
|
|
|
|
* sum(X,Y)=sumx<X,y<Yimage(x,y)
|
|
|
|
|
* sqsum(X,Y)=sumx<X,y<Yimage(x,y)2
|
|
|
|
|
* tilted_sum(X,Y)=sumy<Y,abs(x-X)<yimage(x,y)
|
|
|
|
|
*
|
|
|
|
|
* Using these integral images, one may calculate sum, mean, standard deviation over arbitrary up-right or rotated rectangular region of the image in a constant time.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_integral(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE sum, sqsum, tilted_sum, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "02", &sqsum, &tilted_sum);
|
|
|
|
|
CvSize size = cvSize(cvGetSize(CVARR(self)).width + 1, cvGetSize(CVARR(self)).height + 1);
|
|
|
|
|
int cn = CV_MAT_CN(cvGetElemType(CVARR(self)));
|
|
|
|
|
sum = cCvMat::new_object(size, CV_MAKETYPE(CV_64F, cn));
|
|
|
|
|
sqsum = (sqsum == Qtrue ? cCvMat::new_object(size, CV_MAKETYPE(CV_64F, cn)) : Qnil);
|
|
|
|
|
tilted_sum = (tilted_sum == Qtrue ? cCvMat::new_object(size, CV_MAKETYPE(CV_64F, cn)) : Qnil);
|
|
|
|
|
cvIntegral(CVARR(self), CVARR(sum), NIL_P(sqsum) ? NULL : CVARR(sqsum), NIL_P(tilted_sum) ? NULL : CVARR(tilted_sum));
|
|
|
|
|
dest = rb_ary_new3(1, sum);
|
|
|
|
|
if(sqsum)
|
|
|
|
|
rb_ary_push(dest, sqsum);
|
|
|
|
|
if(tilted_sum)
|
|
|
|
|
rb_ary_push(dest, tilted_sum);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* threshold_binary(<i>threshold, max_value[,use_otsu = false]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Applies fixed-level threshold to array elements.
|
|
|
|
|
*
|
|
|
|
|
* dst(x,y) = max_value, if src(x,y)>threshold
|
|
|
|
|
* 0, otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_threshold_binary(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE threshold, max_value, use_otsu, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &threshold, &max_value, &use_otsu);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvThreshold(CVARR(self), CVARR(dest), NUM2DBL(threshold), NUM2DBL(max_value), CV_THRESH_BINARY | (use_otsu == Qtrue ? CV_THRESH_OTSU : 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* threshold_binary_inverse(<i>threshold, max_value[,use_otsu = false]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Applies fixed-level threshold to array elements.
|
|
|
|
|
*
|
|
|
|
|
* dst(x,y) = 0, if src(x,y)>threshold
|
|
|
|
|
* max_value, otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_threshold_binary_inverse(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE threshold, max_value, use_otsu, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &threshold, &max_value, &use_otsu);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvThreshold(CVARR(self), CVARR(dest), NUM2DBL(threshold), NUM2DBL(max_value), CV_THRESH_BINARY_INV | (use_otsu == Qtrue ? CV_THRESH_OTSU : 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* threshold_trunc(<i>threshold[,use_otsu = false]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Applies fixed-level threshold to array elements.
|
|
|
|
|
*
|
|
|
|
|
* dst(x,y) = threshold, if src(x,y)>threshold
|
|
|
|
|
* src(x,y), otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_threshold_trunc(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE threshold, use_otsu, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &threshold, &use_otsu);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvThreshold(CVARR(self), CVARR(dest), NUM2DBL(threshold), 0, CV_THRESH_BINARY_INV | (use_otsu == Qtrue ? CV_THRESH_OTSU : 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* threshold_to_zero(<i>threshold[,use_otsu = false]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Applies fixed-level threshold to array elements.
|
|
|
|
|
*
|
|
|
|
|
* dst(x,y) = src(x,y), if src(x,y)>threshold
|
|
|
|
|
* 0, otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_threshold_to_zero(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE threshold, use_otsu, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &threshold, &use_otsu);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvThreshold(CVARR(self), CVARR(dest), NUM2DBL(threshold), 0, CV_THRESH_TOZERO | (use_otsu == Qtrue ? CV_THRESH_OTSU : 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* threshold_to_zero_inverse(<i>threshold[,use_otsu = false]</i>)
|
|
|
|
|
*
|
|
|
|
|
* Applies fixed-level threshold to array elements.
|
|
|
|
|
*
|
|
|
|
|
* dst(x,y) = 0, if src(x,y)>threshold
|
|
|
|
|
* src(x,y), otherwise
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_threshold_to_zero_inverse(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE threshold, use_otsu, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &threshold, &use_otsu);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvThreshold(CVARR(self), CVARR(dest), NUM2DBL(threshold), 0, CV_THRESH_TOZERO_INV | (use_otsu == Qtrue ? CV_THRESH_OTSU : 0));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* pyr_down(<i>[filter = :gaussian_5x5]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return downsamples image.
|
|
|
|
|
*
|
|
|
|
|
* This operation performs downsampling step of Gaussian pyramid decomposition.
|
|
|
|
|
* First it convolves source image with the specified filter and then downsamples the image by rejecting even rows and columns.
|
|
|
|
|
*
|
|
|
|
|
* note: filter - only :gaussian_5x5 is currently supported.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_pyr_down(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE filter_type, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &filter_type);
|
|
|
|
|
int filter = CV_GAUSSIAN_5x5;
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
switch (TYPE(filter_type)) {
|
|
|
|
|
case T_SYMBOL:
|
|
|
|
|
// currently suport CV_GAUSSIAN_5x5 only.
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eArgError, "argument 1 (filter_type) should be Symbol.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
dest = cCvMat::new_object(size.height / 2, size.width / 2, cvGetElemType(CVARR(self)));
|
|
|
|
|
cvPyrDown(CVARR(self), CVARR(dest), filter);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* pyr_up(<i>[filter = :gaussian_5x5]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Return upsamples image.
|
|
|
|
|
*
|
|
|
|
|
* This operation performs up-sampling step of Gaussian pyramid decomposition.
|
|
|
|
|
* First it upsamples the source image by injecting even zero rows and columns and then convolves result with the specified filter multiplied by 4 for interpolation.
|
|
|
|
|
* So the destination image is four times larger than the source image.
|
|
|
|
|
*
|
|
|
|
|
* note: filter - only :gaussian_5x5 is currently supported.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_pyr_up(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE filter_type, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &filter_type);
|
|
|
|
|
int filter = CV_GAUSSIAN_5x5;
|
|
|
|
|
if (argc > 0) {
|
|
|
|
|
switch (TYPE(filter_type)) {
|
|
|
|
|
case T_SYMBOL:
|
|
|
|
|
// currently suport CV_GAUSSIAN_5x5 only.
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
rb_raise(rb_eArgError, "argument 1 (filter_type) should be Symbol.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
dest = cCvMat::new_object(size.height * 2, size.width * 2, cvGetElemType(CVARR(self)));
|
|
|
|
|
cvPyrUp(CVARR(self), CVARR(dest), filter);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* flood_fill(<i>seed_point, new_val, lo_diff, up_diff[,flood_fill_option]</i>) -> [cvmat, cvconnectedcomp, iplimage(mask)]
|
|
|
|
|
*
|
|
|
|
|
* Return image filled a connnected compoment with given color.
|
|
|
|
|
* This operation fills a connected component starting from the seed point with the specified color.
|
|
|
|
|
* The connectivity is determined by the closeness of pixel values.
|
|
|
|
|
* The pixel at (x, y) is considered to belong to the repainted domain if:
|
|
|
|
|
*
|
|
|
|
|
* src(x',y')-lo_diff<=src(x,y)<=src(x',y')+up_diff, grayscale image, floating range
|
|
|
|
|
* src(seed.x,seed.y)-lo<=src(x,y)<=src(seed.x,seed.y)+up_diff, grayscale image, fixed range
|
|
|
|
|
* src(x',y')r-lo_diffr<=src(x,y)r<=src(x',y')r+up_diffr and
|
|
|
|
|
* src(x',y')g-lo_diffg<=src(x,y)g<=src(x',y')g+up_diffg and
|
|
|
|
|
* src(x',y')b-lo_diffb<=src(x,y)b<=src(x',y')b+up_diffb, color image, floating range
|
|
|
|
|
* src(seed.x,seed.y)r-lo_diffr<=src(x,y)r<=src(seed.x,seed.y)r+up_diffr and
|
|
|
|
|
* src(seed.x,seed.y)g-lo_diffg<=src(x,y)g<=src(seed.x,seed.y)g+up_diffg and
|
|
|
|
|
* src(seed.x,seed.y)b-lo_diffb<=src(x,y)b<=src(seed.x,seed.y)b+up_diffb, color image, fixed range
|
|
|
|
|
*
|
|
|
|
|
* where src(x',y') is value of one of pixel neighbors.
|
|
|
|
|
* That is, to be added to the connected component, a pixel's color/brightness should be close enough to:
|
|
|
|
|
* * color/brightness of one of its neighbors that are already referred to the connected component in case of floating range
|
|
|
|
|
* * color/brightness of the seed point in case of fixed range.
|
|
|
|
|
*
|
|
|
|
|
* arguments
|
|
|
|
|
* * seed_point -The starting point.
|
|
|
|
|
* * new_val - New value of repainted domain pixels.
|
|
|
|
|
* * lo_diff - Maximal lower brightness/color difference between the currently observed pixel and one of its neighbor belong to the component or seed pixel to add the pixel to component. In case of 8-bit color images it is packed value.
|
|
|
|
|
* * up_diff - Maximal upper brightness/color difference between the currently observed pixel and one of its neighbor belong to the component or seed pixel to add the pixel to component. In case of 8-bit color images it is packed value.
|
|
|
|
|
*
|
|
|
|
|
* and flood_fill_option
|
|
|
|
|
* :connectivity => 4 or 8, 4 default
|
|
|
|
|
* Connectivity determines which neighbors of a pixel are considered.
|
|
|
|
|
* :fixed_range => true or false, false default
|
|
|
|
|
* If set the difference between the current pixel and seed pixel is considered, otherwise difference between neighbor pixels is considered (the range is floating).
|
|
|
|
|
* :mask_only => true or false, false default
|
|
|
|
|
* If set, the function does not fill the image(new_val is ignored), but the fills mask.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>flood_fill_option</i>'s default value is CvMat::FLOOD_FILL_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_flood_fill(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
return rb_flood_fill_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* flood_fill!(<i>seed_point, new_val, lo_diff, up_diff[,flood_fill_option]</i>) -> [self, cvconnectedcomp, iplimage(mask)]
|
|
|
|
|
*
|
|
|
|
|
* Fills a connected component with given color.
|
|
|
|
|
* see CvMat#flood_fill
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_flood_fill_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE seed_point, new_val, lo_diff, up_diff, flood_fill_option, mask, comp;
|
|
|
|
|
rb_scan_args(argc, argv, "23", &seed_point, &new_val, &lo_diff, &up_diff, &flood_fill_option);
|
|
|
|
|
flood_fill_option = FLOOD_FILL_OPTION(flood_fill_option);
|
|
|
|
|
int flags = FF_CONNECTIVITY(flood_fill_option);
|
|
|
|
|
if (FF_FIXED_RANGE(flood_fill_option)) {
|
|
|
|
|
flags |= CV_FLOODFILL_FIXED_RANGE;
|
|
|
|
|
}
|
|
|
|
|
if (FF_MASK_ONLY(flood_fill_option)) {
|
|
|
|
|
flags |= CV_FLOODFILL_MASK_ONLY;
|
|
|
|
|
}
|
|
|
|
|
CvSize size = cvGetSize(CVARR(self));
|
|
|
|
|
mask = cIplImage::new_object(size.width + 2, size.height + 2, CV_MAKETYPE(CV_8U, 1));
|
|
|
|
|
comp = cCvConnectedComp::new_object();
|
|
|
|
|
cvFloodFill(CVARR(self),
|
|
|
|
|
VALUE_TO_CVPOINT(seed_point),
|
|
|
|
|
VALUE_TO_CVSCALAR(new_val),
|
|
|
|
|
NIL_P(lo_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(lo_diff),
|
|
|
|
|
NIL_P(lo_diff) ? cvScalar(0) : VALUE_TO_CVSCALAR(up_diff),
|
|
|
|
|
CVCONNECTEDCOMP(comp),
|
|
|
|
|
flags,
|
|
|
|
|
CVARR(mask));
|
|
|
|
|
cvSetImageROI(IPLIMAGE(mask), cvRect(1, 1, size.width, size.height));
|
|
|
|
|
return rb_ary_new3(3, self, comp, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* find_contours([find_contours_options]) -> cvchain or chcontour or nil
|
|
|
|
|
*
|
|
|
|
|
* Finds contours in binary image, and return contours as CvContour or CvChain.
|
|
|
|
|
* If contours not found, return nil.
|
|
|
|
|
*
|
|
|
|
|
* <i>flood_fill_option</i> should be Hash include these keys.
|
|
|
|
|
* :mode - Retrieval mode.
|
|
|
|
|
* :external - retrive only the extreme outer contours
|
|
|
|
|
* :list - retrieve all the contours and puts them in the list.(default)
|
|
|
|
|
* :ccomp - retrieve all the contours and organizes them into two-level hierarchy:
|
|
|
|
|
* top level are external boundaries of the components, second level are bounda boundaries of the holes
|
|
|
|
|
* :tree - retrieve all the contours and reconstructs the full hierarchy of nested contours
|
|
|
|
|
* Connectivity determines which neighbors of a pixel are considered.
|
|
|
|
|
* :method - Approximation method.
|
|
|
|
|
* :code - output contours in the Freeman chain code. All other methods output polygons (sequences of vertices).
|
|
|
|
|
* :approx_none - translate all the points from the chain code into points;
|
|
|
|
|
* :approx_simple - compress horizontal, vertical, and diagonal segments, that is, the function leaves only their ending points;(default)
|
|
|
|
|
* :approx_tc89_l1
|
|
|
|
|
* :approx_tc89_kcos - apply one of the flavors of Teh-Chin chain approximation algorithm.
|
|
|
|
|
* If set the difference between the current pixel and seed pixel is considered,
|
|
|
|
|
* otherwise difference between neighbor pixels is considered (the range is floating).
|
|
|
|
|
* :offset - Offset, by which every contour point is shifted.
|
|
|
|
|
* This is useful if the contours are extracted from the image ROI
|
|
|
|
|
* and then they should be analyzed in the whole image context. Should be CvPoint.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>find_contours_option</i>'s default value is CvMat::FIND_CONTOURS_OPTION.
|
|
|
|
|
*
|
|
|
|
|
* <b>support single-channel 8bit unsigned image only.</b>
|
|
|
|
|
*
|
|
|
|
|
* note: Non-zero pixels are treated as 1's, zero pixels remain 0's
|
|
|
|
|
* that is image treated as binary. To get such a binary image from grayscale,
|
|
|
|
|
* one may use threshold, adaptive_threshold or canny.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_contours(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
return rb_find_contours_bang(argc, argv, copy(self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* find_contours!([find_contours_options]) -> cvchain or chcontour or nil
|
|
|
|
|
*
|
|
|
|
|
* Finds contours in binary image.
|
|
|
|
|
* The function modifies the source image content.
|
|
|
|
|
* (Because the copy is not made, it is slightly faster than find_contours.)
|
|
|
|
|
*
|
|
|
|
|
* see find_contours
|
|
|
|
|
*
|
|
|
|
|
* <b>support single-channel 8bit unsigned image only.</b>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_contours_bang(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE find_contours_option, klass, element_klass, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &find_contours_option);
|
|
|
|
|
CvSeq *contour = 0;
|
|
|
|
|
find_contours_option = FIND_CONTOURS_OPTION(find_contours_option);
|
|
|
|
|
int mode = FC_MODE(find_contours_option);
|
|
|
|
|
int method = FC_METHOD(find_contours_option);
|
|
|
|
|
int header, header_size, element_size;
|
|
|
|
|
if (method == CV_CHAIN_CODE) {
|
|
|
|
|
klass = cCvChain::rb_class();
|
|
|
|
|
element_klass = cCvChainCode::rb_class();
|
|
|
|
|
header = CV_SEQ_CHAIN_CONTOUR;
|
|
|
|
|
header_size = sizeof(CvChain);
|
|
|
|
|
element_size = sizeof(CvChainCode);
|
|
|
|
|
} else {
|
|
|
|
|
klass = cCvContour::rb_class();
|
|
|
|
|
element_klass = cCvPoint::rb_class();
|
|
|
|
|
header = CV_SEQ_CONTOUR;
|
|
|
|
|
header_size = sizeof(CvContour);
|
|
|
|
|
element_size = sizeof(CvPoint);
|
|
|
|
|
}
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
if(cvFindContours(CVARR(self), CVMEMSTORAGE(storage), &contour, header, mode, method, FC_OFFSET(find_contours_option)) == 0)
|
|
|
|
|
return Qnil;
|
|
|
|
|
if(!contour)
|
|
|
|
|
contour = cvCreateSeq(header, header_size, element_size, CVMEMSTORAGE(storage));
|
|
|
|
|
return cCvSeq::new_sequence(klass, contour, element_klass, storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* pyr_segmentation(<i>level, threshold1, threshold2</i>) -> [cvmat, cvseq(include cvconnectedcomp)]
|
|
|
|
|
*
|
|
|
|
|
* Does image segmentation by pyramids.
|
|
|
|
|
* The pyramid builds up to the level <i>level<i>.
|
|
|
|
|
* The links between any pixel a on <i>level<i>i and
|
|
|
|
|
* its candidate father pixel b on the adjacent level are established if
|
|
|
|
|
* p(c(a),c(b)) < threshold1. After the connected components are defined, they are joined into several clusters. Any two segments A and B belong to the same cluster, if
|
|
|
|
|
* p(c(A),c(B)) < threshold2. The input image has only one channel, then
|
|
|
|
|
* p(c^2,c^2)=|c^2-c^2|. If the input image has three channels (red, green and blue), then
|
|
|
|
|
* p(c^2,c^2)=0,3*(c^2 r-c^2 r)+0.59*(c^2 g-c^2 g)+0,11*(c^2 b-c^2 b) . There may be more than one connected component per a cluster.
|
|
|
|
|
*
|
|
|
|
|
* Return segmented image and sequence of connected components.
|
|
|
|
|
* <b>support single-channel or 3-channel 8bit unsigned image only</b>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_pyr_segmentation(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8U_ONLY(self);
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE level, threshold1, threshold2, storage, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "30", &level, &threshold1, &threshold2);
|
|
|
|
|
IplImage *src = IPLIMAGE(self);
|
|
|
|
|
int l = FIX2INT(level);
|
|
|
|
|
double t1 = NUM2DBL(threshold1), t2 = NUM2DBL(threshold2);
|
|
|
|
|
if (!(l >0))
|
|
|
|
|
rb_raise(rb_eArgError, "argument 1 (level) should be > 0.");
|
|
|
|
|
if(((src->width | src->height) & ((1 << l) -1 )) != 0)
|
|
|
|
|
rb_raise(rb_eArgError, "bad image size on level %d.", FIX2INT(level));
|
|
|
|
|
if (t1 < 0)
|
|
|
|
|
rb_raise(rb_eArgError, "argument 2 (threshold for establishing the link) should be >= 0.");
|
|
|
|
|
if (t2 < 0)
|
|
|
|
|
rb_raise(rb_eArgError, "argument 3 (threshold for the segments clustering) should be >= 0.");
|
|
|
|
|
dest = cIplImage::new_object(cvGetSize(src), cvGetElemType(src));
|
|
|
|
|
CvSeq *comp = 0;
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
|
|
|
|
|
cvPyrSegmentation(src,
|
|
|
|
|
IPLIMAGE(dest),
|
|
|
|
|
CVMEMSTORAGE(storage),
|
|
|
|
|
&comp,
|
|
|
|
|
l, t1, t2);
|
|
|
|
|
if(!comp)
|
|
|
|
|
comp = cvCreateSeq(CV_SEQ_CONNECTED_COMP, sizeof(CvSeq), sizeof(CvConnectedComp), CVMEMSTORAGE(storage));
|
|
|
|
|
return rb_ary_new3(2, dest, cCvSeq::new_sequence(cCvSeq::rb_class(), comp, cCvConnectedComp::rb_class(), storage));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* pyr_mean_shift_filtering(<i>sp, sr[,max_level = 1][termcrit = CvTermCriteria.new(5,1)]</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Does meanshift image segmentation.
|
|
|
|
|
*
|
|
|
|
|
* sp - The spatial window radius.
|
|
|
|
|
* sr - The color window radius.
|
|
|
|
|
* max_level - Maximum level of the pyramid for the segmentation.
|
|
|
|
|
* termcrit - Termination criteria: when to stop meanshift iterations.
|
|
|
|
|
*
|
|
|
|
|
* This method is implements the filtering stage of meanshift segmentation,
|
|
|
|
|
* that is, the output of the function is the filtered "posterized" image with color gradients and fine-grain texture flattened.
|
|
|
|
|
* At every pixel (X,Y) of the input image (or down-sized input image, see below)
|
|
|
|
|
* the function executes meanshift iterations, that is, the pixel (X,Y) neighborhood in the joint space-color hyperspace is considered:
|
|
|
|
|
* {(x,y): X-sp≤x≤X+sp && Y-sp≤y≤Y+sp && ||(R,G,B)-(r,g,b)|| ≤ sr},
|
|
|
|
|
* where (R,G,B) and (r,g,b) are the vectors of color components at (X,Y) and (x,y),
|
|
|
|
|
* respectively (though, the algorithm does not depend on the color space used,
|
|
|
|
|
* so any 3-component color space can be used instead).
|
|
|
|
|
* Over the neighborhood the average spatial value (X',Y')
|
|
|
|
|
* and average color vector (R',G',B') are found and they act as the neighborhood center on the next iteration:
|
|
|
|
|
* (X,Y)~(X',Y'), (R,G,B)~(R',G',B').
|
|
|
|
|
* After the iterations over, the color components of the initial pixel (that is, the pixel from where the iterations started)
|
|
|
|
|
* are set to the final value (average color at the last iteration):
|
|
|
|
|
* I(X,Y) <- (R*,G*,B*).
|
|
|
|
|
* Then max_level > 0, the gaussian pyramid of max_level+1 levels is built,
|
|
|
|
|
* and the above procedure is run on the smallest layer.
|
|
|
|
|
* After that, the results are propagated to the larger layer and the iterations are run again
|
|
|
|
|
* only on those pixels where the layer colors differ much (>sr) from the lower-resolution layer,
|
|
|
|
|
* that is, the boundaries of the color regions are clarified.
|
|
|
|
|
*
|
|
|
|
|
* Note, that the results will be actually different from the ones obtained by running the meanshift procedure on the whole original image (i.e. when max_level==0).
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_pyr_mean_shift_filtering(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE spatial_window_radius, color_window_radius, max_level, termcrit, dest;
|
|
|
|
|
rb_scan_args(argc, argv, "22", &spatial_window_radius, &color_window_radius, &max_level, &termcrit);
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvPyrMeanShiftFiltering(CVARR(self), CVARR(dest),
|
|
|
|
|
NUM2DBL(spatial_window_radius),
|
|
|
|
|
NUM2DBL(color_window_radius),
|
|
|
|
|
IF_INT(max_level, 1),
|
|
|
|
|
NIL_P(termcrit) ? cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 5, 1) : VALUE_TO_CVTERMCRITERIA(termcrit));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* watershed -> cvmat(mean markers:cv32s)
|
|
|
|
|
*
|
|
|
|
|
* Does watershed segmentation.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_watershed(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE markers = cCvMat::new_object(cvGetSize(CVARR(self)), CV_32SC1);
|
|
|
|
|
cvZero(CVARR(markers));
|
|
|
|
|
cvWatershed(CVARR(self), CVARR(markers));
|
|
|
|
|
return markers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* moments -> array(include CvMoments)
|
|
|
|
|
*
|
|
|
|
|
* Calculates moments.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_moments(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE is_binary, moments;
|
|
|
|
|
rb_scan_args(argc, argv, "01", &is_binary);
|
|
|
|
|
IplImage image = *IPLIMAGE(self);
|
|
|
|
|
int cn = CV_MAT_CN(cvGetElemType(CVARR(self)));
|
|
|
|
|
moments = rb_ary_new();
|
|
|
|
|
for(int i = 1; i <= cn; i++) {
|
|
|
|
|
cvSetImageCOI(&image, i);
|
|
|
|
|
rb_ary_push(moments, cCvMoments::new_object(&image, TRUE_OR_FALSE(is_binary, 0)));
|
|
|
|
|
}
|
|
|
|
|
return moments;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* hough_line_standard(<i>rho, theta, threshold</i>) -> cvseq(include CvLine)
|
|
|
|
|
*
|
|
|
|
|
* Finds lines in binary image using standard(classical) Hough transform.
|
|
|
|
|
* * rho - Distance resolution in pixel-related units.
|
|
|
|
|
* * theta - Angle resolution measured in radians.
|
|
|
|
|
* * threshold - Threshold parameter. A line is returned by the function if the corresponding accumulator value is greater than threshold.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_hough_lines_standard(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE rho, theta, threshold, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "30", &rho, &theta, &threshold);
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
CvSeq *seq = cvHoughLines2(CVARR(copy(self)), CVMEMSTORAGE(storage),
|
|
|
|
|
CV_HOUGH_STANDARD, NUM2DBL(rho), NUM2DBL(theta), NUM2INT(threshold));
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvLine::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* hough_line_probabilistic(<i>rho, theta, threshold, min_length, max_gap</i>) -> cvseq(include CvTwoPoints)
|
|
|
|
|
*
|
|
|
|
|
* Finds lines in binary image using probabilistic Hough transform.
|
|
|
|
|
* * rho - Distance resolution in pixel-related units.
|
|
|
|
|
* * theta - Angle resolution measured in radians.
|
|
|
|
|
* * threshold - Threshold parameter. A line is returned by the function if the corresponding accumulator value is greater than threshold.
|
|
|
|
|
* * min_length - The minimum line length.
|
|
|
|
|
* * max_gap - The maximum gap between line segments lieing on the same line to treat them as the single line segment (i.e. to join them).
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_hough_lines_probabilistic(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE rho, theta, threshold, p1, p2, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "50", &rho, &theta, &threshold, &p1, &p2);
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
CvSeq *seq = cvHoughLines2(CVARR(copy(self)), CVMEMSTORAGE(storage),
|
|
|
|
|
CV_HOUGH_PROBABILISTIC, NUM2DBL(rho), NUM2DBL(theta), NUM2INT(threshold),
|
|
|
|
|
NUM2DBL(p1), NUM2DBL(p2));
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvTwoPoints::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* hough_line_multi_scale(<i>rho, theta, threshold, div_rho, div_theta</i>) -> cvseq(include CvLine)
|
|
|
|
|
*
|
|
|
|
|
* Finds lines in binary image using multi-scale variant of classical Hough transform.
|
|
|
|
|
* * rho - Distance resolution in pixel-related units.
|
|
|
|
|
* * theta - Angle resolution measured in radians.
|
|
|
|
|
* * threshold - Threshold parameter. A line is returned by the function if the corresponding accumulator value is greater than threshold.
|
|
|
|
|
* * div_rho = divisor for distance resolution rho.
|
|
|
|
|
* * div_theta = divisor for angle resolution theta.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_hough_lines_multi_scale(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE rho, theta, threshold, p1, p2, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "50", &rho, &theta, &threshold, &p1, &p2);
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
CvSeq *seq = cvHoughLines2(CVARR(copy(self)), CVMEMSTORAGE(storage),
|
|
|
|
|
CV_HOUGH_MULTI_SCALE, NUM2DBL(rho), NUM2DBL(theta), NUM2INT(threshold),
|
|
|
|
|
NUM2DBL(p1), NUM2DBL(p2));
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvLine::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* hough_circles_gradient(<i>dp, min_dist, threshold_canny, threshold_accumulate, min_radius = 0, max_radius = max(width,height)</i>) -> cvseq(include CvCircle32f)
|
|
|
|
|
*
|
|
|
|
|
* Finds circles in grayscale image using Hough transform.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_hough_circles_gradient(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE dp, min_dist, threshold_canny, threshold_accumulate, min_radius, max_radius, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "24", &dp, &min_dist, &threshold_canny, &threshold_accumulate, &min_radius, &max_radius);
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
CvSeq *seq = cvHoughCircles(CVARR(self), CVMEMSTORAGE(storage),
|
|
|
|
|
CV_HOUGH_GRADIENT, NUM2DBL(dp), NUM2DBL(min_dist),
|
|
|
|
|
NUM2DBL(threshold_canny), NUM2DBL(threshold_accumulate),
|
|
|
|
|
IF_INT(min_radius, 0), IF_INT(max_radius, 0));
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvCircle32f::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* inpaint_ns(<i>mask, radius</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Inpaints the selected region in the image by Navier-Stokes based method.
|
|
|
|
|
* The radius of circlular neighborhood of each point inpainted that is considered by the algorithm.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_inpaint_ns(VALUE self, VALUE mask, VALUE radius)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8U_ONLY(self);
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE dest;
|
|
|
|
|
if (!(rb_obj_is_kind_of(mask, cCvMat::rb_class())) || cvGetElemType(CVARR(mask)) != CV_8UC1)
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (mask) should be mask image.");
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvInpaint(CVARR(self), CVARR(mask), CVARR(dest), NUM2DBL(radius), CV_INPAINT_NS);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* inpaint_telea(<i>mask, radius</i>) -> cvmat
|
|
|
|
|
*
|
|
|
|
|
* Inpaints the selected region in the image by The method by Alexandru Telea's method.
|
|
|
|
|
* The radius of circlular neighborhood of each point inpainted that is considered by the algorithm.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_inpaint_telea(VALUE self, VALUE mask, VALUE radius)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8U_ONLY(self);
|
|
|
|
|
SUPPORT_C1C3_ONLY(self);
|
|
|
|
|
VALUE dest;
|
|
|
|
|
if (!(rb_obj_is_kind_of(mask, cCvMat::rb_class())) || cvGetElemType(CVARR(mask)) != CV_8UC1)
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (mask) should be mask image.");
|
|
|
|
|
dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvInpaint(CVARR(self), CVARR(mask), CVARR(dest), NUM2DBL(radius), CV_INPAINT_TELEA);
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* equalize_hist - cvmat
|
|
|
|
|
*
|
|
|
|
|
* Equalize histgram of grayscale of image.
|
|
|
|
|
*
|
|
|
|
|
* equalizes histogram of the input image using the following algorithm:
|
|
|
|
|
* 1. calculate histogram H for src.
|
|
|
|
|
* 2. normalize histogram, so that the sum of histogram bins is 255.
|
|
|
|
|
* 3. compute integral of the histogram:
|
|
|
|
|
* H’(i) = sum0≤j≤iH(j)
|
|
|
|
|
* 4. transform the image using H’ as a look-up table: dst(x,y)=H’(src(x,y))
|
|
|
|
|
* The algorithm normalizes brightness and increases contrast of the image.
|
|
|
|
|
*
|
|
|
|
|
* <b>support single-channel 8bit image (grayscale) only.</b>
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_equalize_hist(VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE dest = cCvMat::new_object(cvGetSize(CVARR(self)), cvGetElemType(CVARR(self)));
|
|
|
|
|
cvEqualizeHist(CVARR(self), CVARR(dest));
|
|
|
|
|
return dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* match_template(<i>template[,method = :sqdiff]</i>) -> cvmat(result)
|
|
|
|
|
*
|
|
|
|
|
* Compares template against overlapped image regions.
|
|
|
|
|
|
|
|
|
|
* <i>method</i> is specifies the way the template must be compared with image regions.
|
|
|
|
|
* <i>method</i> should be following symbol. (see CvMat::MATCH_TEMPLATE_METHOD 's key and value.)
|
|
|
|
|
*
|
|
|
|
|
* * :sqdiff
|
|
|
|
|
* R(x,y)=sumx',y'[T(x',y')-I(x+x',y+y')]2
|
|
|
|
|
* * :sqdiff_normed
|
|
|
|
|
* R(x,y)=sumx',y'[T(x',y')-I(x+x',y+y')]2/sqrt[sumx',y'T(x',y')2*sumx',y'I(x+x',y+y')2]
|
|
|
|
|
* * :ccorr
|
|
|
|
|
* R(x,y)=sumx',y'[T(x',y')*I(x+x',y+y')]
|
|
|
|
|
* * :ccorr_normed
|
|
|
|
|
* R(x,y)=sumx',y'[T(x',y')*I(x+x',y+y')]/sqrt[sumx',y'T(x',y')2*sumx',y'I(x+x',y+y')2]
|
|
|
|
|
* * :ccoeff
|
|
|
|
|
* R(x,y)=sumx',y'[T'(x',y')*I'(x+x',y+y')],
|
|
|
|
|
* where T'(x',y')=T(x',y') - 1/(w*h)*sumx",y"T(x",y")
|
|
|
|
|
* I'(x+x',y+y')=I(x+x',y+y') - 1/(w*h)*sumx",y"I(x+x",y+y")
|
|
|
|
|
* * :ccoeff_normed
|
|
|
|
|
* R(x,y)=sumx',y'[T'(x',y')*I'(x+x',y+y')]/sqrt[sumx',y'T'(x',y')2*sumx',y'I'(x+x',y+y')2]
|
|
|
|
|
*
|
|
|
|
|
* After the match_template finishes comparison, the best matches can be found as global
|
|
|
|
|
* minimums (:sqdiff*) or maximums(:ccorr* or :ccoeff*) using minmax function.
|
|
|
|
|
* In case of color image and template summation in both numerator and each sum in denominator
|
|
|
|
|
* is done over all the channels (and separate mean values are used for each channel).
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_match_template(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE templ, method, result;
|
|
|
|
|
rb_scan_args(argc, argv, "11", &templ, &method);
|
|
|
|
|
if (!(rb_obj_is_kind_of(templ, cCvMat::rb_class())))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (template) should be %s.", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
if (cvGetElemType(CVARR(self)) != cvGetElemType(CVARR(templ)))
|
|
|
|
|
rb_raise(rb_eTypeError, "template should be same type of self.");
|
|
|
|
|
CvSize src_size = cvGetSize(CVARR(self)), template_size = cvGetSize(CVARR(self));
|
|
|
|
|
result = cCvMat::new_object(cvSize(src_size.width - template_size.width + 1,
|
|
|
|
|
src_size.height - template_size.height + 1),
|
|
|
|
|
CV_32FC1);
|
|
|
|
|
cvMatchTemplate(CVARR(self), CVARR(templ), CVARR(result), CVMETHOD("MATCH_TEMPLATE_METHOD", CV_TM_SQDIFF));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* match_shapes_i1(<i>object</i>) -> float
|
|
|
|
|
*
|
|
|
|
|
* Compares two shapes(self and object). <i>object</i> should be CvMat or CvContour.
|
|
|
|
|
*
|
|
|
|
|
* A ~ object1, B - object2):
|
|
|
|
|
* I1(A,B)=sumi=1..7abs(1/mAi - 1/mBi)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_match_shapes_i1(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE object;
|
|
|
|
|
rb_scan_args(argc, argv, "10", &object);
|
|
|
|
|
if ((!(rb_obj_is_kind_of(object, cCvMat::rb_class()))) && (!(rb_obj_is_kind_of(object, cCvContour::rb_class()))))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (shape) should be %s or %s", rb_class2name(cCvMat::rb_class()), rb_class2name(cCvContour::rb_class()));
|
|
|
|
|
return rb_float_new(cvMatchShapes(CVARR(self), CVARR(object), CV_CONTOURS_MATCH_I1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* match_shapes_i2(<i>object</i>) -> float
|
|
|
|
|
*
|
|
|
|
|
* Compares two shapes(self and object). <i>object</i> should be CvMat or CvContour.
|
|
|
|
|
*
|
|
|
|
|
* A ~ object1, B - object2):
|
|
|
|
|
* I2(A,B)=sumi=1..7abs(mAi - mBi)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_match_shapes_i2(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE object;
|
|
|
|
|
rb_scan_args(argc, argv, "10", &object);
|
|
|
|
|
if ((!(rb_obj_is_kind_of(object, cCvMat::rb_class()))) && (!(rb_obj_is_kind_of(object, cCvContour::rb_class()))))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (shape) should be %s or %s", rb_class2name(cCvMat::rb_class()), rb_class2name(cCvContour::rb_class()));
|
|
|
|
|
return rb_float_new(cvMatchShapes(CVARR(self), CVARR(object), CV_CONTOURS_MATCH_I2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* match_shapes_i3(<i>object</i>) -> float
|
|
|
|
|
*
|
|
|
|
|
* Compares two shapes(self and object). <i>object</i> should be CvMat or CvContour.
|
|
|
|
|
*
|
|
|
|
|
* A ~ object1, B - object2):
|
|
|
|
|
* I3(A,B)=sumi=1..7abs(mAi - mBi)/abs(mAi)
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_match_shapes_i3(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE object;
|
|
|
|
|
rb_scan_args(argc, argv, "10", &object);
|
|
|
|
|
if ((!(rb_obj_is_kind_of(object, cCvMat::rb_class()))) && (!(rb_obj_is_kind_of(object, cCvContour::rb_class()))))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (shape) should be %s or %s", rb_class2name(cCvMat::rb_class()), rb_class2name(cCvContour::rb_class()));
|
|
|
|
|
return rb_float_new(cvMatchShapes(CVARR(self), CVARR(object), CV_CONTOURS_MATCH_I3));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* mean_shift(window, criteria) -> comp
|
|
|
|
|
*
|
|
|
|
|
* Implements CAMSHIFT object tracking algrorithm.
|
|
|
|
|
* First, it finds an object center using mean_shift and, after that,
|
|
|
|
|
* calculates the object size and orientation.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_mean_shift(VALUE self, VALUE window, VALUE criteria)
|
|
|
|
|
{
|
|
|
|
|
VALUE comp = cCvConnectedComp::new_object();
|
|
|
|
|
cvMeanShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), CVCONNECTEDCOMP(comp));
|
|
|
|
|
return comp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* cam_shift(window, criteria) -> [comp, box]
|
|
|
|
|
*
|
|
|
|
|
* Implements CAMSHIFT object tracking algrorithm. First, it finds an object center using cvMeanShift and,
|
|
|
|
|
* after that, calculates the object size and orientation. The function returns number of iterations made
|
|
|
|
|
* within cvMeanShift.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_cam_shift(VALUE self, VALUE window, VALUE criteria)
|
|
|
|
|
{
|
|
|
|
|
VALUE comp, box;
|
|
|
|
|
comp = cCvConnectedComp::new_object();
|
|
|
|
|
box = cCvBox2D::new_object();
|
|
|
|
|
cvCamShift(CVARR(self), VALUE_TO_CVRECT(window), VALUE_TO_CVTERMCRITERIA(criteria), CVCONNECTEDCOMP(comp), CVBOX2D(box));
|
|
|
|
|
return rb_ary_new3(2, comp, box);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* snake_image(<i>points, alpha, beta, gamma, window, criteria[, calc_gradient = true]</i>) -> cvseq(pointset)
|
|
|
|
|
*
|
|
|
|
|
* Updates snake in order to minimize its total energy that is a sum of internal energy
|
|
|
|
|
* that depends on contour shape (the smoother contour is, the smaller internal energy is)
|
|
|
|
|
* and external energy that depends on the energy field and reaches minimum at the local energy
|
|
|
|
|
* extremums that correspond to the image edges in case of image gradient.
|
|
|
|
|
|
|
|
|
|
* The parameter criteria.epsilon is used to define the minimal number of points that must be moved
|
|
|
|
|
* during any iteration to keep the iteration process running.
|
|
|
|
|
*
|
|
|
|
|
* If at some iteration the number of moved points is less than criteria.epsilon or
|
|
|
|
|
* the function performed criteria.max_iter iterations, the function terminates.
|
|
|
|
|
*
|
|
|
|
|
* points
|
|
|
|
|
* Contour points (snake).
|
|
|
|
|
* alpha
|
|
|
|
|
* Weight[s] of continuity energy, single float or array of length floats, one per each contour point.
|
|
|
|
|
* beta
|
|
|
|
|
* Weight[s] of curvature energy, similar to alpha.
|
|
|
|
|
* gamma
|
|
|
|
|
* Weight[s] of image energy, similar to alpha.
|
|
|
|
|
* window
|
|
|
|
|
* Size of neighborhood of every point used to search the minimum, both win.width and win.height must be odd.
|
|
|
|
|
* criteria
|
|
|
|
|
* Termination criteria.
|
|
|
|
|
* calc_gradient
|
|
|
|
|
* Gradient flag. If not 0, the function calculates gradient magnitude for every image pixel and consideres
|
|
|
|
|
* it as the energy field, otherwise the input image itself is considered.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_snake_image(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
VALUE points, alpha, beta, gamma, window, criteria, calc_gradient, storage;
|
|
|
|
|
rb_scan_args(argc, argv, "43", &points, &alpha, &beta, &gamma, &window, &criteria, &calc_gradient);
|
|
|
|
|
CvPoint *pointset = 0;
|
|
|
|
|
CvSeq *seq = 0;
|
|
|
|
|
int length = CVPOINTS_FROM_POINT_SET(points, &pointset);
|
|
|
|
|
int coeff = (TYPE(alpha) == T_ARRAY || TYPE(beta) == T_ARRAY || TYPE(gamma) == T_ARRAY) ? CV_ARRAY : CV_VALUE;
|
|
|
|
|
float *a = 0, *b = 0, *c = 0;
|
|
|
|
|
IplImage stub;
|
|
|
|
|
if(coeff == CV_VALUE){
|
|
|
|
|
a = ALLOC(float);
|
|
|
|
|
a[0] = (float)NUM2DBL(alpha);
|
|
|
|
|
b = ALLOC(float);
|
|
|
|
|
b[0] = (float)NUM2DBL(beta);
|
|
|
|
|
c = ALLOC(float);
|
|
|
|
|
c[0] = (float)NUM2DBL(gamma);
|
|
|
|
|
}else{ // CV_ARRAY
|
|
|
|
|
rb_raise(rb_eNotImpError, "");
|
|
|
|
|
// todo
|
|
|
|
|
}
|
|
|
|
|
CvSize w = VALUE_TO_CVSIZE(window);
|
|
|
|
|
CvTermCriteria tc = VALUE_TO_CVTERMCRITERIA(criteria);
|
|
|
|
|
cvSnakeImage(cvGetImage(CVARR(self), &stub), pointset, length,
|
|
|
|
|
a, b, c, coeff, w, tc, IF_BOOL(calc_gradient, 1, 0, 1));
|
|
|
|
|
storage = cCvMemStorage::new_object();
|
|
|
|
|
seq = cvCreateSeq(CV_SEQ_POINT_SET, sizeof(CvSeq), sizeof(CvPoint), CVMEMSTORAGE(storage));
|
|
|
|
|
cvSeqPushMulti(seq, pointset, length);
|
|
|
|
|
return cCvSeq::new_sequence(cCvSeq::rb_class(), seq, cCvPoint::rb_class(), storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* optical_flow_hs(<i>prev[,velx = nil][,vely = nil][,options]</i>) -> [cvmat, cvmat]
|
|
|
|
|
*
|
|
|
|
|
* Calculates optical flow for two images (previous -> self) using Horn & Schunck algorithm.
|
|
|
|
|
* Return horizontal component of the optical flow and vertical component of the optical flow.
|
|
|
|
|
* <i>prev</i> is previous image
|
|
|
|
|
* <i>velx</i> is previous velocity field of x-axis, and <i>vely</i> is previous velocity field of y-axis.
|
|
|
|
|
*
|
|
|
|
|
* options
|
|
|
|
|
* * :lambda -> should be Float (default is 0.0005)
|
|
|
|
|
* Lagrangian multiplier.
|
|
|
|
|
* * :criteria -> should be CvTermCriteria object (default is CvTermCriteria(1, 0.001))
|
|
|
|
|
* Criteria of termination of velocity computing.
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::OPTICAL_FLOW_HS_OPTION.
|
|
|
|
|
*
|
|
|
|
|
* sample code
|
|
|
|
|
* velx, vely = nil, nil
|
|
|
|
|
* while true
|
|
|
|
|
* current = capture.query
|
|
|
|
|
* velx, vely = current.optical_flow_hs(prev, velx, vely) if prev
|
|
|
|
|
* prev = current
|
2010-12-31 03:02:19 -05:00
|
|
|
|
* end
|
2008-08-19 11:01:28 -04:00
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_optical_flow_hs(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE prev, velx, vely, options;
|
|
|
|
|
int use_previous = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options);
|
|
|
|
|
options = OPTICAL_FLOW_HS_OPTION(options);
|
|
|
|
|
if (!rb_obj_is_kind_of(prev, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (previous image) should be %s", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
if (NIL_P(velx) && NIL_P(vely)) {
|
|
|
|
|
velx = cCvMat::new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
vely = cCvMat::new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
} else {
|
|
|
|
|
if (rb_obj_is_kind_of(velx, cCvMat::rb_class()) && rb_obj_is_kind_of(vely, cCvMat::rb_class()))
|
|
|
|
|
use_previous = 1;
|
|
|
|
|
else
|
|
|
|
|
rb_raise(rb_eArgError, "Necessary to give both argument 2(previous velocity field x) and argument 3(previous velocity field y)");
|
|
|
|
|
}
|
|
|
|
|
cvCalcOpticalFlowHS(CVARR(prev), CVARR(self), use_previous, CVARR(velx), CVARR(vely), HS_LAMBDA(options), HS_CRITERIA(options));
|
|
|
|
|
return rb_ary_new3(2, velx, vely);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* optical_flow_lk(<i>prev, win_size</i>) -> [cvmat, cvmat]
|
|
|
|
|
*
|
|
|
|
|
* Calculates optical flow for two images (previous -> self) using Lucas & Kanade algorithm
|
|
|
|
|
* Return horizontal component of the optical flow and vertical component of the optical flow.
|
|
|
|
|
*
|
|
|
|
|
* <i>win_size</i> is size of the averaging window used for grouping pixels.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_optical_flow_lk(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE prev, win_size, velx, vely;
|
|
|
|
|
rb_scan_args(argc, argv, "20", &prev, &win_size);
|
|
|
|
|
if (!rb_obj_is_kind_of(prev, cCvMat::rb_class()))
|
|
|
|
|
rb_raise(rb_eTypeError, "argument 1 (previous image) should be %s", rb_class2name(cCvMat::rb_class()));
|
|
|
|
|
velx = cCvMat::new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
vely = cCvMat::new_object(cvGetSize(CVARR(self)), CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
cvCalcOpticalFlowLK(CVARR(prev), CVARR(self), VALUE_TO_CVSIZE(win_size), CVARR(velx), CVARR(vely));
|
|
|
|
|
return rb_ary_new3(2, velx, vely);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* optical_flow_bm(<i>prev[,velx = nil][,vely = nil][,option]</i>) -> [cvmat, cvmat]
|
|
|
|
|
*
|
|
|
|
|
* Calculates optical flow for two images (previous -> self) using block matching method.
|
|
|
|
|
* Return horizontal component of the optical flow and vertical component of the optical flow.
|
|
|
|
|
* <i>prev</i> is previous image.
|
|
|
|
|
* <i>velx</i> is previous velocity field of x-axis, and <i>vely</i> is previous velocity field of y-axis.
|
|
|
|
|
*
|
|
|
|
|
* options
|
|
|
|
|
* * :block_size -> should be CvSize (default is CvSize(4,4))
|
|
|
|
|
* Size of basic blocks that are compared.
|
|
|
|
|
* * :shift_size -> should be CvSize (default is CvSize(1,1))
|
|
|
|
|
* Block coordinate increments.
|
|
|
|
|
* * :max_range -> should be CvSize (default is CVSize(4,4))
|
|
|
|
|
* Size of the scanned neighborhood in pixels around block.
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::OPTICAL_FLOW_BM_OPTION.
|
|
|
|
|
*
|
|
|
|
|
* Velocity is computed for every block, but not for every pixel,
|
|
|
|
|
* so velocity image pixels correspond to input image blocks.
|
|
|
|
|
* input/output velocity field's size should be (self.width / block_size.width)x(self.height / block_size.height).
|
|
|
|
|
* e.g. image.size is 320x240 and block_size is 4x4, velocity field's size is 80x60.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_optical_flow_bm(int argc, VALUE *argv, VALUE self)
|
|
|
|
|
{
|
|
|
|
|
SUPPORT_8UC1_ONLY(self);
|
|
|
|
|
VALUE prev, velx, vely, options;
|
|
|
|
|
int use_previous = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "13", &prev, &velx, &vely, &options);
|
|
|
|
|
options = OPTICAL_FLOW_BM_OPTION(options);
|
|
|
|
|
CvSize
|
|
|
|
|
image_size = cvGetSize(CVARR(self)),
|
|
|
|
|
block_size = BM_BLOCK_SIZE(options),
|
|
|
|
|
shift_size = BM_SHIFT_SIZE(options),
|
|
|
|
|
max_range = BM_MAX_RANGE(options),
|
|
|
|
|
velocity_size = cvSize(image_size.width / block_size.width, image_size.height / block_size.height);
|
|
|
|
|
if (NIL_P(velx) && NIL_P(vely)) {
|
|
|
|
|
velx = cCvMat::new_object(velocity_size, CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
vely = cCvMat::new_object(velocity_size, CV_MAKETYPE(CV_32F, 1));
|
|
|
|
|
} else {
|
|
|
|
|
if (rb_obj_is_kind_of(velx, cCvMat::rb_class()) && rb_obj_is_kind_of(vely, cCvMat::rb_class()))
|
|
|
|
|
use_previous = 1;
|
|
|
|
|
else
|
|
|
|
|
rb_raise(rb_eArgError, "Necessary to give both argument 2(previous velocity field x) and argument 3(previous velocity field y)");
|
|
|
|
|
}
|
|
|
|
|
cvCalcOpticalFlowBM(CVARR(prev), CVARR(self),
|
|
|
|
|
block_size, shift_size, max_range, use_previous,
|
|
|
|
|
CVARR(velx), CVARR(vely));
|
|
|
|
|
return rb_ary_new3(2, velx, vely);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.find_fundamental_mat_7point(<i>points1, points2[,options = {}]</i>) -> fundamental_matrix(cvmat) or nil
|
|
|
|
|
*
|
|
|
|
|
* Calculates fundamental matrix from corresponding points, use for 7-point algorism. Return fundamental matrix(9x3).
|
|
|
|
|
* <i>points1</i> and <i>points2</i> should be 2x7 or 3x7 single-channel, or 1x7 multi-channel matrix.
|
|
|
|
|
* <i>option</i> should be Hash include these keys.
|
|
|
|
|
* :with_status (true or false)
|
|
|
|
|
* If set true, return fundamental_matrix and status. [fundamental_matrix, status]
|
|
|
|
|
* Otherwise return fundamental matrix only(default).
|
|
|
|
|
*
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION.
|
|
|
|
|
* note: 9x3 fundamental matrix means 3x3 three fundamental matrices.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_fundamental_mat_7point(int argc, VALUE *argv, VALUE klass)
|
|
|
|
|
{
|
|
|
|
|
VALUE points1, points2, option, fundamental_matrix, status;
|
|
|
|
|
int num = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &points1, &points2, &option);
|
|
|
|
|
option = FIND_FUNDAMENTAL_MAT_OPTION(option);
|
|
|
|
|
fundamental_matrix = cCvMat::new_object(9, 3, CV_32FC1);
|
|
|
|
|
if(FFM_WITH_STATUS(option)){
|
|
|
|
|
status = cCvMat::new_object(cvGetSize(CVARR(points1)), CV_8UC1);
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_7POINT, 0, 0, CVMAT(status));
|
|
|
|
|
return rb_ary_new3(2, fundamental_matrix, status);
|
|
|
|
|
}else{
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_7POINT, 0, 0, NULL);
|
|
|
|
|
return fundamental_matrix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.find_fundamental_mat_8point(<i>points1, points2[,options = {}]</i>) -> fundamental_matrix(cvmat) or nil
|
|
|
|
|
*
|
|
|
|
|
* Calculates fundamental matrix from corresponding points, use for 8-point algorism.
|
|
|
|
|
* <i>points1</i> and <i>points2</i> should be 2x7 or 3x7 single-channel, or 1x7 multi-channel matrix.
|
|
|
|
|
* <i>option</i> should be Hash include these keys.
|
|
|
|
|
* :with_status (true or false)
|
|
|
|
|
* If set true, return fundamental_matrix and status. [fundamental_matrix, status]
|
|
|
|
|
* Otherwise return fundamental matrix only(default).
|
|
|
|
|
*
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_fundamental_mat_8point(int argc, VALUE *argv, VALUE klass)
|
|
|
|
|
{
|
|
|
|
|
VALUE points1, points2, option, fundamental_matrix, status;
|
|
|
|
|
int num = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &points1, &points2, &option);
|
|
|
|
|
option = FIND_FUNDAMENTAL_MAT_OPTION(option);
|
|
|
|
|
fundamental_matrix = cCvMat::new_object(3, 3, CV_32FC1);
|
|
|
|
|
if(FFM_WITH_STATUS(option)){
|
|
|
|
|
status = cCvMat::new_object(cvGetSize(CVARR(points1)), CV_8UC1);
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_8POINT, 0, 0, CVMAT(status));
|
|
|
|
|
return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status);
|
|
|
|
|
}else{
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_8POINT, 0, 0, NULL);
|
|
|
|
|
return num == 0 ? Qnil : fundamental_matrix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.find_fundamental_mat_ransac(<i>points1, points2[,options = {}]</i>) -> fundamental_matrix(cvmat) or nil
|
|
|
|
|
*
|
|
|
|
|
* Calculates fundamental matrix from corresponding points, use for RANSAC algorism.
|
|
|
|
|
* <i>points1</i> and <i>points2</i> should be 2x7 or 3x7 single-channel, or 1x7 multi-channel matrix.
|
|
|
|
|
* <i>option</i> should be Hash include these keys.
|
|
|
|
|
* :with_status (true or false)
|
|
|
|
|
* If set true, return fundamental_matrix and status. [fundamental_matrix, status]
|
|
|
|
|
* Otherwise return fundamental matrix only(default).
|
|
|
|
|
* :maximum_distance
|
|
|
|
|
* The maximum distance from point to epipolar line in pixels, beyond which the point is considered an outlier
|
|
|
|
|
* and is not used for computing the final fundamental matrix. Usually it is set to 0.5 or 1.0.
|
|
|
|
|
* :desirable_level
|
|
|
|
|
* It denotes the desirable level of confidence that the matrix is correct.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_fundamental_mat_ransac(int argc, VALUE *argv, VALUE klass)
|
|
|
|
|
{
|
|
|
|
|
VALUE points1, points2, option, fundamental_matrix, status;
|
|
|
|
|
int num = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &points1, &points2, &option);
|
|
|
|
|
option = FIND_FUNDAMENTAL_MAT_OPTION(option);
|
|
|
|
|
fundamental_matrix = cCvMat::new_object(3, 3, CV_32FC1);
|
|
|
|
|
if(FFM_WITH_STATUS(option)){
|
|
|
|
|
status = cCvMat::new_object(cvGetSize(CVARR(points1)), CV_8UC1);
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_RANSAC, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), CVMAT(status));
|
|
|
|
|
return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status);
|
|
|
|
|
}else{
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_RANSAC, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL);
|
|
|
|
|
return num == 0 ? Qnil : fundamental_matrix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.find_fundamental_mat_lmeds(<i>points1, points2[,options = {}]</i>) -> fundamental_matrix(cvmat) or nil
|
|
|
|
|
*
|
|
|
|
|
* Calculates fundamental matrix from corresponding points, use for LMedS algorism.
|
|
|
|
|
* <i>points1</i> and <i>points2</i> should be 2x7 or 3x7 single-channel, or 1x7 multi-channel matrix.
|
|
|
|
|
* <i>option</i> should be Hash include these keys.
|
|
|
|
|
* :with_status (true or false)
|
|
|
|
|
* If set true, return fundamental_matrix and status. [fundamental_matrix, status]
|
|
|
|
|
* Otherwise return fundamental matrix only(default).
|
|
|
|
|
* :maximum_distance
|
|
|
|
|
* The maximum distance from point to epipolar line in pixels, beyond which the point is considered an outlier
|
|
|
|
|
* and is not used for computing the final fundamental matrix. Usually it is set to 0.5 or 1.0.
|
|
|
|
|
* :desirable_level
|
|
|
|
|
* It denotes the desirable level of confidence that the matrix is correct.
|
|
|
|
|
*
|
|
|
|
|
* note: <i>option</i>'s default value is CvMat::FIND_FUNDAMENTAL_MAT_OPTION.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_find_fundamental_mat_lmeds(int argc, VALUE *argv, VALUE klass)
|
|
|
|
|
{
|
|
|
|
|
VALUE points1, points2, option, fundamental_matrix, status;
|
|
|
|
|
int num = 0;
|
|
|
|
|
rb_scan_args(argc, argv, "21", &points1, &points2, &option);
|
|
|
|
|
option = FIND_FUNDAMENTAL_MAT_OPTION(option);
|
|
|
|
|
fundamental_matrix = cCvMat::new_object(3, 3, CV_32FC1);
|
|
|
|
|
if(FFM_WITH_STATUS(option)){
|
|
|
|
|
status = cCvMat::new_object(cvGetSize(CVARR(points1)), CV_8UC1);
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), CVMAT(status));
|
|
|
|
|
return num == 0 ? Qnil : rb_ary_new3(2, fundamental_matrix, status);
|
|
|
|
|
}else{
|
|
|
|
|
num = cvFindFundamentalMat(CVMAT(points1), CVMAT(points2), CVMAT(fundamental_matrix), CV_FM_LMEDS, FFM_MAXIMUM_DISTANCE(option), FFM_DESIRABLE_LEVEL(option), NULL);
|
|
|
|
|
return num == 0 ? Qnil : fundamental_matrix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* call-seq:
|
|
|
|
|
* CvMat.compute_correspond_epilines(<i>points, which_image, fundamental_matrix</i>) -> correspondent_lines(cvmat)
|
|
|
|
|
*
|
|
|
|
|
* For points in one image of stereo pair computes the corresponding epilines in the other image.
|
|
|
|
|
* Finds equation of a line that contains the corresponding point (i.e. projection of the same 3D point)
|
|
|
|
|
* in the other image. Each line is encoded by a vector of 3 elements l=[a,b,c]T, so that:
|
|
|
|
|
* lT*[x, y, 1]T=0,
|
|
|
|
|
* or
|
|
|
|
|
* a*x + b*y + c = 0
|
|
|
|
|
* From the fundamental matrix definition (see cvFindFundamentalMatrix discussion), line l2 for a point p1 in the first image (which_image=1) can be computed as:
|
|
|
|
|
* l2=F*p1
|
|
|
|
|
* and the line l1 for a point p2 in the second image (which_image=1) can be computed as:
|
|
|
|
|
* l1=FT*p2
|
|
|
|
|
* Line coefficients are defined up to a scale. They are normalized (a2+b2=1) are stored into correspondent_lines.
|
|
|
|
|
*/
|
|
|
|
|
VALUE
|
|
|
|
|
rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_image, VALUE fundamental_matrix)
|
|
|
|
|
{
|
|
|
|
|
VALUE correspondent_lines;
|
|
|
|
|
CvSize size = cvGetSize(CVARR(points));
|
|
|
|
|
int n;
|
|
|
|
|
if(size.width <= 3 && size.height >= 7)
|
|
|
|
|
n = size.height;
|
|
|
|
|
else if(size.height <= 3 && size.width >= 7)
|
|
|
|
|
n = size.width;
|
|
|
|
|
else
|
|
|
|
|
rb_raise(rb_eTypeError, "input points should 2xN, Nx2 or 3xN, Nx3 matrix(N >= 7).");
|
|
|
|
|
correspondent_lines = cCvMat::new_object(n, 3, CV_32F);
|
|
|
|
|
cvComputeCorrespondEpilines(CVMAT(points), FIX2INT(which_image), CVMAT(fundamental_matrix), CVMAT(correspondent_lines));
|
|
|
|
|
return correspondent_lines;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
new_object(int rows, int cols, int type)
|
|
|
|
|
{
|
|
|
|
|
return OPENCV_OBJECT(rb_klass, cvCreateMat(rows, cols, type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
|
new_object(CvSize size, int type)
|
|
|
|
|
{
|
|
|
|
|
return OPENCV_OBJECT(rb_klass, cvCreateMat(size.height, size.width, type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__NAMESPACE_END_OPENCV
|
|
|
|
|
__NAMESPACE_END_CVMAT
|