bonanza-ruby-opencv 0.0.13.20140330211753
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 +28 -0
- data/.yardopts +3 -0
- data/DEVELOPERS_NOTE.md +137 -0
- data/Gemfile +9 -0
- data/History.txt +5 -0
- data/License.txt +30 -0
- data/Manifest.txt +239 -0
- data/README.md +98 -0
- data/Rakefile +99 -0
- data/config.yml +7 -0
- data/examples/alpha_blend.rb +21 -0
- data/examples/contours/bitmap-contours-with-labels.png +0 -0
- data/examples/contours/bitmap-contours.png +0 -0
- data/examples/contours/bounding-box-detect-canny.rb +62 -0
- data/examples/contours/contour_retrieval_modes.rb +139 -0
- data/examples/contours/rotated-boxes.jpg +0 -0
- data/examples/convexhull.rb +47 -0
- data/examples/face_detect.rb +20 -0
- data/examples/facerec/create_csv.rb +43 -0
- data/examples/facerec/facerec_eigenfaces.rb +132 -0
- data/examples/facerec/facerec_fisherfaces.rb +131 -0
- data/examples/facerec/facerec_lbph.rb +116 -0
- data/examples/facerec/readme.md +111 -0
- data/examples/find_obj.rb +169 -0
- data/examples/houghcircle.rb +22 -0
- data/examples/images/box.png +0 -0
- data/examples/images/box_in_scene.png +0 -0
- data/examples/images/inpaint.png +0 -0
- data/examples/images/lena-256x256.jpg +0 -0
- data/examples/images/lena-eyes.jpg +0 -0
- data/examples/images/lenna-rotated.jpg +0 -0
- data/examples/images/lenna.jpg +0 -0
- data/examples/images/stuff.jpg +0 -0
- data/examples/images/tiffany.jpg +0 -0
- data/examples/inpaint.rb +57 -0
- data/examples/match_kdtree.rb +88 -0
- data/examples/match_template.rb +26 -0
- data/examples/paint.rb +70 -0
- data/examples/snake.rb +43 -0
- data/ext/opencv/algorithm.cpp +291 -0
- data/ext/opencv/algorithm.h +38 -0
- data/ext/opencv/curve.cpp +127 -0
- data/ext/opencv/curve.h +34 -0
- data/ext/opencv/cvavgcomp.cpp +64 -0
- data/ext/opencv/cvavgcomp.h +39 -0
- data/ext/opencv/cvbox2d.cpp +195 -0
- data/ext/opencv/cvbox2d.h +61 -0
- data/ext/opencv/cvcapture.cpp +607 -0
- data/ext/opencv/cvcapture.h +72 -0
- data/ext/opencv/cvchain.cpp +233 -0
- data/ext/opencv/cvchain.h +46 -0
- data/ext/opencv/cvcircle32f.cpp +126 -0
- data/ext/opencv/cvcircle32f.h +52 -0
- data/ext/opencv/cvconnectedcomp.cpp +156 -0
- data/ext/opencv/cvconnectedcomp.h +49 -0
- data/ext/opencv/cvcontour.cpp +332 -0
- data/ext/opencv/cvcontour.h +48 -0
- data/ext/opencv/cvcontourtree.cpp +96 -0
- data/ext/opencv/cvcontourtree.h +41 -0
- data/ext/opencv/cvconvexitydefect.cpp +92 -0
- data/ext/opencv/cvconvexitydefect.h +42 -0
- data/ext/opencv/cverror.cpp +115 -0
- data/ext/opencv/cverror.h +28 -0
- data/ext/opencv/cvfeaturetree.cpp +123 -0
- data/ext/opencv/cvfeaturetree.h +55 -0
- data/ext/opencv/cvfont.cpp +228 -0
- data/ext/opencv/cvfont.h +64 -0
- data/ext/opencv/cvhaarclassifiercascade.cpp +148 -0
- data/ext/opencv/cvhaarclassifiercascade.h +39 -0
- data/ext/opencv/cvhistogram.cpp +715 -0
- data/ext/opencv/cvhistogram.h +73 -0
- data/ext/opencv/cvhumoments.cpp +178 -0
- data/ext/opencv/cvhumoments.h +51 -0
- data/ext/opencv/cvline.cpp +159 -0
- data/ext/opencv/cvline.h +54 -0
- data/ext/opencv/cvmat.cpp +6829 -0
- data/ext/opencv/cvmat.h +323 -0
- data/ext/opencv/cvmemstorage.cpp +73 -0
- data/ext/opencv/cvmemstorage.h +53 -0
- data/ext/opencv/cvmoments.cpp +293 -0
- data/ext/opencv/cvmoments.h +75 -0
- data/ext/opencv/cvpoint.cpp +265 -0
- data/ext/opencv/cvpoint.h +67 -0
- data/ext/opencv/cvpoint2d32f.cpp +216 -0
- data/ext/opencv/cvpoint2d32f.h +63 -0
- data/ext/opencv/cvpoint3d32f.cpp +252 -0
- data/ext/opencv/cvpoint3d32f.h +66 -0
- data/ext/opencv/cvrect.cpp +441 -0
- data/ext/opencv/cvrect.h +88 -0
- data/ext/opencv/cvscalar.cpp +301 -0
- data/ext/opencv/cvscalar.h +76 -0
- data/ext/opencv/cvseq.cpp +605 -0
- data/ext/opencv/cvseq.h +74 -0
- data/ext/opencv/cvsize.cpp +227 -0
- data/ext/opencv/cvsize.h +65 -0
- data/ext/opencv/cvsize2d32f.cpp +215 -0
- data/ext/opencv/cvsize2d32f.h +64 -0
- data/ext/opencv/cvslice.cpp +126 -0
- data/ext/opencv/cvslice.h +61 -0
- data/ext/opencv/cvsurfparams.cpp +208 -0
- data/ext/opencv/cvsurfparams.h +58 -0
- data/ext/opencv/cvsurfpoint.cpp +279 -0
- data/ext/opencv/cvsurfpoint.h +54 -0
- data/ext/opencv/cvtermcriteria.cpp +198 -0
- data/ext/opencv/cvtermcriteria.h +71 -0
- data/ext/opencv/cvtwopoints.cpp +122 -0
- data/ext/opencv/cvtwopoints.h +51 -0
- data/ext/opencv/cvutils.cpp +221 -0
- data/ext/opencv/cvutils.h +31 -0
- data/ext/opencv/cvvideowriter.cpp +142 -0
- data/ext/opencv/cvvideowriter.h +43 -0
- data/ext/opencv/eigenfaces.cpp +75 -0
- data/ext/opencv/eigenfaces.h +30 -0
- data/ext/opencv/extconf.rb +82 -0
- data/ext/opencv/facerecognizer.cpp +181 -0
- data/ext/opencv/facerecognizer.h +46 -0
- data/ext/opencv/fisherfaces.cpp +75 -0
- data/ext/opencv/fisherfaces.h +30 -0
- data/ext/opencv/gui.cpp +71 -0
- data/ext/opencv/gui.h +30 -0
- data/ext/opencv/iplconvkernel.cpp +198 -0
- data/ext/opencv/iplconvkernel.h +71 -0
- data/ext/opencv/iplimage.cpp +666 -0
- data/ext/opencv/iplimage.h +75 -0
- data/ext/opencv/lbph.cpp +78 -0
- data/ext/opencv/lbph.h +30 -0
- data/ext/opencv/mouseevent.cpp +186 -0
- data/ext/opencv/mouseevent.h +56 -0
- data/ext/opencv/opencv.cpp +833 -0
- data/ext/opencv/opencv.h +405 -0
- data/ext/opencv/pointset.cpp +280 -0
- data/ext/opencv/pointset.h +68 -0
- data/ext/opencv/trackbar.cpp +127 -0
- data/ext/opencv/trackbar.h +69 -0
- data/ext/opencv/window.cpp +377 -0
- data/ext/opencv/window.h +66 -0
- data/images/CvMat_sobel.png +0 -0
- data/images/CvMat_sub_rect.png +0 -0
- data/images/CvSeq_relationmap.png +0 -0
- data/lib/opencv.rb +12 -0
- data/lib/opencv/psyched_yaml.rb +22 -0
- data/lib/opencv/version.rb +4 -0
- data/test/eigenfaces_save.xml +7524 -0
- data/test/fisherfaces_save.xml +7530 -0
- data/test/helper.rb +166 -0
- data/test/lbph_save.xml +4304 -0
- data/test/runner.rb +30 -0
- data/test/samples/airplane.jpg +0 -0
- data/test/samples/baboon.jpg +0 -0
- data/test/samples/baboon200.jpg +0 -0
- data/test/samples/baboon200_rotated.jpg +0 -0
- data/test/samples/blank0.jpg +0 -0
- data/test/samples/blank1.jpg +0 -0
- data/test/samples/blank2.jpg +0 -0
- data/test/samples/blank3.jpg +0 -0
- data/test/samples/blank4.jpg +0 -0
- data/test/samples/blank5.jpg +0 -0
- data/test/samples/blank6.jpg +0 -0
- data/test/samples/blank7.jpg +0 -0
- data/test/samples/blank8.jpg +0 -0
- data/test/samples/blank9.jpg +0 -0
- data/test/samples/cat.jpg +0 -0
- data/test/samples/chessboard.jpg +0 -0
- data/test/samples/contours.jpg +0 -0
- data/test/samples/fruits.jpg +0 -0
- data/test/samples/haarcascade_frontalface_alt.xml.gz +0 -0
- data/test/samples/inpaint-mask.bmp +0 -0
- data/test/samples/lena-256x256.jpg +0 -0
- data/test/samples/lena-32x32.jpg +0 -0
- data/test/samples/lena-eyes.jpg +0 -0
- data/test/samples/lena-inpaint.jpg +0 -0
- data/test/samples/lena.jpg +0 -0
- data/test/samples/lines.jpg +0 -0
- data/test/samples/messy0.jpg +0 -0
- data/test/samples/messy1.jpg +0 -0
- data/test/samples/movie_sample.avi +0 -0
- data/test/samples/one_way_train_0000.jpg +0 -0
- data/test/samples/one_way_train_0001.jpg +0 -0
- data/test/samples/partially_blank0.jpg +0 -0
- data/test/samples/partially_blank1.jpg +0 -0
- data/test/samples/smooth0.jpg +0 -0
- data/test/samples/smooth1.jpg +0 -0
- data/test/samples/smooth2.jpg +0 -0
- data/test/samples/smooth3.jpg +0 -0
- data/test/samples/smooth4.jpg +0 -0
- data/test/samples/smooth5.jpg +0 -0
- data/test/samples/smooth6.jpg +0 -0
- data/test/samples/str-cv-rotated.jpg +0 -0
- data/test/samples/str-cv.jpg +0 -0
- data/test/samples/str-ov.jpg +0 -0
- data/test/samples/stuff.jpg +0 -0
- data/test/test_curve.rb +43 -0
- data/test/test_cvavgcomp.rb +24 -0
- data/test/test_cvbox2d.rb +76 -0
- data/test/test_cvcapture.rb +183 -0
- data/test/test_cvchain.rb +108 -0
- data/test/test_cvcircle32f.rb +41 -0
- data/test/test_cvconnectedcomp.rb +61 -0
- data/test/test_cvcontour.rb +150 -0
- data/test/test_cvcontourtree.rb +43 -0
- data/test/test_cverror.rb +50 -0
- data/test/test_cvfeaturetree.rb +65 -0
- data/test/test_cvfont.rb +58 -0
- data/test/test_cvhaarclassifiercascade.rb +63 -0
- data/test/test_cvhistogram.rb +271 -0
- data/test/test_cvhumoments.rb +83 -0
- data/test/test_cvline.rb +50 -0
- data/test/test_cvmat.rb +3003 -0
- data/test/test_cvmat_drawing.rb +349 -0
- data/test/test_cvmat_dxt.rb +150 -0
- data/test/test_cvmat_imageprocessing.rb +2085 -0
- data/test/test_cvmoments.rb +180 -0
- data/test/test_cvpoint.rb +75 -0
- data/test/test_cvpoint2d32f.rb +75 -0
- data/test/test_cvpoint3d32f.rb +93 -0
- data/test/test_cvrect.rb +144 -0
- data/test/test_cvscalar.rb +113 -0
- data/test/test_cvseq.rb +295 -0
- data/test/test_cvsize.rb +75 -0
- data/test/test_cvsize2d32f.rb +75 -0
- data/test/test_cvslice.rb +31 -0
- data/test/test_cvsurfparams.rb +57 -0
- data/test/test_cvsurfpoint.rb +66 -0
- data/test/test_cvtermcriteria.rb +56 -0
- data/test/test_cvtwopoints.rb +40 -0
- data/test/test_cvvideowriter.rb +58 -0
- data/test/test_eigenfaces.rb +93 -0
- data/test/test_fisherfaces.rb +93 -0
- data/test/test_iplconvkernel.rb +54 -0
- data/test/test_iplimage.rb +232 -0
- data/test/test_lbph.rb +152 -0
- data/test/test_mouseevent.rb +17 -0
- data/test/test_opencv.rb +360 -0
- data/test/test_pointset.rb +128 -0
- data/test/test_preliminary.rb +130 -0
- data/test/test_trackbar.rb +47 -0
- data/test/test_window.rb +115 -0
- data/yard_extension.rb +5 -0
- metadata +399 -0
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# ruby-opencv
|
2
|
+
|
3
|
+
An OpenCV wrapper for Ruby.
|
4
|
+
|
5
|
+
* Web site: <https://github.com/ruby-opencv/ruby-opencv>
|
6
|
+
* Ruby 1.9.3, 2.0.0, 2.1.x and OpenCV 2.4.8 are supported.
|
7
|
+
|
8
|
+
## Requirement
|
9
|
+
|
10
|
+
* OpenCV <http://opencv.org/>
|
11
|
+
* [Download](http://sourceforge.net/projects/opencvlibrary/)
|
12
|
+
* [Install guide](http://docs.opencv.org/doc/tutorials/introduction/table_of_content_introduction/table_of_content_introduction.html#table-of-content-introduction)
|
13
|
+
|
14
|
+
## Install
|
15
|
+
### Linux/Mac
|
16
|
+
1. Install [OpenCV](http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/)
|
17
|
+
2. Install ruby-opencv
|
18
|
+
|
19
|
+
```
|
20
|
+
$ gem install ruby-opencv -- --with-opencv-dir=/path/to/opencvdir
|
21
|
+
```
|
22
|
+
|
23
|
+
Note: **/path/to/opencvdir** is the directory where you installed OpenCV.
|
24
|
+
|
25
|
+
|
26
|
+
### Windows
|
27
|
+
You can use pre-build binary for Windows (mswin32).
|
28
|
+
|
29
|
+
1. Install [OpenCV](http://sourceforge.net/projects/opencvlibrary/files/opencv-win/)
|
30
|
+
2. Set path to OpenCV libraries. When you installed OpenCV to **C:\opencv**, add **C:\opencv\build\x86\vc10\bin** to the systems path.
|
31
|
+
3. Install ruby-opencv
|
32
|
+
|
33
|
+
```
|
34
|
+
$ gem install ruby-opencv
|
35
|
+
```
|
36
|
+
|
37
|
+
## Sample code
|
38
|
+
### Load and Display an Image
|
39
|
+
|
40
|
+
A sample to load and display an image. An equivalent code of [this tutorial](http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#display-image).
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
require 'opencv'
|
44
|
+
include OpenCV
|
45
|
+
|
46
|
+
if ARGV.size == 0
|
47
|
+
puts "Usage: ruby #{__FILE__} ImageToLoadAndDisplay"
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
image = nil
|
52
|
+
begin
|
53
|
+
image = CvMat.load(ARGV[0], CV_LOAD_IMAGE_COLOR) # Read the file.
|
54
|
+
rescue
|
55
|
+
puts 'Could not open or find the image.'
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
|
59
|
+
window = GUI::Window.new('Display window') # Create a window for display.
|
60
|
+
window.show(image) # Show our image inside it.
|
61
|
+
GUI::wait_key # Wait for a keystroke in the window.
|
62
|
+
```
|
63
|
+
|
64
|
+
### Face Detection
|
65
|
+
|
66
|
+
A sample to detect faces from an image.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
require 'opencv'
|
70
|
+
include OpenCV
|
71
|
+
|
72
|
+
if ARGV.length < 2
|
73
|
+
puts "Usage: ruby #{__FILE__} source dest"
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
|
77
|
+
data = './data/haarcascades/haarcascade_frontalface_alt.xml'
|
78
|
+
detector = CvHaarClassifierCascade::load(data)
|
79
|
+
image = CvMat.load(ARGV[0])
|
80
|
+
detector.detect_objects(image).each do |region|
|
81
|
+
color = CvColor::Blue
|
82
|
+
image.rectangle! region.top_left, region.bottom_right, :color => color
|
83
|
+
end
|
84
|
+
|
85
|
+
image.save_image(ARGV[1])
|
86
|
+
window = GUI::Window.new('Face detection')
|
87
|
+
window.show(image)
|
88
|
+
GUI::wait_key
|
89
|
+
```
|
90
|
+
|
91
|
+
For more samples, see examples/*.rb
|
92
|
+
|
93
|
+
## LICENSE:
|
94
|
+
|
95
|
+
The BSD Liscense
|
96
|
+
|
97
|
+
see LICENSE.txt
|
98
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require "rubygems/ext"
|
4
|
+
require "rubygems/installer"
|
5
|
+
require 'hoe'
|
6
|
+
require 'rake/extensiontask'
|
7
|
+
require 'fileutils'
|
8
|
+
require './lib/opencv/psyched_yaml'
|
9
|
+
require 'yard'
|
10
|
+
require 'yard/rake/yardoc_task'
|
11
|
+
require './yard_extension'
|
12
|
+
|
13
|
+
SO_FILE = 'opencv.so'
|
14
|
+
|
15
|
+
Hoe.plugin :gemspec
|
16
|
+
|
17
|
+
hoespec = Hoe.spec 'ruby-opencv' do |s|
|
18
|
+
s.summary = 'OpenCV wrapper for Ruby'
|
19
|
+
s.description = 'ruby-opencv is a wrapper of OpenCV for Ruby. It helps you to write computer vision programs (e.g. detecting faces from pictures) with Ruby.'
|
20
|
+
s.licenses = ['The BSD License']
|
21
|
+
s.developer('lsxi', 'masakazu.yonekura@gmail.com')
|
22
|
+
s.developer('ser1zw', 'azariahsawtikes@gmail.com')
|
23
|
+
s.developer('pcting', 'pcting@gmail.com')
|
24
|
+
|
25
|
+
s.readme_file = 'README.md'
|
26
|
+
s.history_file = 'History.txt'
|
27
|
+
|
28
|
+
s.spec_extras = { :extensions => ['ext/opencv/extconf.rb'] }
|
29
|
+
|
30
|
+
s.test_globs = ['test/test_*.rb']
|
31
|
+
s.urls = ['https://github.com/ruby-opencv/ruby-opencv/']
|
32
|
+
|
33
|
+
s.extra_dev_deps << ['rake-compiler', '~> 0'] << ['hoe-gemspec', '~> 0']
|
34
|
+
|
35
|
+
Rake::ExtensionTask.new('opencv', spec) do |ext|
|
36
|
+
ext.lib_dir = 'lib'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
hoespec.spec.files.delete('.gemtest')
|
41
|
+
|
42
|
+
Rake::Task[:test].prerequisites << :compile
|
43
|
+
|
44
|
+
desc 'Create a pre-compiled gem'
|
45
|
+
task 'gem:precompile' => ['gem'] do
|
46
|
+
tmp_dir = Dir.mktmpdir('tmp', '.')
|
47
|
+
gemfile = Dir.glob("pkg/*.gem")[0]
|
48
|
+
target_dir = File.join(tmp_dir, File.basename(gemfile, '.gem'))
|
49
|
+
|
50
|
+
installer = Gem::Installer.new(gemfile)
|
51
|
+
installer.unpack(target_dir)
|
52
|
+
|
53
|
+
gemspec = installer.spec
|
54
|
+
extension = gemspec.extensions[0]
|
55
|
+
gemspec.extensions.clear
|
56
|
+
|
57
|
+
config = ENV['CONFIG'] ? YAML.load_file(ENV['CONFIG']) : {}
|
58
|
+
rubies = config['rubies'] || [Gem.ruby]
|
59
|
+
args = config['extopts'] || []
|
60
|
+
gemspec.platform = config['platform'] || Gem::Platform::CURRENT
|
61
|
+
|
62
|
+
multi = rubies.size > 1
|
63
|
+
rubies.each { |ruby|
|
64
|
+
lib_dir = 'lib'
|
65
|
+
if multi
|
66
|
+
major, minor, _ = `#{ruby} -e "print RUBY_VERSION"`.chomp.split('.')
|
67
|
+
lib_dir = File.join(lib_dir, [major, minor].join('.'))
|
68
|
+
end
|
69
|
+
|
70
|
+
make_cmd = (`#{ruby} -e "print RUBY_PLATFORM"` =~ /mswin/) ? 'nmake' : 'make'
|
71
|
+
Dir.chdir(target_dir) {
|
72
|
+
cmd = [ruby, extension, *args].join(' ')
|
73
|
+
results = []
|
74
|
+
Gem::Ext::ExtConfBuilder.run(cmd, results)
|
75
|
+
Gem::Ext::ExtConfBuilder.make('', results)
|
76
|
+
|
77
|
+
FileUtils.mkdir_p lib_dir
|
78
|
+
FileUtils.mv SO_FILE, lib_dir
|
79
|
+
sh "#{make_cmd} clean"
|
80
|
+
}
|
81
|
+
|
82
|
+
gemspec.files << File.join(lib_dir, SO_FILE)
|
83
|
+
}
|
84
|
+
|
85
|
+
Dir.chdir(target_dir) {
|
86
|
+
gemfile = Gem::Package.build(gemspec)
|
87
|
+
FileUtils.mv gemfile, File.dirname(__FILE__)
|
88
|
+
}
|
89
|
+
|
90
|
+
FileUtils.rm_rf tmp_dir
|
91
|
+
end
|
92
|
+
|
93
|
+
# yard
|
94
|
+
YARD::Rake::YardocTask.new do |t|
|
95
|
+
t.files = ['lib/**/*.rb', 'ext/**/*.cpp']
|
96
|
+
end
|
97
|
+
|
98
|
+
# vim: syntax=ruby
|
99
|
+
|
data/config.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Alpha blending sample with GUI
|
5
|
+
|
6
|
+
require 'opencv'
|
7
|
+
include OpenCV
|
8
|
+
|
9
|
+
img1 = IplImage.load('images/lenna.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
10
|
+
img2 = IplImage.load('images/tiffany.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
11
|
+
|
12
|
+
window = GUI::Window.new('Alpha blend')
|
13
|
+
max = 100.0
|
14
|
+
val = max / 2.0
|
15
|
+
window.set_trackbar("Alpha", max, val) { |v|
|
16
|
+
a = v.to_f / max
|
17
|
+
window.show CvMat.add_weighted(img1, a, img2, 1.0 - a, 0)
|
18
|
+
}
|
19
|
+
window.show CvMat.add_weighted(img1, val / max, img2, 1.0 - val / max, 0)
|
20
|
+
GUI::wait_key
|
21
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Detects contours in an image and
|
4
|
+
# their boundingboxes
|
5
|
+
#
|
6
|
+
require "opencv"
|
7
|
+
|
8
|
+
# Load image
|
9
|
+
cvmat = OpenCV::CvMat.load("rotated-boxes.jpg")
|
10
|
+
|
11
|
+
# The "canny" edge-detector does only work with grayscale images
|
12
|
+
# so to be sure, convert the image
|
13
|
+
# otherwise you will get an OpenCV::CvStsAssert exception.
|
14
|
+
cvmat = cvmat.BGR2GRAY
|
15
|
+
|
16
|
+
# Use the "canny" edge detection algorithm (http://en.wikipedia.org/wiki/Canny_edge_detector)
|
17
|
+
# Parameters are two colors that are then used to determine possible corners
|
18
|
+
canny = cvmat.canny(50, 150)
|
19
|
+
|
20
|
+
# Look for contours
|
21
|
+
# We want them to be returned as a flat list (CV_RETR_LIST) and simplified (CV_CHAIN_APPROX_SIMPLE)
|
22
|
+
# Both are the defaults but included here for clarity
|
23
|
+
contour = canny.find_contours(mode: OpenCV::CV_RETR_LIST, method: OpenCV::CV_CHAIN_APPROX_SIMPLE)
|
24
|
+
|
25
|
+
# The Canny Algorithm returns two matches for every contour (see O'Reilly: Learning OpenCV Page 235)
|
26
|
+
# We need only the external edges so we ignore holes.
|
27
|
+
# When there are no more contours, contours.h_next will return nil
|
28
|
+
while contour
|
29
|
+
# No "holes" please (aka. internal contours)
|
30
|
+
unless contour.hole?
|
31
|
+
|
32
|
+
puts '-' * 80
|
33
|
+
puts "BOUNDING RECT FOUND"
|
34
|
+
puts '-' * 80
|
35
|
+
|
36
|
+
# You can detect the "bounding rectangle" which is always oriented horizontally and vertically
|
37
|
+
box = contour.bounding_rect
|
38
|
+
puts "found external contour with bounding rectangle from #{box.top_left.x},#{box.top_left.y} to #{box.bottom_right.x},#{box.bottom_right.y}"
|
39
|
+
|
40
|
+
# The contour area can be computed:
|
41
|
+
puts "that contour encloses an area of #{contour.contour_area} square pixels"
|
42
|
+
|
43
|
+
# .. as can be the length of the contour
|
44
|
+
puts "that contour is #{contour.arc_length} pixels long "
|
45
|
+
|
46
|
+
# Draw that bounding rectangle
|
47
|
+
cvmat.rectangle! box.top_left, box.bottom_right, color: OpenCV::CvColor::Black
|
48
|
+
|
49
|
+
# You can also detect the "minimal rectangle" which has an angle, width, height and center coordinates
|
50
|
+
# and is not neccessarily horizonally or vertically aligned.
|
51
|
+
# The corner of the rectangle with the lowest y and x position is the anchor (see image here: http://bit.ly/lT1XvB)
|
52
|
+
# The zero angle position is always straight up.
|
53
|
+
# Positive angle values are clockwise and negative values counter clockwise (so -60 means 60 degree counter clockwise)
|
54
|
+
box = contour.min_area_rect2
|
55
|
+
puts "found minimal rectangle with its center at (#{box.center.x.round},#{box.center.y.round}), width of #{box.size.width.round}px, height of #{box.size.height.round} and an angle of #{box.angle.round} degree"
|
56
|
+
end
|
57
|
+
contour = contour.h_next
|
58
|
+
end
|
59
|
+
|
60
|
+
# And save the image
|
61
|
+
puts "\nSaving image with bounding rectangles"
|
62
|
+
cvmat.save_image("rotated-boxes-with-detected-bounding-rectangles.jpg")
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file shows the different retrieval modes for contour detection
|
4
|
+
#
|
5
|
+
require "opencv"
|
6
|
+
|
7
|
+
# Load image
|
8
|
+
# The structure of the image is "explained" in bitmap-contours-with-labels.png
|
9
|
+
cvmat = OpenCV::CvMat.load("bitmap-contours.png")
|
10
|
+
|
11
|
+
# "find_contours" does only operate on bitmap images (black/white)
|
12
|
+
mat = OpenCV::CvMat.new(cvmat.rows, cvmat.cols, :cv8u, 1)
|
13
|
+
(cvmat.rows * cvmat.cols).times do |i|
|
14
|
+
mat[i] = (cvmat[i][0] <= 128) ? OpenCV::CvScalar.new(0) : OpenCV::CvScalar.new(255)
|
15
|
+
end
|
16
|
+
|
17
|
+
# find_contours takes two parameters:
|
18
|
+
# 1. Retrieval mode (:mode, defines the structure of the contour sequence returned)
|
19
|
+
# - CV_RETR_LIST (default)
|
20
|
+
# - CV_RETR_EXTERNAL
|
21
|
+
# - CV_RETR_CCOMP
|
22
|
+
# - CV_RETR_TREE
|
23
|
+
# 2. Retrieval Method (:method, how the contours are approximated)
|
24
|
+
# - CV_CHAIN_CODE
|
25
|
+
# - CV_CHAIN_APPROX_NONE
|
26
|
+
# - CV_CHAIN_APPROX_SIMPLE (default)
|
27
|
+
# - CV_CHAIN_APPROX_TC89_L1
|
28
|
+
# - CV_CHAIN_APPROX_T89_KCOS
|
29
|
+
# - CV_LINK_RUNS
|
30
|
+
|
31
|
+
#
|
32
|
+
# The default: CV_RETR_LIST and CV_CHAIN_APPROX_SIMPLE
|
33
|
+
# This produces a flat list of contours that can be traversed with .h_next and .h_prev
|
34
|
+
#
|
35
|
+
puts "Detecting using CV_RETR_LIST and CV_CHAIN_APPROX_SIMPLE"
|
36
|
+
contour = mat.find_contours(mode: OpenCV::CV_RETR_LIST, method: OpenCV::CV_CHAIN_APPROX_SIMPLE)
|
37
|
+
cindex=1
|
38
|
+
|
39
|
+
while contour
|
40
|
+
puts "Contour ##{cindex} is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
41
|
+
contour = contour.h_next
|
42
|
+
cindex+=1
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# CV_RETR_EXTERNAL retrieves only the outer most non "hole" contour
|
47
|
+
#
|
48
|
+
puts '-'*80
|
49
|
+
puts "Detecting using CV_RETR_EXTERNAL and CV_CHAIN_APPROX_SIMPLE"
|
50
|
+
contour = mat.find_contours(mode: OpenCV::CV_RETR_EXTERNAL, method: OpenCV::CV_CHAIN_APPROX_SIMPLE)
|
51
|
+
cindex=1
|
52
|
+
|
53
|
+
while contour
|
54
|
+
puts "Contour ##{cindex} is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
55
|
+
contour = contour.h_next
|
56
|
+
cindex+=1
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# CV_RETR_CCOMP organizes the contours in a two level deep stack
|
61
|
+
# The first level holds the contours
|
62
|
+
# The second level contains the holes of the contours in level 1
|
63
|
+
#
|
64
|
+
# C00001 <-> C00000 <-> C000 <-> C0
|
65
|
+
# | |
|
66
|
+
# V V
|
67
|
+
# H0000 H00
|
68
|
+
#
|
69
|
+
puts '-'*80
|
70
|
+
puts "Detecting using CV_RETR_CCOMP and CV_CHAIN_APPROX_SIMPLE"
|
71
|
+
contour = mat.find_contours(mode: OpenCV::CV_RETR_CCOMP, method: OpenCV::CV_CHAIN_APPROX_SIMPLE)
|
72
|
+
|
73
|
+
# C00001
|
74
|
+
puts "Contour #1 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
75
|
+
contour = contour.h_next
|
76
|
+
|
77
|
+
# C00000
|
78
|
+
puts "Contour #2 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
79
|
+
contour = contour.h_next
|
80
|
+
|
81
|
+
# C000
|
82
|
+
puts "Contour #3 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
83
|
+
contour_down = contour.v_next
|
84
|
+
|
85
|
+
# H0000
|
86
|
+
puts "Contour #4 is #{contour_down.contour_area} px^2 (width: #{contour_down.bounding_rect.width}, height: #{contour_down.bounding_rect.height}, type: #{(contour_down.hole?)?"hole":"contour"})"
|
87
|
+
contour = contour.h_next
|
88
|
+
|
89
|
+
# C0
|
90
|
+
puts "Contour #5 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
91
|
+
contour_down = contour.v_next
|
92
|
+
|
93
|
+
# H00
|
94
|
+
puts "Contour #6 is #{contour_down.contour_area} px^2 (width: #{contour_down.bounding_rect.width}, height: #{contour_down.bounding_rect.height}, type: #{(contour_down.hole?)?"hole":"contour"})"
|
95
|
+
|
96
|
+
#
|
97
|
+
# CV_RETR_TREE manages the contours in a tree structure
|
98
|
+
# This reconstructs the complete hierarchy of contours and holes that the image displayed
|
99
|
+
#
|
100
|
+
# C0
|
101
|
+
# |
|
102
|
+
# V
|
103
|
+
# H00
|
104
|
+
# |
|
105
|
+
# V
|
106
|
+
# C000
|
107
|
+
# |
|
108
|
+
# V
|
109
|
+
# H0000-------+
|
110
|
+
# | |
|
111
|
+
# V V
|
112
|
+
# C00000 C00001
|
113
|
+
#
|
114
|
+
puts '-'*80
|
115
|
+
puts "Detecting using CV_RETR_TREE and CV_CHAIN_APPROX_SIMPLE"
|
116
|
+
contour = mat.find_contours(mode: OpenCV::CV_RETR_TREE, method: OpenCV::CV_CHAIN_APPROX_SIMPLE)
|
117
|
+
|
118
|
+
# C0
|
119
|
+
puts "Contour #1 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
120
|
+
contour = contour.v_next
|
121
|
+
|
122
|
+
# H00
|
123
|
+
puts "Contour #2 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
124
|
+
contour = contour.v_next
|
125
|
+
|
126
|
+
# C000
|
127
|
+
puts "Contour #3 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
128
|
+
contour = contour.v_next
|
129
|
+
|
130
|
+
# H0000
|
131
|
+
puts "Contour #4 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
132
|
+
contour = contour.v_next
|
133
|
+
|
134
|
+
# C00000
|
135
|
+
puts "Contour #5 is #{contour.contour_area} px^2 (width: #{contour.bounding_rect.width}, height: #{contour.bounding_rect.height}, type: #{(contour.hole?)?"hole":"contour"})"
|
136
|
+
contour_right = contour.h_next
|
137
|
+
|
138
|
+
# C00001
|
139
|
+
puts "Contour #6 is #{contour_right.contour_area} px^2 (width: #{contour_right.bounding_rect.width}, height: #{contour_right.bounding_rect.height}, type: #{(contour_right.hole?)?"hole":"contour"})"
|
Binary file
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# convexhull.rb
|
3
|
+
# Draw contours and convexity defect points to captured image
|
4
|
+
require "rubygems"
|
5
|
+
require "opencv"
|
6
|
+
include OpenCV
|
7
|
+
|
8
|
+
window = GUI::Window.new("convexhull")
|
9
|
+
capture = CvCapture::open
|
10
|
+
|
11
|
+
accuracy = 1
|
12
|
+
t = window.set_trackbar("accuracy", 10, 1) { |v|
|
13
|
+
accuracy = v
|
14
|
+
}
|
15
|
+
|
16
|
+
circle_options = { color: CvColor::Blue, line_type: :aa, thickness: -1 }
|
17
|
+
|
18
|
+
loop do
|
19
|
+
image = capture.query
|
20
|
+
|
21
|
+
# Calculate contours from a binary image
|
22
|
+
gray = image.BGR2GRAY
|
23
|
+
bin = gray.threshold(0x44, 0xFF, :binary)
|
24
|
+
contours = bin.find_contours
|
25
|
+
|
26
|
+
while contours
|
27
|
+
# Draw contours
|
28
|
+
poly = contours.approx(accuracy: accuracy)
|
29
|
+
begin
|
30
|
+
image.draw_contours!(poly, CvColor::Red, CvColor::Black, 2,
|
31
|
+
thickness: 2, line_type: :aa)
|
32
|
+
end while (poly = poly.h_next)
|
33
|
+
|
34
|
+
# Draw convexity defects
|
35
|
+
hull = contours.convex_hull2(true, false)
|
36
|
+
contours.convexity_defects(hull).each { |cd|
|
37
|
+
image.circle!(cd.start, 3, circle_options)
|
38
|
+
image.circle!(cd.depth_point, 3, circle_options)
|
39
|
+
image.circle!(cd.end, 3, circle_options)
|
40
|
+
}
|
41
|
+
contours = contours.h_next
|
42
|
+
end
|
43
|
+
|
44
|
+
window.show image
|
45
|
+
exit if GUI::wait_key(1)
|
46
|
+
end
|
47
|
+
|