spyglass 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 368c20a70c719acceb1244b9cab1ad6274622eaa
|
4
|
+
data.tar.gz: 00e92f3dd911a30304ec83269b254420f5acdc57
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b4fac2a901002853912daf86ce7192a6b6fe05d8167c26bcdf7c30ff14e46dacab58c55186527084fcb5eeb80eabc76ac65933e962ad4cbfefbc44dbf0ef6bf3
|
7
|
+
data.tar.gz: 6880d0ee03bd34737d78fa8609b0feaf672618074612386ee22e27750da780f120f0246f3996a7a197962ea62715c180d19357c544d269bd451a6bde3e58bc35
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 André Medeiros
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Spyglass
|
2
|
+
========
|
3
|
+
|
4
|
+
OpenCV in Ruby, made simple.
|
5
|
+
|
6
|
+
Why?
|
7
|
+
====
|
8
|
+
|
9
|
+
Because I've been working on a computer vision project for 2 months and missed Ruby. Also, I wanted a nice, coherent API that would make me happy to use.
|
10
|
+
|
11
|
+
Requirements
|
12
|
+
============
|
13
|
+
|
14
|
+
This gem requires OpenCV 2.4.5 or better. For an in-depth OpenCV installation guide, refer to the [OpenCV Wiki page](http://opencv.willowgarage.com/wiki/InstallGuide). It also depends on `pkg-config` being installed. I'm also accepting pull requests for Windows.
|
15
|
+
|
16
|
+
TODO
|
17
|
+
====
|
18
|
+
|
19
|
+
There is a lot left to implement, as I've really only ported the parts of the API that I've used so far. Apart from that, there's:
|
20
|
+
|
21
|
+
* Documentation
|
22
|
+
* More tests
|
23
|
+
|
24
|
+
Code Status
|
25
|
+
===========
|
26
|
+
|
27
|
+
* [![Build Status](https://travis-ci.org/andremedeiros/spyglass.png?branch=master)](https://travis-ci.org/andremedeiros/spyglass)
|
28
|
+
* [![Dependency Status](https://gemnasium.com/andremedeiros/spyglass.png)](https://gemnasium.com/andremedeiros/spyglass)
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$LOAD_PATH.unshift('lib')
|
2
|
+
require 'spyglass'
|
3
|
+
|
4
|
+
include Spyglass
|
5
|
+
|
6
|
+
puts <<-eos
|
7
|
+
WARNING: This demo might not work well with cameras that do auto-exposure.
|
8
|
+
If you can, disable those features for a better feel of this demo.
|
9
|
+
|
10
|
+
eos
|
11
|
+
|
12
|
+
bg = BackgroundSubtractor.new
|
13
|
+
window = GUI::Window.new("Beach!")
|
14
|
+
cap = VideoCapture.new 0, width: 640, height: 480
|
15
|
+
frame = Image.new
|
16
|
+
result = Image.new
|
17
|
+
beach = Image.load File.expand_path('images/beach.jpg', File.dirname(__FILE__))
|
18
|
+
|
19
|
+
puts "Step off the camera's field of vision!"
|
20
|
+
3.times { |sec| puts "... #{ 3 - sec }"; sleep(1) }
|
21
|
+
|
22
|
+
puts "Training background subtractor..."
|
23
|
+
20.times { cap >> frame; bg.subtract frame, 0.05 }
|
24
|
+
|
25
|
+
puts "Show yourself ;-)"
|
26
|
+
|
27
|
+
loop do
|
28
|
+
cap >> frame
|
29
|
+
|
30
|
+
result.copy!(beach)
|
31
|
+
delta = bg.subtract(frame, 0)
|
32
|
+
result.copy!(frame, delta);
|
33
|
+
|
34
|
+
window.show result
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift('lib')
|
2
|
+
require 'spyglass'
|
3
|
+
|
4
|
+
include Spyglass
|
5
|
+
|
6
|
+
classifier = CascadeClassifier.new("spec/fixtures/haarcascade_frontalface_default.xml")
|
7
|
+
window = GUI::Window.new "Video"
|
8
|
+
cap = VideoCapture.new 0
|
9
|
+
frame = Image.new
|
10
|
+
|
11
|
+
loop do
|
12
|
+
cap >> frame
|
13
|
+
|
14
|
+
rects = classifier.detect(frame, scale_factor: 1.5, min_size: Size.new(30, 30))
|
15
|
+
rects.map { |r| frame.draw_rectangle(r) }
|
16
|
+
|
17
|
+
window.show(frame)
|
18
|
+
|
19
|
+
break if GUI::wait_key(10) > 0
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift('lib')
|
2
|
+
require 'spyglass'
|
3
|
+
|
4
|
+
include Spyglass
|
5
|
+
|
6
|
+
window = GUI::Window.new "Original"
|
7
|
+
apple = Image.load File.expand_path('images/apple.jpg', File.dirname(__FILE__))
|
8
|
+
|
9
|
+
window.show(apple)
|
10
|
+
|
11
|
+
canny = apple.convert(ColorSpace[:BGR => :Gray])
|
12
|
+
canny.canny!(200, 300)
|
13
|
+
|
14
|
+
result = Image.new
|
15
|
+
result.copy!(apple)
|
16
|
+
result.draw_contours(canny.contours)
|
17
|
+
|
18
|
+
result_window = GUI::Window.new "Contours"
|
19
|
+
result_window.show(result)
|
20
|
+
|
21
|
+
loop do
|
22
|
+
break if GUI::wait_key(10) > 0
|
23
|
+
end
|
24
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#include "background_subtractor.h"
|
2
|
+
|
3
|
+
static VALUE BackgroundSubtractorClass;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace BackgroundSubtractor {
|
7
|
+
void define_ruby_class() {
|
8
|
+
// Class definition
|
9
|
+
BackgroundSubtractorClass = rb_define_class_under(Spyglass::get_ruby_module(), "BackgroundSubtractor", rb_cObject);
|
10
|
+
rb_define_alloc_func(BackgroundSubtractorClass, rb_alloc);
|
11
|
+
rb_define_method(BackgroundSubtractorClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
12
|
+
|
13
|
+
// Instance methods
|
14
|
+
rb_define_method(BackgroundSubtractorClass, "subtract", RUBY_METHOD_FUNC(rb_subtract), -1);
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE get_ruby_class() {
|
18
|
+
return BackgroundSubtractorClass;
|
19
|
+
}
|
20
|
+
|
21
|
+
static VALUE rb_alloc(VALUE self) {
|
22
|
+
cv::BackgroundSubtractorMOG2 *bg = new cv::BackgroundSubtractorMOG2();
|
23
|
+
return Data_Wrap_Struct(BackgroundSubtractorClass, NULL, rb_free, bg);
|
24
|
+
}
|
25
|
+
|
26
|
+
static void rb_free(cv::BackgroundSubtractorMOG2 *bg) {
|
27
|
+
bg->~BackgroundSubtractorMOG2();
|
28
|
+
delete bg;
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
|
32
|
+
VALUE opts;
|
33
|
+
rb_scan_args(argc, argv, "01", &opts);
|
34
|
+
|
35
|
+
if(!RTEST(opts))
|
36
|
+
return self;
|
37
|
+
|
38
|
+
cv::BackgroundSubtractorMOG2 *bg = SG_GET_BG_SUBTRACTOR(self);
|
39
|
+
|
40
|
+
SG_OPTION(opts, int, history, 500, NUM2INT);
|
41
|
+
SG_OPTION(opts, double, threshold, 8.0, NUM2DBL);
|
42
|
+
SG_OPTION(opts, bool, shadow_detection, true, RTEST);
|
43
|
+
|
44
|
+
bg->set("history", history);
|
45
|
+
bg->set("varThreshold", threshold);
|
46
|
+
bg->set("detectShadows", shadow_detection);
|
47
|
+
|
48
|
+
return self;
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE rb_subtract(int argc, VALUE *argv, VALUE self) {
|
52
|
+
VALUE image, learn_rate;
|
53
|
+
double rate;
|
54
|
+
|
55
|
+
rb_scan_args(argc, argv, "11", &image, &learn_rate);
|
56
|
+
|
57
|
+
if(CLASS_OF(image) != Image::get_ruby_class()) {
|
58
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
|
59
|
+
rb_obj_classname(image));
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
if(RTEST(learn_rate) && TYPE(learn_rate) != T_FLOAT && TYPE(learn_rate) != T_FIXNUM)
|
64
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Float or Fixnum)",
|
65
|
+
rb_obj_classname(learn_rate));
|
66
|
+
|
67
|
+
rate = RTEST(learn_rate) ? NUM2DBL(learn_rate) : -1.0;
|
68
|
+
|
69
|
+
cv::BackgroundSubtractorMOG2 *bg = SG_GET_BG_SUBTRACTOR(self);
|
70
|
+
cv::Mat *img = SG_GET_IMAGE(image);
|
71
|
+
|
72
|
+
cv::Mat *delta = new cv::Mat();
|
73
|
+
(*bg)(*img, *delta, rate);
|
74
|
+
|
75
|
+
return Image::from_cvmat(delta);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef SPYGLASS_BACKGROUND_SUBTRACTOR_H_
|
2
|
+
#define SPYGLASS_BACKGROUND_SUBTRACTOR_H_
|
3
|
+
|
4
|
+
#include "spyglass.h"
|
5
|
+
|
6
|
+
namespace Spyglass {
|
7
|
+
namespace BackgroundSubtractor {
|
8
|
+
void define_ruby_class();
|
9
|
+
VALUE get_ruby_class();
|
10
|
+
|
11
|
+
static VALUE rb_alloc(VALUE self);
|
12
|
+
static void rb_free(cv::BackgroundSubtractorMOG2 *bg);
|
13
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self);
|
14
|
+
static VALUE rb_subtract(int argc, VALUE *argv, VALUE self);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
#endif // SPYGLASS_BACKGROUND_SUBTRACTOR_H_
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#include "cascade_classifier.h"
|
2
|
+
|
3
|
+
static VALUE CascadeClassifierClass;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace CascadeClassifier {
|
7
|
+
void define_ruby_class() {
|
8
|
+
// Class definition
|
9
|
+
CascadeClassifierClass = rb_define_class_under(Spyglass::get_ruby_module(), "CascadeClassifier", rb_cObject);
|
10
|
+
rb_define_alloc_func(CascadeClassifierClass, rb_alloc);
|
11
|
+
rb_define_method(CascadeClassifierClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), 1);
|
12
|
+
|
13
|
+
// Instance methods
|
14
|
+
rb_define_method(CascadeClassifierClass, "detect", RUBY_METHOD_FUNC(rb_detect), -1);
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE get_ruby_class() {
|
18
|
+
return CascadeClassifierClass;
|
19
|
+
}
|
20
|
+
|
21
|
+
static VALUE rb_alloc(VALUE self) {
|
22
|
+
cv::CascadeClassifier *classifier = new cv::CascadeClassifier();
|
23
|
+
return Data_Wrap_Struct(CascadeClassifierClass, NULL, rb_free, classifier);
|
24
|
+
}
|
25
|
+
|
26
|
+
static void rb_free(cv::CascadeClassifier *classifier) {
|
27
|
+
classifier->~CascadeClassifier();
|
28
|
+
delete classifier;
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE rb_initialize(VALUE self, VALUE src) {
|
32
|
+
Check_Type(src, T_STRING);
|
33
|
+
|
34
|
+
cv::CascadeClassifier *classifier = SG_GET_CLASSIFIER(self);
|
35
|
+
|
36
|
+
classifier->load(StringValueCStr(src));
|
37
|
+
|
38
|
+
return self;
|
39
|
+
}
|
40
|
+
|
41
|
+
static VALUE rb_detect(int argc, VALUE *argv, VALUE self) {
|
42
|
+
VALUE image, opts;
|
43
|
+
rb_scan_args(argc, argv, "11", &image, &opts);
|
44
|
+
|
45
|
+
if(CLASS_OF(image) != Image::get_ruby_class()) {
|
46
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Spyglass::Image)",
|
47
|
+
rb_obj_classname(image));
|
48
|
+
}
|
49
|
+
|
50
|
+
cv::CascadeClassifier *classifier = SG_GET_CLASSIFIER(self);
|
51
|
+
cv::Mat *img = SG_GET_IMAGE(image);
|
52
|
+
|
53
|
+
SG_OPTION(opts, double, scale_factor, 1.1, NUM2DBL);
|
54
|
+
SG_OPTION(opts, int, min_neighbors, 3, NUM2INT);
|
55
|
+
SG_OPTION(opts, cv::Size *, min_size, new cv::Size(), SG_GET_SIZE);
|
56
|
+
SG_OPTION(opts, cv::Size *, max_size, new cv::Size(), SG_GET_SIZE);
|
57
|
+
|
58
|
+
std::vector<cv::Rect> results;
|
59
|
+
classifier->detectMultiScale(*img, results, scale_factor, min_neighbors, 0, *min_size, *max_size);
|
60
|
+
|
61
|
+
VALUE result = rb_ary_new2(results.size());
|
62
|
+
for(size_t i = 0; i < results.size(); i++) {
|
63
|
+
cv::Rect *rect = new cv::Rect(results[i]);
|
64
|
+
rb_ary_store(result, (long)i, Rect::from_cvrect(rect));
|
65
|
+
}
|
66
|
+
|
67
|
+
return result;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef SPYGLASS_CASCADE_CLASSIFIER_H_
|
2
|
+
#define SPYGLASS_CASCADE_CLASSIFIER_H_
|
3
|
+
|
4
|
+
#include "spyglass.h"
|
5
|
+
|
6
|
+
namespace Spyglass {
|
7
|
+
namespace CascadeClassifier {
|
8
|
+
void define_ruby_class();
|
9
|
+
VALUE get_ruby_class();
|
10
|
+
|
11
|
+
static VALUE rb_alloc(VALUE self);
|
12
|
+
static void rb_free(cv::CascadeClassifier *classifier);
|
13
|
+
static VALUE rb_initialize(VALUE self, VALUE src);
|
14
|
+
static VALUE rb_detect(int argc, VALUE *argv, VALUE self);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
#endif // SPYGLASS_CASCADE_CLASSIFIER_H_
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#include "color.h"
|
2
|
+
|
3
|
+
static VALUE ColorClass;
|
4
|
+
|
5
|
+
namespace Spyglass {
|
6
|
+
namespace Color {
|
7
|
+
void define_ruby_class() {
|
8
|
+
// Class definition
|
9
|
+
ColorClass = rb_define_class_under(Spyglass::get_ruby_module(), "Color", rb_cObject);
|
10
|
+
rb_define_alloc_func(ColorClass, rb_alloc);
|
11
|
+
rb_define_method(ColorClass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
12
|
+
|
13
|
+
// Instance methods
|
14
|
+
rb_define_method(ColorClass, "[]", RUBY_METHOD_FUNC(rb_get_color), 1);
|
15
|
+
rb_define_method(ColorClass, "to_a", RUBY_METHOD_FUNC(rb_to_a), 0);
|
16
|
+
rb_define_method(ColorClass, "zeros?", RUBY_METHOD_FUNC(rb_is_zeros), 0);
|
17
|
+
}
|
18
|
+
|
19
|
+
VALUE get_ruby_class() {
|
20
|
+
return ColorClass;
|
21
|
+
}
|
22
|
+
|
23
|
+
static VALUE rb_alloc(VALUE self) {
|
24
|
+
cv::Scalar *color = new cv::Scalar(0, 0, 0, 0);
|
25
|
+
return Data_Wrap_Struct(ColorClass, NULL, rb_free, color);
|
26
|
+
}
|
27
|
+
|
28
|
+
static void rb_free(cv::Scalar *color) {
|
29
|
+
delete color;
|
30
|
+
}
|
31
|
+
|
32
|
+
static VALUE rb_initialize(int argc, VALUE *argv, VALUE self) {
|
33
|
+
if(argc < 1 || argc > 4)
|
34
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..4)", argc);
|
35
|
+
|
36
|
+
cv::Scalar *color = SG_GET_COLOR(self);
|
37
|
+
|
38
|
+
for(int idx = 0; idx < argc; idx++) {
|
39
|
+
(*color)[idx] = NUM2DBL(argv[idx]);
|
40
|
+
}
|
41
|
+
|
42
|
+
return self;
|
43
|
+
}
|
44
|
+
|
45
|
+
static VALUE rb_get_color(VALUE self, VALUE index) {
|
46
|
+
Check_Type(index, T_FIXNUM);
|
47
|
+
|
48
|
+
int idx = NUM2INT(index);
|
49
|
+
|
50
|
+
if(idx < 0 || idx > 3)
|
51
|
+
return Qnil;
|
52
|
+
|
53
|
+
cv::Scalar *color = SG_GET_COLOR(self);
|
54
|
+
double val = (*color)[idx];
|
55
|
+
return DBL2NUM(val);
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE rb_to_a(VALUE self) {
|
59
|
+
cv::Scalar *color = SG_GET_COLOR(self);
|
60
|
+
VALUE ary = rb_ary_new2(4);
|
61
|
+
|
62
|
+
for(int idx = 0; idx < 4; idx++)
|
63
|
+
rb_ary_store(ary, idx, DBL2NUM((*color)[idx]));
|
64
|
+
|
65
|
+
return ary;
|
66
|
+
}
|
67
|
+
|
68
|
+
static VALUE rb_is_zeros(VALUE self) {
|
69
|
+
cv::Scalar *color = SG_GET_COLOR(self);
|
70
|
+
bool all_zeros = true;
|
71
|
+
for(int idx = 0; idx < 4; idx++) {
|
72
|
+
if((*color)[idx] > 0)
|
73
|
+
all_zeros = false;
|
74
|
+
}
|
75
|
+
|
76
|
+
return all_zeros ? Qtrue : Qfalse;
|
77
|
+
}
|
78
|
+
|
79
|
+
VALUE from_cvscalar(cv::Scalar *color) {
|
80
|
+
return Data_Wrap_Struct(ColorClass, NULL, rb_free, color);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|