ruby-opencv 0.0.8.pre
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.
- data/Gemfile +8 -0
- data/History.txt +5 -0
- data/License.txt +30 -0
- data/Manifest.txt +229 -0
- data/README.rdoc +149 -0
- data/Rakefile +32 -0
- data/examples/alpha_blend.rb +21 -0
- data/examples/box.png +0 -0
- data/examples/box_in_scene.png +0 -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-with-detected-bounding-rectangles.jpg +0 -0
- data/examples/contours/rotated-boxes.jpg +0 -0
- data/examples/convexhull.rb +47 -0
- data/examples/face_detect.rb +20 -0
- data/examples/find_obj.rb +169 -0
- data/examples/houghcircle.rb +22 -0
- data/examples/inpaint.png +0 -0
- data/examples/inpaint.rb +57 -0
- data/examples/lenna-rotated.jpg +0 -0
- data/examples/lenna.jpg +0 -0
- data/examples/match_kdtree.rb +88 -0
- data/examples/matching_to_many_images.rb +16 -0
- data/examples/matching_to_many_images/query.png +0 -0
- data/examples/matching_to_many_images/train/1.png +0 -0
- data/examples/matching_to_many_images/train/2.png +0 -0
- data/examples/matching_to_many_images/train/3.png +0 -0
- data/examples/matching_to_many_images/train/trainImages.txt +3 -0
- data/examples/paint.rb +70 -0
- data/examples/snake.rb +43 -0
- data/examples/stuff.jpg +0 -0
- data/examples/tiffany.jpg +0 -0
- data/ext/opencv/GPATH +0 -0
- data/ext/opencv/GSYMS +0 -0
- data/ext/opencv/curve.cpp +112 -0
- data/ext/opencv/curve.h +34 -0
- data/ext/opencv/cvavgcomp.cpp +67 -0
- data/ext/opencv/cvavgcomp.h +39 -0
- data/ext/opencv/cvbox2d.cpp +197 -0
- data/ext/opencv/cvbox2d.h +61 -0
- data/ext/opencv/cvcapture.cpp +499 -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 +116 -0
- data/ext/opencv/cvcircle32f.h +52 -0
- data/ext/opencv/cvcondensation.cpp +282 -0
- data/ext/opencv/cvcondensation.h +49 -0
- data/ext/opencv/cvconnectedcomp.cpp +143 -0
- data/ext/opencv/cvconnectedcomp.h +49 -0
- data/ext/opencv/cvcontour.cpp +296 -0
- data/ext/opencv/cvcontour.h +48 -0
- data/ext/opencv/cvcontourtree.cpp +91 -0
- data/ext/opencv/cvcontourtree.h +41 -0
- data/ext/opencv/cvconvexitydefect.cpp +103 -0
- data/ext/opencv/cvconvexitydefect.h +42 -0
- data/ext/opencv/cverror.cpp +159 -0
- data/ext/opencv/cverror.h +28 -0
- data/ext/opencv/cvfeaturetree.cpp +125 -0
- data/ext/opencv/cvfeaturetree.h +55 -0
- data/ext/opencv/cvfont.cpp +208 -0
- data/ext/opencv/cvfont.h +64 -0
- data/ext/opencv/cvhaarclassifiercascade.cpp +168 -0
- data/ext/opencv/cvhaarclassifiercascade.h +39 -0
- data/ext/opencv/cvhistogram.cpp +546 -0
- data/ext/opencv/cvhistogram.h +73 -0
- data/ext/opencv/cvhumoments.cpp +139 -0
- data/ext/opencv/cvhumoments.h +51 -0
- data/ext/opencv/cvline.cpp +154 -0
- data/ext/opencv/cvline.h +54 -0
- data/ext/opencv/cvmat.cpp +5848 -0
- data/ext/opencv/cvmat.h +284 -0
- data/ext/opencv/cvmatnd.cpp +44 -0
- data/ext/opencv/cvmatnd.h +28 -0
- data/ext/opencv/cvmemstorage.cpp +68 -0
- data/ext/opencv/cvmemstorage.h +53 -0
- data/ext/opencv/cvmoments.cpp +287 -0
- data/ext/opencv/cvmoments.h +75 -0
- data/ext/opencv/cvpoint.cpp +228 -0
- data/ext/opencv/cvpoint.h +64 -0
- data/ext/opencv/cvpoint2d32f.cpp +211 -0
- data/ext/opencv/cvpoint2d32f.h +63 -0
- data/ext/opencv/cvpoint3d32f.cpp +245 -0
- data/ext/opencv/cvpoint3d32f.h +66 -0
- data/ext/opencv/cvrect.cpp +333 -0
- data/ext/opencv/cvrect.h +79 -0
- data/ext/opencv/cvscalar.cpp +236 -0
- data/ext/opencv/cvscalar.h +71 -0
- data/ext/opencv/cvseq.cpp +599 -0
- data/ext/opencv/cvseq.h +74 -0
- data/ext/opencv/cvsize.cpp +221 -0
- data/ext/opencv/cvsize.h +65 -0
- data/ext/opencv/cvsize2d32f.cpp +209 -0
- data/ext/opencv/cvsize2d32f.h +64 -0
- data/ext/opencv/cvslice.cpp +120 -0
- data/ext/opencv/cvslice.h +61 -0
- data/ext/opencv/cvsparsemat.cpp +44 -0
- data/ext/opencv/cvsparsemat.h +28 -0
- data/ext/opencv/cvsurfparams.cpp +199 -0
- data/ext/opencv/cvsurfparams.h +58 -0
- data/ext/opencv/cvsurfpoint.cpp +223 -0
- data/ext/opencv/cvsurfpoint.h +52 -0
- data/ext/opencv/cvtermcriteria.cpp +192 -0
- data/ext/opencv/cvtermcriteria.h +71 -0
- data/ext/opencv/cvtwopoints.cpp +116 -0
- data/ext/opencv/cvtwopoints.h +51 -0
- data/ext/opencv/cvutils.cpp +194 -0
- data/ext/opencv/cvutils.h +29 -0
- data/ext/opencv/cvvideowriter.cpp +137 -0
- data/ext/opencv/cvvideowriter.h +43 -0
- data/ext/opencv/gui.cpp +68 -0
- data/ext/opencv/gui.h +30 -0
- data/ext/opencv/iplconvkernel.cpp +192 -0
- data/ext/opencv/iplconvkernel.h +71 -0
- data/ext/opencv/iplimage.cpp +644 -0
- data/ext/opencv/iplimage.h +73 -0
- data/ext/opencv/lib/opencv.rb +3 -0
- data/ext/opencv/lib/opencv/psyched_yaml.rb +22 -0
- data/ext/opencv/lib/opencv/version.rb +3 -0
- data/ext/opencv/mouseevent.cpp +181 -0
- data/ext/opencv/mouseevent.h +56 -0
- data/ext/opencv/opencv.cpp +722 -0
- data/ext/opencv/opencv.h +400 -0
- data/ext/opencv/pointset.cpp +274 -0
- data/ext/opencv/pointset.h +68 -0
- data/ext/opencv/trackbar.cpp +121 -0
- data/ext/opencv/trackbar.h +69 -0
- data/ext/opencv/window.cpp +357 -0
- data/ext/opencv/window.h +66 -0
- data/extconf.rb +75 -0
- data/images/CvMat_sobel.png +0 -0
- data/images/CvMat_sub_rect.png +0 -0
- data/images/CvSeq_relationmap.png +0 -0
- data/images/face_detect_from_lena.jpg +0 -0
- data/ruby-opencv.gemspec +43 -0
- data/test/helper.rb +166 -0
- data/test/log.txt +55 -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 +2947 -0
- data/test/test_cvmat_drawing.rb +349 -0
- data/test/test_cvmat_dxt.rb +150 -0
- data/test/test_cvmat_imageprocessing.rb +2025 -0
- data/test/test_cvmat_matching.rb +57 -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_iplconvkernel.rb +54 -0
- data/test/test_iplimage.rb +236 -0
- data/test/test_mouseevent.rb +17 -0
- data/test/test_opencv.rb +324 -0
- data/test/test_pointset.rb +126 -0
- data/test/test_preliminary.rb +130 -0
- data/test/test_trackbar.rb +47 -0
- data/test/test_window.rb +115 -0
- data/test/videowriter_result.avi +0 -0
- metadata +394 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8-unix -*-
|
3
|
+
|
4
|
+
# Alpha blending sample with GUI
|
5
|
+
|
6
|
+
require 'opencv'
|
7
|
+
include OpenCV
|
8
|
+
|
9
|
+
img1 = IplImage.load('lenna.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
10
|
+
img2 = IplImage.load('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
|
+
|
data/examples/box.png
ADDED
Binary file
|
Binary file
|
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
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# face_detect.rb
|
3
|
+
require "rubygems"
|
4
|
+
require "opencv"
|
5
|
+
|
6
|
+
include OpenCV
|
7
|
+
|
8
|
+
window = GUI::Window.new("face detect")
|
9
|
+
capture = CvCapture.open
|
10
|
+
detector = CvHaarClassifierCascade::load("./data/haarcascades/haarcascade_frontalface_alt.xml")
|
11
|
+
|
12
|
+
loop {
|
13
|
+
image = capture.query
|
14
|
+
detector.detect_objects(image).each { |rect|
|
15
|
+
image.rectangle! rect.top_left, rect.bottom_right, :color => CvColor::Red
|
16
|
+
}
|
17
|
+
window.show image
|
18
|
+
break if GUI::wait_key(100)
|
19
|
+
}
|
20
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- mode: ruby; coding: utf-8-unix -*-
|
3
|
+
|
4
|
+
# A Demo Ruby/OpenCV Implementation of SURF
|
5
|
+
# See https://code.ros.org/trac/opencv/browser/tags/2.3.1/opencv/samples/c/find_obj.cpp
|
6
|
+
require 'opencv'
|
7
|
+
require 'benchmark'
|
8
|
+
include OpenCV
|
9
|
+
|
10
|
+
def compare_surf_descriptors(d1, d2, best, length)
|
11
|
+
raise ArgumentError unless (length % 4) == 0
|
12
|
+
total_cost = 0
|
13
|
+
0.step(length - 1, 4) { |i|
|
14
|
+
t0 = d1[i] - d2[i]
|
15
|
+
t1 = d1[i + 1] - d2[i + 1]
|
16
|
+
t2 = d1[i + 2] - d2[i + 2]
|
17
|
+
t3 = d1[i + 3] - d2[i + 3]
|
18
|
+
total_cost += t0 * t0 + t1 * t1 + t2 * t2 + t3 * t3
|
19
|
+
break if total_cost > best
|
20
|
+
}
|
21
|
+
total_cost
|
22
|
+
end
|
23
|
+
|
24
|
+
def naive_nearest_neighbor(vec, laplacian, model_keypoints, model_descriptors)
|
25
|
+
length = model_descriptors[0].size
|
26
|
+
neighbor = nil
|
27
|
+
dist1 = 1e6
|
28
|
+
dist2 = 1e6
|
29
|
+
|
30
|
+
model_descriptors.size.times { |i|
|
31
|
+
kp = model_keypoints[i]
|
32
|
+
mvec = model_descriptors[i]
|
33
|
+
next if laplacian != kp.laplacian
|
34
|
+
|
35
|
+
d = compare_surf_descriptors(vec, mvec, dist2, length)
|
36
|
+
if d < dist1
|
37
|
+
dist2 = dist1
|
38
|
+
dist1 = d
|
39
|
+
neighbor = i
|
40
|
+
elsif d < dist2
|
41
|
+
dist2 = d
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
return (dist1 < 0.6 * dist2) ? neighbor : nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_pairs(object_keypoints, object_descriptors,
|
49
|
+
image_keypoints, image_descriptors)
|
50
|
+
ptpairs = []
|
51
|
+
object_descriptors.size.times { |i|
|
52
|
+
kp = object_keypoints[i]
|
53
|
+
descriptor = object_descriptors[i]
|
54
|
+
nearest_neighbor = naive_nearest_neighbor(descriptor, kp.laplacian, image_keypoints, image_descriptors)
|
55
|
+
unless nearest_neighbor.nil?
|
56
|
+
ptpairs << i
|
57
|
+
ptpairs << nearest_neighbor
|
58
|
+
end
|
59
|
+
}
|
60
|
+
ptpairs
|
61
|
+
end
|
62
|
+
|
63
|
+
def locate_planar_object(object_keypoints, object_descriptors,
|
64
|
+
image_keypoints, image_descriptors, src_corners)
|
65
|
+
ptpairs = find_pairs(object_keypoints, object_descriptors, image_keypoints, image_descriptors)
|
66
|
+
n = ptpairs.size / 2
|
67
|
+
return nil if n < 4
|
68
|
+
|
69
|
+
pt1 = []
|
70
|
+
pt2 = []
|
71
|
+
n.times { |i|
|
72
|
+
pt1 << object_keypoints[ptpairs[i * 2]].pt
|
73
|
+
pt2 << image_keypoints[ptpairs[i * 2 + 1]].pt
|
74
|
+
}
|
75
|
+
|
76
|
+
_pt1 = CvMat.new(1, n, CV_32F, 2)
|
77
|
+
_pt2 = CvMat.new(1, n, CV_32F, 2)
|
78
|
+
_pt1.set_data(pt1)
|
79
|
+
_pt2.set_data(pt2)
|
80
|
+
h = CvMat.find_homography(_pt1, _pt2, :ransac, 5)
|
81
|
+
|
82
|
+
dst_corners = []
|
83
|
+
4.times { |i|
|
84
|
+
x = src_corners[i].x
|
85
|
+
y = src_corners[i].y
|
86
|
+
z = 1.0 / (h[6][0] * x + h[7][0] * y + h[8][0])
|
87
|
+
x = (h[0][0] * x + h[1][0] * y + h[2][0]) * z
|
88
|
+
y = (h[3][0] * x + h[4][0] * y + h[5][0]) * z
|
89
|
+
dst_corners << CvPoint.new(x.to_i, y.to_i)
|
90
|
+
}
|
91
|
+
|
92
|
+
dst_corners
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
##### Main #####
|
97
|
+
puts 'This program demonstrated the use of the SURF Detector and Descriptor using'
|
98
|
+
puts 'brute force matching on planar objects.'
|
99
|
+
puts 'Usage:'
|
100
|
+
puts "ruby #{__FILE__} <object_filename> <scene_filename>, default is box.png and box_in_scene.png"
|
101
|
+
puts
|
102
|
+
|
103
|
+
object_filename = (ARGV.size == 2) ? ARGV[0] : 'box.png'
|
104
|
+
scene_filename = (ARGV.size == 2) ? ARGV[1] : 'box_in_scene.png'
|
105
|
+
|
106
|
+
object, image = nil, nil
|
107
|
+
begin
|
108
|
+
object = IplImage.load(object_filename, CV_LOAD_IMAGE_GRAYSCALE)
|
109
|
+
image = IplImage.load(scene_filename, CV_LOAD_IMAGE_GRAYSCALE)
|
110
|
+
rescue
|
111
|
+
puts "Can not load #{object_filename} and/or #{scene_filename}"
|
112
|
+
puts "Usage: ruby #{__FILE__} [<object_filename> <scene_filename>]"
|
113
|
+
exit
|
114
|
+
end
|
115
|
+
object_color = object.GRAY2BGR
|
116
|
+
|
117
|
+
param = CvSURFParams.new(1500)
|
118
|
+
|
119
|
+
object_keypoints, object_descriptors = nil, nil
|
120
|
+
image_keypoints, image_descriptors = nil, nil
|
121
|
+
tms = Benchmark.measure {
|
122
|
+
object_keypoints, object_descriptors = object.extract_surf(param)
|
123
|
+
puts "Object Descriptors: #{object_descriptors.size}"
|
124
|
+
|
125
|
+
image_keypoints, image_descriptors = image.extract_surf(param)
|
126
|
+
puts "Image Descriptors: #{image_descriptors.size}"
|
127
|
+
}
|
128
|
+
puts "Extraction time = #{tms.real * 1000} ms"
|
129
|
+
|
130
|
+
correspond = IplImage.new(image.width, object.height + image.height, CV_8U, 1);
|
131
|
+
correspond.set_roi(CvRect.new(0, 0, object.width, object.height))
|
132
|
+
object.copy(correspond)
|
133
|
+
correspond.set_roi(CvRect.new(0, object.height, image.width, image.height))
|
134
|
+
image.copy(correspond)
|
135
|
+
correspond.reset_roi
|
136
|
+
|
137
|
+
src_corners = [CvPoint.new(0, 0), CvPoint.new(object.width, 0),
|
138
|
+
CvPoint.new(object.width, object.height), CvPoint.new(0, object.height)]
|
139
|
+
dst_corners = locate_planar_object(object_keypoints, object_descriptors,
|
140
|
+
image_keypoints, image_descriptors, src_corners)
|
141
|
+
|
142
|
+
correspond = correspond.GRAY2BGR
|
143
|
+
if dst_corners
|
144
|
+
4.times { |i|
|
145
|
+
r1 = dst_corners[i % 4]
|
146
|
+
r2 = dst_corners[(i + 1) % 4]
|
147
|
+
correspond.line!(CvPoint.new(r1.x, r1.y + object.height), CvPoint.new(r2.x, r2.y + object.height),
|
148
|
+
:color => CvColor::Red, :thickness => 2, :line_type => :aa)
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
ptpairs = find_pairs(object_keypoints, object_descriptors, image_keypoints, image_descriptors)
|
153
|
+
|
154
|
+
0.step(ptpairs.size - 1, 2) { |i|
|
155
|
+
r1 = object_keypoints[ptpairs[i]]
|
156
|
+
r2 = image_keypoints[ptpairs[i + 1]]
|
157
|
+
correspond.line!(r1.pt, CvPoint.new(r2.pt.x, r2.pt.y + object.height),
|
158
|
+
:color => CvColor::Red, :line_type => :aa)
|
159
|
+
}
|
160
|
+
|
161
|
+
object_keypoints.each { |r|
|
162
|
+
radius = (r.size * 1.2 / 9.0 * 2).to_i
|
163
|
+
object_color.circle!(r.pt, radius, :color => CvColor::Red, :line_type => :aa)
|
164
|
+
}
|
165
|
+
|
166
|
+
GUI::Window.new('Object Correspond').show correspond
|
167
|
+
GUI::Window.new('Object').show object_color
|
168
|
+
GUI::wait_key
|
169
|
+
|