spyglass 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +6 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +5 -0
- data/examples/background_subtractor.rb +35 -0
- data/examples/cascade_classifier.rb +21 -0
- data/examples/contours.rb +24 -0
- data/examples/images/apple.jpg +0 -0
- data/examples/images/beach.jpg +0 -0
- data/examples/video_capture.rb +15 -0
- data/ext/spyglass/background_subtractor.cc +78 -0
- data/ext/spyglass/background_subtractor.h +18 -0
- data/ext/spyglass/cascade_classifier.cc +70 -0
- data/ext/spyglass/cascade_classifier.h +18 -0
- data/ext/spyglass/color.cc +83 -0
- data/ext/spyglass/color.h +22 -0
- data/ext/spyglass/color_space.cc +39 -0
- data/ext/spyglass/color_space.h +13 -0
- data/ext/spyglass/contour.cc +92 -0
- data/ext/spyglass/contour.h +22 -0
- data/ext/spyglass/extconf.rb +6 -0
- data/ext/spyglass/gui.cc +27 -0
- data/ext/spyglass/gui.h +15 -0
- data/ext/spyglass/image.cc +482 -0
- data/ext/spyglass/image.h +46 -0
- data/ext/spyglass/point.cc +78 -0
- data/ext/spyglass/point.h +23 -0
- data/ext/spyglass/prelude.h +42 -0
- data/ext/spyglass/rect.cc +131 -0
- data/ext/spyglass/rect.h +30 -0
- data/ext/spyglass/size.cc +89 -0
- data/ext/spyglass/size.h +25 -0
- data/ext/spyglass/spyglass.cc +35 -0
- data/ext/spyglass/spyglass.h +29 -0
- data/ext/spyglass/video_capture.cc +96 -0
- data/ext/spyglass/video_capture.h +20 -0
- data/ext/spyglass/window.cc +93 -0
- data/ext/spyglass/window.h +23 -0
- data/lib/spyglass.rb +6 -0
- data/lib/spyglass/color_space.rb +12 -0
- data/lib/spyglass/version.rb +3 -0
- data/spec/fixtures/haarcascade_frontalface_default.xml +35712 -0
- data/spec/fixtures/lena.jpg +0 -0
- data/spec/matchers/close_to.rb +6 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/spyglass/background_subtractor_spec.rb +23 -0
- data/spec/spyglass/cascade_classifier_spec.rb +28 -0
- data/spec/spyglass/color_space_spec.rb +13 -0
- data/spec/spyglass/color_spec.rb +54 -0
- data/spec/spyglass/contour_spec.rb +26 -0
- data/spec/spyglass/gui/window_spec.rb +21 -0
- data/spec/spyglass/image_spec.rb +116 -0
- data/spec/spyglass/point_spec.rb +41 -0
- data/spec/spyglass/rect_spec.rb +103 -0
- data/spec/spyglass/size_spec.rb +52 -0
- data/spyglass.gemspec +26 -0
- data/tasks/compile.rake +6 -0
- data/tasks/gem.rake +2 -0
- data/tasks/rspec.rake +21 -0
- metadata +177 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef SPYGLASS_COLOR_H_
|
2
|
+
#define SPYGLASS_COLOR_H_
|
3
|
+
|
4
|
+
#include "spyglass.h"
|
5
|
+
|
6
|
+
namespace Spyglass {
|
7
|
+
namespace Color {
|
8
|
+
void define_ruby_class();
|
9
|
+
VALUE get_ruby_class();
|
10
|
+
|
11
|
+
static VALUE rb_alloc(VALUE self);
|
12
|
+
static void rb_free(cv::Scalar *color);
|
13
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self);
|
14
|
+
static VALUE rb_get_color(VALUE self, VALUE index);
|
15
|
+
static VALUE rb_is_zeros(VALUE self);
|
16
|
+
static VALUE rb_to_a(VALUE self);
|
17
|
+
|
18
|
+
VALUE from_cvscalar(cv::Scalar *color);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
#endif
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "color_space.h"
|
2
|
+
|
3
|
+
VALUE ColorSpaceModule;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace ColorSpace {
|
7
|
+
void define_ruby_module() {
|
8
|
+
ColorSpaceModule = rb_define_module_under(Spyglass::get_ruby_module(), "ColorSpace");
|
9
|
+
|
10
|
+
// BGR
|
11
|
+
rb_define_const(ColorSpaceModule, "BGR_TO_GRAY", INT2FIX(CV_BGR2GRAY));
|
12
|
+
rb_define_const(ColorSpaceModule, "BGR_TO_HLS", INT2FIX(CV_BGR2HLS));
|
13
|
+
rb_define_const(ColorSpaceModule, "BGR_TO_HSV", INT2FIX(CV_BGR2HSV));
|
14
|
+
rb_define_const(ColorSpaceModule, "BGR_TO_YCRCB", INT2FIX(CV_BGR2YCrCb));
|
15
|
+
|
16
|
+
// Gray
|
17
|
+
rb_define_const(ColorSpaceModule, "GRAY_TO_BGR", INT2FIX(CV_GRAY2BGR));
|
18
|
+
rb_define_const(ColorSpaceModule, "GRAY_TO_RGB", INT2FIX(CV_GRAY2RGB));
|
19
|
+
|
20
|
+
// HLS
|
21
|
+
rb_define_const(ColorSpaceModule, "HLS_TO_BGR", INT2FIX(CV_HLS2BGR));
|
22
|
+
rb_define_const(ColorSpaceModule, "HLS_TO_RGB", INT2FIX(CV_HLS2RGB));
|
23
|
+
|
24
|
+
// HSV
|
25
|
+
rb_define_const(ColorSpaceModule, "HSV_TO_BGR", INT2FIX(CV_HSV2BGR));
|
26
|
+
rb_define_const(ColorSpaceModule, "HSV_TO_RGB", INT2FIX(CV_HSV2RGB));
|
27
|
+
|
28
|
+
// RGB
|
29
|
+
rb_define_const(ColorSpaceModule, "RGB_TO_GRAY", INT2FIX(CV_RGB2GRAY));
|
30
|
+
rb_define_const(ColorSpaceModule, "RGB_TO_HLS", INT2FIX(CV_RGB2HLS));
|
31
|
+
rb_define_const(ColorSpaceModule, "RGB_TO_HSV", INT2FIX(CV_RGB2HSV));
|
32
|
+
rb_define_const(ColorSpaceModule, "RGB_TO_YCRCB", INT2FIX(CV_RGB2YCrCb));
|
33
|
+
|
34
|
+
// YCrCb
|
35
|
+
rb_define_const(ColorSpaceModule, "YCRCB_TO_BGR", INT2FIX(CV_YCrCb2BGR));
|
36
|
+
rb_define_const(ColorSpaceModule, "YCRCB_TO_RGB", INT2FIX(CV_YCrCb2RGB));
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#include "contour.h"
|
2
|
+
|
3
|
+
static VALUE ContourClass;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace Contour {
|
7
|
+
void define_ruby_class() {
|
8
|
+
// Class definition
|
9
|
+
ContourClass = rb_define_class_under(Spyglass::get_ruby_module(), "Contour", rb_cObject);
|
10
|
+
rb_define_alloc_func(ContourClass, rb_alloc);
|
11
|
+
rb_define_method(ContourClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
12
|
+
|
13
|
+
// Instance methods
|
14
|
+
rb_define_method(ContourClass, "rect", RUBY_METHOD_FUNC(rb_get_rect), 0);
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE get_ruby_class() {
|
18
|
+
return ContourClass;
|
19
|
+
}
|
20
|
+
|
21
|
+
static VALUE rb_alloc(VALUE self) {
|
22
|
+
std::vector<cv::Point *> *contour = new std::vector<cv::Point *>();
|
23
|
+
return Data_Wrap_Struct(ContourClass, NULL, rb_free, contour);
|
24
|
+
}
|
25
|
+
|
26
|
+
static void rb_free(std::vector<cv::Point *> *contour) {
|
27
|
+
contour->clear();
|
28
|
+
delete contour;
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
|
32
|
+
VALUE points;
|
33
|
+
rb_scan_args(argc, argv, "01", &points);
|
34
|
+
|
35
|
+
if(!RTEST(points))
|
36
|
+
return self;
|
37
|
+
|
38
|
+
Check_Type(points, T_ARRAY);
|
39
|
+
|
40
|
+
std::vector<cv::Point *> *contour = SG_GET_CONTOUR(self);
|
41
|
+
for(int idx = 0; idx < RARRAY_LEN(points); idx++) {
|
42
|
+
VALUE point = rb_ary_entry(points, idx);
|
43
|
+
if(CLASS_OF(point) != Point::get_ruby_class()) {
|
44
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Point)",
|
45
|
+
rb_obj_classname(point));
|
46
|
+
}
|
47
|
+
|
48
|
+
cv::Point *_point = new cv::Point(* SG_GET_POINT(point));
|
49
|
+
contour->push_back(_point);
|
50
|
+
}
|
51
|
+
|
52
|
+
return self;
|
53
|
+
}
|
54
|
+
|
55
|
+
static VALUE rb_get_rect(VALUE self) {
|
56
|
+
std::vector<cv::Point *> *contour = SG_GET_CONTOUR(self);
|
57
|
+
cv::Rect rect = cv::boundingRect(to_value_vector(contour));
|
58
|
+
cv::Rect *_rect = new cv::Rect(rect);
|
59
|
+
return Rect::from_cvrect(_rect);
|
60
|
+
}
|
61
|
+
|
62
|
+
std::vector<cv::Point> to_value_vector(std::vector<cv::Point *> *contour) {
|
63
|
+
std::vector<cv::Point> result;
|
64
|
+
for(int idx = 0; idx < contour->size(); idx++) {
|
65
|
+
cv::Point *point = (*contour)[idx];
|
66
|
+
result.push_back(*point);
|
67
|
+
}
|
68
|
+
|
69
|
+
return result;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE from_cvpoint_vector(std::vector<cv::Point> contours) {
|
73
|
+
std::vector<cv::Point *> *ctrs = new std::vector<cv::Point *>();
|
74
|
+
|
75
|
+
for(int idx = 0; idx < contours.size(); idx++) {
|
76
|
+
ctrs->push_back(new cv::Point(contours[idx]));
|
77
|
+
}
|
78
|
+
|
79
|
+
return Data_Wrap_Struct(ContourClass, NULL, rb_free, ctrs);
|
80
|
+
}
|
81
|
+
|
82
|
+
VALUE from_contour_vector(std::vector<std::vector<cv::Point> > contours) {
|
83
|
+
VALUE ctrs = rb_ary_new2(contours.size());
|
84
|
+
for(int idx = 0; idx < contours.size(); idx++) {
|
85
|
+
rb_ary_store(ctrs, idx, from_cvpoint_vector(contours[idx]));
|
86
|
+
}
|
87
|
+
|
88
|
+
return ctrs;
|
89
|
+
}
|
90
|
+
|
91
|
+
}
|
92
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef SPYGLASS_CONTOUR_H_
|
2
|
+
#define SPYGLASS_CONTOUR_H_
|
3
|
+
|
4
|
+
#include "spyglass.h"
|
5
|
+
|
6
|
+
namespace Spyglass {
|
7
|
+
namespace Contour {
|
8
|
+
void define_ruby_class();
|
9
|
+
VALUE get_ruby_class();
|
10
|
+
|
11
|
+
static VALUE rb_alloc(VALUE self);
|
12
|
+
static void rb_free(std::vector<cv::Point *> *contour);
|
13
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self);
|
14
|
+
static VALUE rb_get_rect(VALUE self);
|
15
|
+
|
16
|
+
std::vector<cv::Point> to_value_vector(std::vector<cv::Point *> *contour);
|
17
|
+
VALUE from_cvpoint_vector(std::vector<cv::Point> contours);
|
18
|
+
VALUE from_contour_vector(std::vector<std::vector<cv::Point> > contours);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
#endif // SPYGLASS_CONTOUR_H_
|
data/ext/spyglass/gui.cc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#include "gui.h"
|
2
|
+
|
3
|
+
static VALUE GuiModule;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace GUI {
|
7
|
+
void define_ruby_module() {
|
8
|
+
GuiModule = rb_define_module_under(Spyglass::get_ruby_module(), "GUI");
|
9
|
+
|
10
|
+
// Module methods
|
11
|
+
rb_define_singleton_method(GuiModule, "wait_key", RUBY_METHOD_FUNC(rb_wait_key), 1);
|
12
|
+
}
|
13
|
+
|
14
|
+
VALUE get_ruby_module() {
|
15
|
+
return GuiModule;
|
16
|
+
}
|
17
|
+
|
18
|
+
static VALUE rb_wait_key(VALUE klass, VALUE timeout) {
|
19
|
+
Check_Type(timeout, T_FIXNUM);
|
20
|
+
|
21
|
+
int msecs = FIX2INT(timeout);
|
22
|
+
int key = cv::waitKey(msecs);
|
23
|
+
|
24
|
+
return INT2FIX(key);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
data/ext/spyglass/gui.h
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef SPYGLASS_GUI_H_
|
2
|
+
#define SPYGLASS_GUI_H_
|
3
|
+
|
4
|
+
#include "spyglass.h"
|
5
|
+
|
6
|
+
namespace Spyglass {
|
7
|
+
namespace GUI {
|
8
|
+
void define_ruby_module();
|
9
|
+
VALUE get_ruby_module();
|
10
|
+
|
11
|
+
static VALUE rb_wait_key(VALUE klass, VALUE timeout);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
#endif // SPYGLASS_GUI_H_
|
@@ -0,0 +1,482 @@
|
|
1
|
+
#include "image.h"
|
2
|
+
|
3
|
+
static VALUE ImageClass;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace Image {
|
7
|
+
void define_ruby_class() {
|
8
|
+
// Class definition
|
9
|
+
ImageClass = rb_define_class_under(Spyglass::get_ruby_module(), "Image", rb_cObject);
|
10
|
+
rb_define_alloc_func(ImageClass, rb_alloc);
|
11
|
+
rb_define_method(ImageClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
12
|
+
|
13
|
+
// Class methods
|
14
|
+
rb_define_singleton_method(ImageClass, "load", RUBY_METHOD_FUNC(rb_load), -1);
|
15
|
+
rb_define_singleton_method(ImageClass, "zeros", RUBY_METHOD_FUNC(rb_zeros), -1);
|
16
|
+
|
17
|
+
// Instance methods
|
18
|
+
rb_define_method(ImageClass, "canny", RUBY_METHOD_FUNC(rb_canny), 2);
|
19
|
+
rb_define_method(ImageClass, "canny!", RUBY_METHOD_FUNC(rb_canny_inplace), 2);
|
20
|
+
rb_define_method(ImageClass, "cols", RUBY_METHOD_FUNC(rb_get_cols), 0);
|
21
|
+
rb_define_method(ImageClass, "contours", RUBY_METHOD_FUNC(rb_get_contours), 0);
|
22
|
+
rb_define_method(ImageClass, "convert", RUBY_METHOD_FUNC(rb_convert), 1);
|
23
|
+
rb_define_method(ImageClass, "convert!", RUBY_METHOD_FUNC(rb_convert_inplace), 1);
|
24
|
+
rb_define_method(ImageClass, "copy!", RUBY_METHOD_FUNC(rb_copy_inplace), -1);
|
25
|
+
rb_define_method(ImageClass, "crop", RUBY_METHOD_FUNC(rb_crop), 1);
|
26
|
+
rb_define_method(ImageClass, "crop!", RUBY_METHOD_FUNC(rb_crop_inplace), 1);
|
27
|
+
rb_define_method(ImageClass, "dilate", RUBY_METHOD_FUNC(rb_dilate), -1);
|
28
|
+
rb_define_method(ImageClass, "dilate!", RUBY_METHOD_FUNC(rb_dilate_inplace), -1);
|
29
|
+
rb_define_method(ImageClass, "draw_contours", RUBY_METHOD_FUNC(rb_draw_contours), 2);
|
30
|
+
rb_define_method(ImageClass, "draw_rectangle", RUBY_METHOD_FUNC(rb_draw_rectangle), 2);
|
31
|
+
rb_define_method(ImageClass, "erode", RUBY_METHOD_FUNC(rb_erode), -1);
|
32
|
+
rb_define_method(ImageClass, "erode!", RUBY_METHOD_FUNC(rb_erode_inplace), -1);
|
33
|
+
rb_define_method(ImageClass, "fill", RUBY_METHOD_FUNC(rb_fill), -1);
|
34
|
+
rb_define_method(ImageClass, "fill!", RUBY_METHOD_FUNC(rb_fill_inplace), -1);
|
35
|
+
rb_define_method(ImageClass, "mean", RUBY_METHOD_FUNC(rb_mean), -1);
|
36
|
+
rb_define_method(ImageClass, "rows", RUBY_METHOD_FUNC(rb_get_rows), 0);
|
37
|
+
rb_define_method(ImageClass, "size", RUBY_METHOD_FUNC(rb_get_size), 0);
|
38
|
+
rb_define_method(ImageClass, "threshold", RUBY_METHOD_FUNC(rb_threshold), -1);
|
39
|
+
rb_define_method(ImageClass, "threshold!", RUBY_METHOD_FUNC(rb_threshold_inplace), -1);
|
40
|
+
rb_define_method(ImageClass, "threshold_inv", RUBY_METHOD_FUNC(rb_threshold_inv), -1);
|
41
|
+
rb_define_method(ImageClass, "threshold_inv!", RUBY_METHOD_FUNC(rb_threshold_inv_inplace), -1);
|
42
|
+
rb_define_method(ImageClass, "write", RUBY_METHOD_FUNC(rb_write), 1);
|
43
|
+
|
44
|
+
// Constants
|
45
|
+
rb_define_const(ImageClass, "TYPE_8UC1", INT2NUM(CV_8UC1));
|
46
|
+
rb_define_const(ImageClass, "TYPE_8UC3", INT2NUM(CV_8UC3));
|
47
|
+
}
|
48
|
+
|
49
|
+
VALUE get_ruby_class() {
|
50
|
+
return ImageClass;
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE rb_alloc(VALUE self) {
|
54
|
+
cv::Mat *mat = new cv::Mat();
|
55
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, mat);
|
56
|
+
}
|
57
|
+
|
58
|
+
static void rb_free(cv::Mat *img) {
|
59
|
+
img->~Mat();
|
60
|
+
delete img;
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
|
64
|
+
if(argc == 0)
|
65
|
+
return self;
|
66
|
+
|
67
|
+
VALUE size, type;
|
68
|
+
rb_scan_args(argc, argv, "02", &size, &type);
|
69
|
+
|
70
|
+
if(RTEST(size) && CLASS_OF(size) != Size::get_ruby_class()) {
|
71
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Size)",
|
72
|
+
rb_obj_classname(size));
|
73
|
+
}
|
74
|
+
|
75
|
+
if(RTEST(type))
|
76
|
+
Check_Type(type, T_FIXNUM);
|
77
|
+
|
78
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
79
|
+
rb_free(img);
|
80
|
+
|
81
|
+
cv::Size *_size = RTEST(size) ? SG_GET_SIZE(size) : new cv::Size();
|
82
|
+
int _type = RTEST(type) ? NUM2INT(type) : CV_8UC3;
|
83
|
+
|
84
|
+
img = new cv::Mat(*_size, _type);
|
85
|
+
Data_Set_Struct(self, img);
|
86
|
+
|
87
|
+
return self;
|
88
|
+
}
|
89
|
+
|
90
|
+
cv::Mat *_do_canny(VALUE self, VALUE threshold1, VALUE threshold2, bool inplace) {
|
91
|
+
Check_Type(threshold1, T_FIXNUM);
|
92
|
+
Check_Type(threshold2, T_FIXNUM);
|
93
|
+
|
94
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
95
|
+
cv::Mat *dest;
|
96
|
+
|
97
|
+
if(inplace)
|
98
|
+
dest = img;
|
99
|
+
else
|
100
|
+
dest = new cv::Mat();
|
101
|
+
|
102
|
+
cv::Canny(*img, *dest, NUM2INT(threshold1), NUM2INT(threshold2));
|
103
|
+
return dest;
|
104
|
+
}
|
105
|
+
|
106
|
+
static VALUE rb_canny(VALUE self, VALUE threshold1, VALUE threshold2) {
|
107
|
+
cv::Mat *img = _do_canny(self, threshold1, threshold2, false);
|
108
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE rb_canny_inplace(VALUE self, VALUE threshold1, VALUE threshold2) {
|
112
|
+
_do_canny(self, threshold1, threshold2, true);
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE rb_copy_inplace(int argc, VALUE *argv, VALUE self) {
|
117
|
+
VALUE src, mask;
|
118
|
+
rb_scan_args(argc, argv, "11", &src, &mask);
|
119
|
+
|
120
|
+
if(CLASS_OF(src) != ImageClass) {
|
121
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
|
122
|
+
rb_obj_classname(src));
|
123
|
+
}
|
124
|
+
|
125
|
+
if(RTEST(mask) && CLASS_OF(mask) != ImageClass) {
|
126
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Rect)",
|
127
|
+
rb_obj_classname(mask));
|
128
|
+
}
|
129
|
+
|
130
|
+
cv::Mat *dest = SG_GET_IMAGE(self);
|
131
|
+
|
132
|
+
rb_free(dest);
|
133
|
+
dest = new cv::Mat();
|
134
|
+
|
135
|
+
cv::Mat *_src = SG_GET_IMAGE(src);
|
136
|
+
|
137
|
+
if(RTEST(mask)) {
|
138
|
+
cv::Mat *_mask = SG_GET_IMAGE(mask);
|
139
|
+
_src->copyTo(*dest, *_mask);
|
140
|
+
} else {
|
141
|
+
_src->copyTo(*dest);
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
Data_Set_Struct(self, dest);
|
146
|
+
return self;
|
147
|
+
}
|
148
|
+
|
149
|
+
cv::Mat *_do_dilate(int argc, VALUE *argv, VALUE self, bool inplace) {
|
150
|
+
VALUE iterations;
|
151
|
+
rb_scan_args(argc, argv, "01", &iterations);
|
152
|
+
|
153
|
+
if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
|
154
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
|
155
|
+
rb_obj_classname(iterations));
|
156
|
+
}
|
157
|
+
|
158
|
+
int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;
|
159
|
+
|
160
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
161
|
+
cv::Mat *dest;
|
162
|
+
|
163
|
+
if(inplace)
|
164
|
+
dest = img;
|
165
|
+
else
|
166
|
+
dest = new cv::Mat();
|
167
|
+
|
168
|
+
cv::dilate(*img, *dest, cv::Mat(), cv::Point(-1, -1), iter);
|
169
|
+
return dest;
|
170
|
+
}
|
171
|
+
|
172
|
+
static VALUE rb_dilate(int argc, VALUE *argv, VALUE self) {
|
173
|
+
cv::Mat *img = _do_dilate(argc, argv, self, false);
|
174
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE rb_dilate_inplace(int argc, VALUE *argv, VALUE self) {
|
178
|
+
_do_dilate(argc, argv, self, true);
|
179
|
+
return self;
|
180
|
+
}
|
181
|
+
|
182
|
+
static VALUE rb_draw_contours(VALUE self, VALUE contours, VALUE color) {
|
183
|
+
if(TYPE(contours) != T_ARRAY && CLASS_OF(contours) != Contour::get_ruby_class())
|
184
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Array or Spyglass::Contour)",
|
185
|
+
rb_obj_classname(contours));
|
186
|
+
|
187
|
+
if(CLASS_OF(color) != Color::get_ruby_class()) {
|
188
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Color)",
|
189
|
+
rb_obj_classname(color));
|
190
|
+
}
|
191
|
+
|
192
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
193
|
+
cv::Scalar *_color = SG_GET_COLOR(color);
|
194
|
+
std::vector<std::vector<cv::Point> > ctrs;
|
195
|
+
|
196
|
+
if(TYPE(contours) == T_ARRAY) {
|
197
|
+
for(int idx = 0; idx < RARRAY_LEN(contours); idx++) {
|
198
|
+
std::vector<cv::Point *> *contour = SG_GET_CONTOUR(rb_ary_entry(contours, idx));
|
199
|
+
ctrs.push_back(Contour::to_value_vector(contour));
|
200
|
+
}
|
201
|
+
} else {
|
202
|
+
std::vector<cv::Point *> *contour = SG_GET_CONTOUR(contours);
|
203
|
+
ctrs.push_back(Contour::to_value_vector(contour));
|
204
|
+
}
|
205
|
+
|
206
|
+
for(int idx = 0; idx < ctrs.size(); idx++)
|
207
|
+
cv::drawContours(*img, ctrs, idx, *_color, CV_FILLED);
|
208
|
+
|
209
|
+
return self;
|
210
|
+
}
|
211
|
+
|
212
|
+
static VALUE rb_draw_rectangle(VALUE self, VALUE rect, VALUE color) {
|
213
|
+
if(CLASS_OF(rect) != Rect::get_ruby_class()) {
|
214
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Rect)",
|
215
|
+
rb_obj_classname(rect));
|
216
|
+
}
|
217
|
+
|
218
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
219
|
+
cv::Rect *_rect = SG_GET_RECT(rect);
|
220
|
+
cv::Scalar *_color = SG_GET_COLOR(color);
|
221
|
+
|
222
|
+
cv::Point bottom_right(_rect->x + _rect->width, _rect->y + _rect->height);
|
223
|
+
|
224
|
+
cv::rectangle(*img, _rect->tl(), bottom_right, *_color);
|
225
|
+
return self;
|
226
|
+
}
|
227
|
+
|
228
|
+
cv::Mat *_do_erode(int argc, VALUE *argv, VALUE self, bool inplace) {
|
229
|
+
VALUE iterations;
|
230
|
+
rb_scan_args(argc, argv, "01", &iterations);
|
231
|
+
|
232
|
+
if(RTEST(iterations) && TYPE(iterations) != T_FIXNUM) {
|
233
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Fixnum)",
|
234
|
+
rb_obj_classname(iterations));
|
235
|
+
}
|
236
|
+
|
237
|
+
int iter = RTEST(iterations) ? FIX2INT(iterations) : 1;
|
238
|
+
|
239
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
240
|
+
cv::Mat *dest;
|
241
|
+
|
242
|
+
if(inplace)
|
243
|
+
dest = img;
|
244
|
+
else
|
245
|
+
dest = new cv::Mat();
|
246
|
+
|
247
|
+
cv::erode(*img, *dest, cv::Mat(), cv::Point(-1, -1), iter);
|
248
|
+
return dest;
|
249
|
+
}
|
250
|
+
|
251
|
+
static VALUE rb_erode(int argc, VALUE *argv, VALUE self) {
|
252
|
+
cv::Mat *img = _do_erode(argc, argv, self, false);
|
253
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
254
|
+
}
|
255
|
+
|
256
|
+
static VALUE rb_erode_inplace(int argc, VALUE *argv, VALUE self) {
|
257
|
+
_do_erode(argc, argv, self, true);
|
258
|
+
return self;
|
259
|
+
}
|
260
|
+
|
261
|
+
cv::Mat *_do_fill(int argc, VALUE *argv, VALUE self, bool inplace) {
|
262
|
+
VALUE color, mask;
|
263
|
+
rb_scan_args(argc, argv, "11", &color, &mask);
|
264
|
+
|
265
|
+
if(CLASS_OF(color) != Color::get_ruby_class())
|
266
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Color)",
|
267
|
+
rb_obj_classname(color));
|
268
|
+
|
269
|
+
if(RTEST(mask) && CLASS_OF(mask) != ImageClass)
|
270
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
|
271
|
+
rb_obj_classname(mask));
|
272
|
+
|
273
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
274
|
+
cv::Mat *dest;
|
275
|
+
|
276
|
+
cv::Scalar *_color = SG_GET_COLOR(color);
|
277
|
+
cv::Mat *_mask = RTEST(mask) ? SG_GET_IMAGE(mask) : new cv::Mat();
|
278
|
+
|
279
|
+
if(inplace)
|
280
|
+
dest = img;
|
281
|
+
else
|
282
|
+
dest = new cv::Mat(*img);
|
283
|
+
|
284
|
+
(*dest).setTo(*_color, *_mask);
|
285
|
+
return dest;
|
286
|
+
}
|
287
|
+
|
288
|
+
static VALUE rb_fill(int argc, VALUE *argv, VALUE self) {
|
289
|
+
cv::Mat *img = _do_fill(argc, argv, self, false);
|
290
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
291
|
+
}
|
292
|
+
|
293
|
+
static VALUE rb_fill_inplace(int argc, VALUE *argv, VALUE self) {
|
294
|
+
_do_fill(argc, argv, self, true);
|
295
|
+
return self;
|
296
|
+
}
|
297
|
+
|
298
|
+
static VALUE rb_load(int argc, VALUE *argv, VALUE klass) {
|
299
|
+
VALUE filename;
|
300
|
+
rb_scan_args(argc, argv, "10", &filename);
|
301
|
+
Check_Type(filename, T_STRING);
|
302
|
+
|
303
|
+
cv::Mat _img = cv::imread(StringValueCStr(filename));
|
304
|
+
cv::Mat *img = new cv::Mat(_img);
|
305
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
306
|
+
}
|
307
|
+
|
308
|
+
static VALUE rb_get_cols(VALUE self) {
|
309
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
310
|
+
return INT2FIX(img->cols);
|
311
|
+
}
|
312
|
+
|
313
|
+
static VALUE rb_get_contours(VALUE self) {
|
314
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
315
|
+
|
316
|
+
std::vector<std::vector<cv::Point> > contours;
|
317
|
+
cv::findContours(*img, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
|
318
|
+
|
319
|
+
return Contour::from_contour_vector(contours);
|
320
|
+
}
|
321
|
+
|
322
|
+
cv::Mat *_do_convert(VALUE self, VALUE color_space, bool inplace) {
|
323
|
+
int code = FIX2INT(color_space);
|
324
|
+
|
325
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
326
|
+
cv::Mat *dest;
|
327
|
+
if(inplace)
|
328
|
+
dest = img;
|
329
|
+
else
|
330
|
+
dest = new cv::Mat();
|
331
|
+
|
332
|
+
cvtColor(*img, *dest, code);
|
333
|
+
return dest;
|
334
|
+
}
|
335
|
+
|
336
|
+
static VALUE rb_convert(VALUE self, VALUE color_space) {
|
337
|
+
cv::Mat *img = _do_convert(self, color_space, false);
|
338
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
339
|
+
}
|
340
|
+
|
341
|
+
static VALUE rb_convert_inplace(VALUE self, VALUE color_space) {
|
342
|
+
cv::Mat *img = _do_convert(self, color_space, true);
|
343
|
+
return self;
|
344
|
+
}
|
345
|
+
|
346
|
+
cv::Mat *_do_crop(VALUE self, VALUE rect) {
|
347
|
+
if(CLASS_OF(rect) != Rect::get_ruby_class()) {
|
348
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Rect)",
|
349
|
+
rb_obj_classname(rect));
|
350
|
+
}
|
351
|
+
|
352
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
353
|
+
cv::Rect *boundaries = SG_GET_RECT(rect);
|
354
|
+
cv::Mat *dest = new cv::Mat();
|
355
|
+
|
356
|
+
(*img)(*boundaries).copyTo(*dest);
|
357
|
+
return dest;
|
358
|
+
}
|
359
|
+
|
360
|
+
static VALUE rb_crop(VALUE self, VALUE rect) {
|
361
|
+
cv::Mat *img = _do_crop(self, rect);
|
362
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
363
|
+
}
|
364
|
+
|
365
|
+
static VALUE rb_crop_inplace(VALUE self, VALUE rect) {
|
366
|
+
// This difers slightly from the other methods for memory reasons.
|
367
|
+
// Whenever you crop an image, OpenCV doesn't automatically reallocate
|
368
|
+
// memory for a smaller size, so we just copy the pixels into a new
|
369
|
+
// instance and get rid of the old one.
|
370
|
+
cv::Mat *old_img = SG_GET_IMAGE(self);
|
371
|
+
cv::Mat *img = _do_crop(self, rect);
|
372
|
+
rb_free(old_img);
|
373
|
+
|
374
|
+
Data_Set_Struct(self, img);
|
375
|
+
return self;
|
376
|
+
}
|
377
|
+
|
378
|
+
static VALUE rb_mean(int argc, VALUE *argv, VALUE self) {
|
379
|
+
VALUE mask;
|
380
|
+
rb_scan_args(argc, argv, "01", &mask);
|
381
|
+
|
382
|
+
if(RTEST(mask) && CLASS_OF(mask) != Image::get_ruby_class()) {
|
383
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
|
384
|
+
rb_obj_classname(mask));
|
385
|
+
}
|
386
|
+
|
387
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
388
|
+
cv::Scalar mean;
|
389
|
+
|
390
|
+
if(RTEST(mask)) {
|
391
|
+
cv::Mat *_mask = SG_GET_IMAGE(mask);
|
392
|
+
mean = cv::mean(*img, *_mask);
|
393
|
+
} else {
|
394
|
+
mean = cv::mean(*img);
|
395
|
+
}
|
396
|
+
|
397
|
+
cv::Scalar *_mean = new cv::Scalar(mean);
|
398
|
+
return Color::from_cvscalar(_mean);
|
399
|
+
}
|
400
|
+
|
401
|
+
static VALUE rb_get_rows(VALUE self) {
|
402
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
403
|
+
return INT2FIX(img->rows);
|
404
|
+
}
|
405
|
+
|
406
|
+
static VALUE rb_get_size(VALUE self) {
|
407
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
408
|
+
return Size::from_cvmat(img);
|
409
|
+
}
|
410
|
+
|
411
|
+
cv::Mat *_do_threshold(int argc, VALUE *argv, VALUE self, bool inverse, bool inplace) {
|
412
|
+
VALUE threshold, replacement, opts;
|
413
|
+
rb_scan_args(argc, argv, "21", &threshold, &replacement, &opts);
|
414
|
+
|
415
|
+
Check_Type(threshold, T_FLOAT);
|
416
|
+
Check_Type(replacement, T_FLOAT);
|
417
|
+
|
418
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
419
|
+
cv::Mat *dest;
|
420
|
+
|
421
|
+
int method = inverse ? cv::THRESH_BINARY_INV : cv::THRESH_BINARY;
|
422
|
+
|
423
|
+
if(inplace)
|
424
|
+
dest = img;
|
425
|
+
else
|
426
|
+
dest = new cv::Mat();
|
427
|
+
|
428
|
+
cv::threshold(*img, *dest, NUM2DBL(threshold), NUM2DBL(replacement), method);
|
429
|
+
return dest;
|
430
|
+
}
|
431
|
+
|
432
|
+
static VALUE rb_threshold(int argc, VALUE *argv, VALUE self) {
|
433
|
+
cv::Mat *img = _do_threshold(argc, argv, self, false, false);
|
434
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
435
|
+
}
|
436
|
+
|
437
|
+
static VALUE rb_threshold_inplace(int argc, VALUE *argv, VALUE self) {
|
438
|
+
_do_threshold(argc, argv, self, false, true);
|
439
|
+
return self;
|
440
|
+
}
|
441
|
+
|
442
|
+
static VALUE rb_threshold_inv(int argc, VALUE *argv, VALUE self) {
|
443
|
+
cv::Mat *img = _do_threshold(argc, argv, self, true, false);
|
444
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
445
|
+
}
|
446
|
+
|
447
|
+
static VALUE rb_threshold_inv_inplace(int argc, VALUE *argv, VALUE self) {
|
448
|
+
_do_threshold(argc, argv, self, true, true);
|
449
|
+
return self;
|
450
|
+
}
|
451
|
+
|
452
|
+
static VALUE rb_write(VALUE self, VALUE filename) {
|
453
|
+
Check_Type(filename, T_STRING);
|
454
|
+
|
455
|
+
cv::Mat *img = SG_GET_IMAGE(self);
|
456
|
+
bool res = cv::imwrite(StringValueCStr(filename), *img);
|
457
|
+
return (res) ? Qtrue : Qfalse;
|
458
|
+
}
|
459
|
+
|
460
|
+
static VALUE rb_zeros(int argc, VALUE *argv, VALUE klass) {
|
461
|
+
VALUE size, type;
|
462
|
+
rb_scan_args(argc, argv, "11", &size, &type);
|
463
|
+
|
464
|
+
if(CLASS_OF(size) != Size::get_ruby_class()) {
|
465
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Size)",
|
466
|
+
rb_obj_classname(size));
|
467
|
+
}
|
468
|
+
|
469
|
+
cv::Size *_size = SG_GET_SIZE(size);
|
470
|
+
|
471
|
+
int _type = RTEST(type) ? NUM2INT(type) : CV_8UC1;
|
472
|
+
|
473
|
+
cv::Mat zeros = cv::Mat::zeros(*_size, _type);
|
474
|
+
cv::Mat *img = new cv::Mat(zeros);
|
475
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, img);
|
476
|
+
}
|
477
|
+
|
478
|
+
VALUE from_cvmat(cv::Mat *mat) {
|
479
|
+
return Data_Wrap_Struct(ImageClass, NULL, rb_free, mat);
|
480
|
+
}
|
481
|
+
}
|
482
|
+
}
|