jf-ruby-opencv 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (241) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.yardopts +3 -0
  4. data/DEVELOPERS_NOTE.md +137 -0
  5. data/Gemfile +9 -0
  6. data/History.txt +5 -0
  7. data/License.txt +30 -0
  8. data/Manifest.txt +239 -0
  9. data/README.md +94 -0
  10. data/Rakefile +99 -0
  11. data/config.yml +7 -0
  12. data/examples/alpha_blend.rb +21 -0
  13. data/examples/contours/bitmap-contours-with-labels.png +0 -0
  14. data/examples/contours/bitmap-contours.png +0 -0
  15. data/examples/contours/bounding-box-detect-canny.rb +62 -0
  16. data/examples/contours/contour_retrieval_modes.rb +139 -0
  17. data/examples/contours/rotated-boxes.jpg +0 -0
  18. data/examples/convexhull.rb +47 -0
  19. data/examples/face_detect.rb +20 -0
  20. data/examples/facerec/create_csv.rb +43 -0
  21. data/examples/facerec/facerec_eigenfaces.rb +132 -0
  22. data/examples/facerec/facerec_fisherfaces.rb +131 -0
  23. data/examples/facerec/facerec_lbph.rb +116 -0
  24. data/examples/facerec/readme.md +111 -0
  25. data/examples/find_obj.rb +169 -0
  26. data/examples/houghcircle.rb +22 -0
  27. data/examples/images/box.png +0 -0
  28. data/examples/images/box_in_scene.png +0 -0
  29. data/examples/images/inpaint.png +0 -0
  30. data/examples/images/lena-256x256.jpg +0 -0
  31. data/examples/images/lena-eyes.jpg +0 -0
  32. data/examples/images/lenna-rotated.jpg +0 -0
  33. data/examples/images/lenna.jpg +0 -0
  34. data/examples/images/stuff.jpg +0 -0
  35. data/examples/images/tiffany.jpg +0 -0
  36. data/examples/inpaint.rb +57 -0
  37. data/examples/match_kdtree.rb +88 -0
  38. data/examples/match_template.rb +26 -0
  39. data/examples/paint.rb +70 -0
  40. data/examples/snake.rb +43 -0
  41. data/ext/opencv/algorithm.cpp +291 -0
  42. data/ext/opencv/algorithm.h +38 -0
  43. data/ext/opencv/curve.cpp +127 -0
  44. data/ext/opencv/curve.h +34 -0
  45. data/ext/opencv/cvavgcomp.cpp +64 -0
  46. data/ext/opencv/cvavgcomp.h +39 -0
  47. data/ext/opencv/cvbox2d.cpp +195 -0
  48. data/ext/opencv/cvbox2d.h +61 -0
  49. data/ext/opencv/cvcapture.cpp +633 -0
  50. data/ext/opencv/cvcapture.h +82 -0
  51. data/ext/opencv/cvchain.cpp +233 -0
  52. data/ext/opencv/cvchain.h +46 -0
  53. data/ext/opencv/cvcircle32f.cpp +126 -0
  54. data/ext/opencv/cvcircle32f.h +52 -0
  55. data/ext/opencv/cvconnectedcomp.cpp +156 -0
  56. data/ext/opencv/cvconnectedcomp.h +49 -0
  57. data/ext/opencv/cvcontour.cpp +384 -0
  58. data/ext/opencv/cvcontour.h +51 -0
  59. data/ext/opencv/cvcontourtree.cpp +96 -0
  60. data/ext/opencv/cvcontourtree.h +41 -0
  61. data/ext/opencv/cvconvexitydefect.cpp +92 -0
  62. data/ext/opencv/cvconvexitydefect.h +42 -0
  63. data/ext/opencv/cverror.cpp +115 -0
  64. data/ext/opencv/cverror.h +28 -0
  65. data/ext/opencv/cvfeaturetree.cpp +123 -0
  66. data/ext/opencv/cvfeaturetree.h +55 -0
  67. data/ext/opencv/cvfont.cpp +228 -0
  68. data/ext/opencv/cvfont.h +64 -0
  69. data/ext/opencv/cvhaarclassifiercascade.cpp +148 -0
  70. data/ext/opencv/cvhaarclassifiercascade.h +39 -0
  71. data/ext/opencv/cvhistogram.cpp +717 -0
  72. data/ext/opencv/cvhistogram.h +73 -0
  73. data/ext/opencv/cvhumoments.cpp +178 -0
  74. data/ext/opencv/cvhumoments.h +51 -0
  75. data/ext/opencv/cvline.cpp +159 -0
  76. data/ext/opencv/cvline.h +54 -0
  77. data/ext/opencv/cvmat.cpp +6086 -0
  78. data/ext/opencv/cvmat.h +290 -0
  79. data/ext/opencv/cvmemstorage.cpp +73 -0
  80. data/ext/opencv/cvmemstorage.h +50 -0
  81. data/ext/opencv/cvmoments.cpp +293 -0
  82. data/ext/opencv/cvmoments.h +75 -0
  83. data/ext/opencv/cvpoint.cpp +234 -0
  84. data/ext/opencv/cvpoint.h +64 -0
  85. data/ext/opencv/cvpoint2d32f.cpp +216 -0
  86. data/ext/opencv/cvpoint2d32f.h +63 -0
  87. data/ext/opencv/cvpoint3d32f.cpp +252 -0
  88. data/ext/opencv/cvpoint3d32f.h +66 -0
  89. data/ext/opencv/cvrect.cpp +338 -0
  90. data/ext/opencv/cvrect.h +79 -0
  91. data/ext/opencv/cvscalar.cpp +241 -0
  92. data/ext/opencv/cvscalar.h +71 -0
  93. data/ext/opencv/cvseq.cpp +663 -0
  94. data/ext/opencv/cvseq.h +75 -0
  95. data/ext/opencv/cvsize.cpp +227 -0
  96. data/ext/opencv/cvsize.h +65 -0
  97. data/ext/opencv/cvsize2d32f.cpp +215 -0
  98. data/ext/opencv/cvsize2d32f.h +64 -0
  99. data/ext/opencv/cvslice.cpp +126 -0
  100. data/ext/opencv/cvslice.h +61 -0
  101. data/ext/opencv/cvsurfparams.cpp +208 -0
  102. data/ext/opencv/cvsurfparams.h +58 -0
  103. data/ext/opencv/cvsurfpoint.cpp +246 -0
  104. data/ext/opencv/cvsurfpoint.h +52 -0
  105. data/ext/opencv/cvtermcriteria.cpp +198 -0
  106. data/ext/opencv/cvtermcriteria.h +71 -0
  107. data/ext/opencv/cvtwopoints.cpp +122 -0
  108. data/ext/opencv/cvtwopoints.h +51 -0
  109. data/ext/opencv/cvutils.cpp +192 -0
  110. data/ext/opencv/cvutils.h +30 -0
  111. data/ext/opencv/cvvideowriter.cpp +142 -0
  112. data/ext/opencv/cvvideowriter.h +43 -0
  113. data/ext/opencv/eigenfaces.cpp +75 -0
  114. data/ext/opencv/eigenfaces.h +30 -0
  115. data/ext/opencv/extconf.rb +77 -0
  116. data/ext/opencv/facerecognizer.cpp +219 -0
  117. data/ext/opencv/facerecognizer.h +46 -0
  118. data/ext/opencv/fisherfaces.cpp +75 -0
  119. data/ext/opencv/fisherfaces.h +30 -0
  120. data/ext/opencv/gui.cpp +71 -0
  121. data/ext/opencv/gui.h +30 -0
  122. data/ext/opencv/iplconvkernel.cpp +198 -0
  123. data/ext/opencv/iplconvkernel.h +71 -0
  124. data/ext/opencv/iplimage.cpp +651 -0
  125. data/ext/opencv/iplimage.h +73 -0
  126. data/ext/opencv/lbph.cpp +78 -0
  127. data/ext/opencv/lbph.h +30 -0
  128. data/ext/opencv/mouseevent.cpp +186 -0
  129. data/ext/opencv/mouseevent.h +56 -0
  130. data/ext/opencv/opencv.cpp +819 -0
  131. data/ext/opencv/opencv.h +408 -0
  132. data/ext/opencv/pointset.cpp +280 -0
  133. data/ext/opencv/pointset.h +68 -0
  134. data/ext/opencv/trackbar.cpp +127 -0
  135. data/ext/opencv/trackbar.h +69 -0
  136. data/ext/opencv/window.cpp +377 -0
  137. data/ext/opencv/window.h +66 -0
  138. data/images/CvMat_sobel.png +0 -0
  139. data/images/CvMat_sub_rect.png +0 -0
  140. data/images/CvSeq_relationmap.png +0 -0
  141. data/lib/opencv.rb +12 -0
  142. data/lib/opencv/psyched_yaml.rb +22 -0
  143. data/lib/opencv/version.rb +3 -0
  144. data/ruby-opencv.gemspec +44 -0
  145. data/test/eigenfaces_save.xml +7524 -0
  146. data/test/fisherfaces_save.xml +7530 -0
  147. data/test/helper.rb +167 -0
  148. data/test/lbph_save.xml +4304 -0
  149. data/test/runner.rb +30 -0
  150. data/test/samples/airplane.jpg +0 -0
  151. data/test/samples/baboon.jpg +0 -0
  152. data/test/samples/baboon200.jpg +0 -0
  153. data/test/samples/baboon200_rotated.jpg +0 -0
  154. data/test/samples/blank0.jpg +0 -0
  155. data/test/samples/blank1.jpg +0 -0
  156. data/test/samples/blank2.jpg +0 -0
  157. data/test/samples/blank3.jpg +0 -0
  158. data/test/samples/blank4.jpg +0 -0
  159. data/test/samples/blank5.jpg +0 -0
  160. data/test/samples/blank6.jpg +0 -0
  161. data/test/samples/blank7.jpg +0 -0
  162. data/test/samples/blank8.jpg +0 -0
  163. data/test/samples/blank9.jpg +0 -0
  164. data/test/samples/cat.jpg +0 -0
  165. data/test/samples/chessboard.jpg +0 -0
  166. data/test/samples/contours.jpg +0 -0
  167. data/test/samples/fruits.jpg +0 -0
  168. data/test/samples/haarcascade_frontalface_alt.xml.gz +0 -0
  169. data/test/samples/inpaint-mask.bmp +0 -0
  170. data/test/samples/lena-256x256.jpg +0 -0
  171. data/test/samples/lena-32x32.jpg +0 -0
  172. data/test/samples/lena-eyes.jpg +0 -0
  173. data/test/samples/lena-inpaint.jpg +0 -0
  174. data/test/samples/lena.jpg +0 -0
  175. data/test/samples/lines.jpg +0 -0
  176. data/test/samples/messy0.jpg +0 -0
  177. data/test/samples/messy1.jpg +0 -0
  178. data/test/samples/movie_sample.avi +0 -0
  179. data/test/samples/one_way_train_0000.jpg +0 -0
  180. data/test/samples/one_way_train_0001.jpg +0 -0
  181. data/test/samples/partially_blank0.jpg +0 -0
  182. data/test/samples/partially_blank1.jpg +0 -0
  183. data/test/samples/smooth0.jpg +0 -0
  184. data/test/samples/smooth1.jpg +0 -0
  185. data/test/samples/smooth2.jpg +0 -0
  186. data/test/samples/smooth3.jpg +0 -0
  187. data/test/samples/smooth4.jpg +0 -0
  188. data/test/samples/smooth5.jpg +0 -0
  189. data/test/samples/smooth6.jpg +0 -0
  190. data/test/samples/str-cv-rotated.jpg +0 -0
  191. data/test/samples/str-cv.jpg +0 -0
  192. data/test/samples/str-ov.jpg +0 -0
  193. data/test/samples/stuff.jpg +0 -0
  194. data/test/test_curve.rb +43 -0
  195. data/test/test_cvavgcomp.rb +24 -0
  196. data/test/test_cvbox2d.rb +76 -0
  197. data/test/test_cvcapture.rb +191 -0
  198. data/test/test_cvchain.rb +108 -0
  199. data/test/test_cvcircle32f.rb +41 -0
  200. data/test/test_cvconnectedcomp.rb +61 -0
  201. data/test/test_cvcontour.rb +171 -0
  202. data/test/test_cvcontourtree.rb +43 -0
  203. data/test/test_cverror.rb +50 -0
  204. data/test/test_cvfeaturetree.rb +65 -0
  205. data/test/test_cvfont.rb +58 -0
  206. data/test/test_cvhaarclassifiercascade.rb +63 -0
  207. data/test/test_cvhistogram.rb +271 -0
  208. data/test/test_cvhumoments.rb +83 -0
  209. data/test/test_cvline.rb +50 -0
  210. data/test/test_cvmat.rb +3036 -0
  211. data/test/test_cvmat_drawing.rb +349 -0
  212. data/test/test_cvmat_dxt.rb +150 -0
  213. data/test/test_cvmat_imageprocessing.rb +2085 -0
  214. data/test/test_cvmoments.rb +180 -0
  215. data/test/test_cvpoint.rb +75 -0
  216. data/test/test_cvpoint2d32f.rb +75 -0
  217. data/test/test_cvpoint3d32f.rb +93 -0
  218. data/test/test_cvrect.rb +144 -0
  219. data/test/test_cvscalar.rb +113 -0
  220. data/test/test_cvseq.rb +311 -0
  221. data/test/test_cvsize.rb +75 -0
  222. data/test/test_cvsize2d32f.rb +75 -0
  223. data/test/test_cvslice.rb +31 -0
  224. data/test/test_cvsurfparams.rb +57 -0
  225. data/test/test_cvsurfpoint.rb +66 -0
  226. data/test/test_cvtermcriteria.rb +56 -0
  227. data/test/test_cvtwopoints.rb +40 -0
  228. data/test/test_cvvideowriter.rb +58 -0
  229. data/test/test_eigenfaces.rb +93 -0
  230. data/test/test_fisherfaces.rb +93 -0
  231. data/test/test_iplconvkernel.rb +54 -0
  232. data/test/test_iplimage.rb +232 -0
  233. data/test/test_lbph.rb +166 -0
  234. data/test/test_mouseevent.rb +17 -0
  235. data/test/test_opencv.rb +360 -0
  236. data/test/test_pointset.rb +128 -0
  237. data/test/test_preliminary.rb +130 -0
  238. data/test/test_trackbar.rb +47 -0
  239. data/test/test_window.rb +115 -0
  240. data/yard_extension.rb +5 -0
  241. metadata +352 -0
@@ -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,43 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby; coding: utf-8 -*-
3
+
4
+ # This is a tiny script to help you creating a CSV file from a face
5
+ # database with a similar hierarchie:
6
+ #
7
+ # philipp@mango:~/facerec/data/at$ tree
8
+ # .
9
+ # |-- README
10
+ # |-- s1
11
+ # | |-- 1.pgm
12
+ # | |-- ...
13
+ # | |-- 10.pgm
14
+ # |-- s2
15
+ # | |-- 1.pgm
16
+ # | |-- ...
17
+ # | |-- 10.pgm
18
+ # ...
19
+ # |-- s40
20
+ # | |-- 1.pgm
21
+ # | |-- ...
22
+ # | |-- 10.pgm
23
+ #
24
+ # See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
25
+ #
26
+ if ARGV.size != 1
27
+ puts "usage: ruby #{__FILE__} <base_path>"
28
+ exit
29
+ end
30
+
31
+ BASE_PATH = ARGV[0]
32
+ SEPARATOR = ';'
33
+
34
+ label = 0
35
+ Dir.glob("#{BASE_PATH}/*").each { |dir|
36
+ if FileTest::directory? dir
37
+ Dir.glob("#{dir}/*") { |filename|
38
+ puts "#{filename}#{SEPARATOR}#{label}"
39
+ }
40
+ label += 1
41
+ end
42
+ }
43
+
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby; coding: utf-8 -*-
3
+
4
+ # Eigenfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_eigenfaces.cpp
5
+ # See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
6
+ require 'opencv'
7
+ include OpenCV
8
+
9
+ def norm_0_255(src)
10
+ dst = nil
11
+ case src.channel
12
+ when 1
13
+ dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC1)
14
+ when 2
15
+ dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC3)
16
+ else
17
+ dst = src.copy
18
+ end
19
+
20
+ dst
21
+ end
22
+
23
+ def read_csv(filename, sepalator = ';')
24
+ images = []
25
+ labels = []
26
+ open(filename, 'r') { |f|
27
+ f.each { |line|
28
+ path, label = line.chomp.split(sepalator)
29
+ images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
30
+ labels << label.to_i
31
+ }
32
+ }
33
+
34
+ [images, labels]
35
+ end
36
+
37
+ if ARGV.size < 1
38
+ puts "usage: ruby #{__FILE__} <csv.ext> <output_folder>"
39
+ exit 1
40
+ end
41
+ fn_csv = ARGV.shift
42
+ output_folder = ARGV.shift
43
+
44
+ images, labels = read_csv(fn_csv);
45
+
46
+ height = images[0].rows;
47
+
48
+ # The following lines simply get the last images from your dataset and remove it
49
+ # from the vector. This is done, so that the training data (which we learn the
50
+ # cv::FaceRecognizer on) and the test data we test the model with, do not overlap.
51
+ test_sample = images.pop
52
+ test_label = labels.pop
53
+
54
+ # The following lines create an Eigenfaces model for
55
+ # face recognition and train it with the images and
56
+ # labels read from the given CSV file.
57
+ # This here is a full PCA, if you just want to keep
58
+ # 10 principal components (read Eigenfaces), then call
59
+ # the factory method like this:
60
+ #
61
+ # EigenFaces.new(10)
62
+ #
63
+ # If you want to create a FaceRecognizer with a
64
+ # confidence threshold (e.g. 123.0), call it with:
65
+ #
66
+ # EigenFaces.new(10, 123.0)
67
+ #
68
+ # If you want to use _all_ Eigenfaces and have a threshold,
69
+ # then call the method like this:
70
+ #
71
+ # EigenFaces.new(0, 123.0)
72
+ #
73
+ model = EigenFaces.new
74
+ model.train(images, labels)
75
+
76
+ # The following line predicts the label of a given test image:
77
+ predicted_label, predicted_confidence = model.predict(test_sample)
78
+
79
+ puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
80
+
81
+ eigenvalues = model.get_mat('eigenvalues')
82
+ w = model.get_mat('eigenvectors');
83
+ mean = model.get_mat('mean')
84
+
85
+ if output_folder
86
+ norm_0_255(mean.reshape(1, images[0].rows)).save("#{output_folder}/mean.png")
87
+ else
88
+ w1 = GUI::Window.new('Predicted')
89
+ w2 = GUI::Window.new('Actual')
90
+ w3 = GUI::Window.new('mean')
91
+
92
+ w1.show images[predicted_label]
93
+ w2.show images[test_label]
94
+ w3.show norm_0_255(mean.reshape(1, images[0].rows))
95
+ end
96
+
97
+ # Display or save the Eigenfaces:
98
+ [w.cols, 10].min.times { |i|
99
+ puts "Eigenvalue ##{i} = #{eigenvalues[i][0]}"
100
+ ev = w.get_cols(i).clone()
101
+ grayscale = norm_0_255(ev.reshape(1, height))
102
+
103
+ # Show the image & apply a Jet colormap for better sensing.
104
+ cgrayscale = grayscale.apply_color_map(COLORMAP_JET)
105
+ if output_folder
106
+ norm_0_255(cgrayscale).save("#{output_folder}/eigenface_#{i}.png")
107
+ else
108
+ w4 = GUI::Window.new("eigenface_#{i}")
109
+ w4.show norm_0_255(cgrayscale)
110
+ end
111
+ }
112
+
113
+ [w.cols, 10].min.step([w.cols, 300].min, 15) { |num_components|
114
+ # slice the eigenvectors from the model
115
+ evs = w.get_cols(0..num_components)
116
+ projection = images[0].reshape(1, 1).subspace_project(evs, mean)
117
+ reconstruction = projection.subspace_reconstruct(evs, mean)
118
+
119
+ # Normalize the result:
120
+ reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows))
121
+
122
+ # Display or save:
123
+ if output_folder
124
+ norm_0_255(reconstruction).save("#{output_folder}/eigenface_reconstruction_#{num_components}.png")
125
+ else
126
+ w5 = GUI::Window.new("eigenface_reconstruction_#{num_components}")
127
+ w5.show norm_0_255(reconstruction)
128
+ end
129
+ }
130
+
131
+ GUI::wait_key unless output_folder
132
+
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby; coding: utf-8 -*-
3
+
4
+ # Fisherfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_fisherfaces.cpp
5
+ # See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
6
+ require 'opencv'
7
+ include OpenCV
8
+
9
+ def norm_0_255(src)
10
+ dst = nil
11
+ case src.channel
12
+ when 1
13
+ dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC1)
14
+ when 2
15
+ dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC3)
16
+ else
17
+ dst = src.copy
18
+ end
19
+
20
+ dst
21
+ end
22
+
23
+ def read_csv(filename, sepalator = ';')
24
+ images = []
25
+ labels = []
26
+ open(filename, 'r') { |f|
27
+ f.each { |line|
28
+ path, label = line.chomp.split(sepalator)
29
+ images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
30
+ labels << label.to_i
31
+ }
32
+ }
33
+
34
+ [images, labels]
35
+ end
36
+
37
+ if ARGV.size < 1
38
+ puts "usage: ruby #{__FILE__} <csv.ext> <output_folder>"
39
+ exit 1
40
+ end
41
+ fn_csv = ARGV.shift
42
+ output_folder = ARGV.shift
43
+
44
+ images, labels = read_csv(fn_csv);
45
+
46
+ height = images[0].rows;
47
+
48
+ # The following lines simply get the last images from your dataset and remove it
49
+ # from the vector. This is done, so that the training data (which we learn the
50
+ # cv::FaceRecognizer on) and the test data we test the model with, do not overlap.
51
+ test_sample = images.pop
52
+ test_label = labels.pop
53
+
54
+ # The following lines create an Fisherfaces model for
55
+ # face recognition and train it with the images and
56
+ # labels read from the given CSV file.
57
+ # If you just want to keep 10 Fisherfaces, then call
58
+ # the factory method like this:
59
+ #
60
+ # FisherFaces.new(10)
61
+ #
62
+ # However it is not useful to discard Fisherfaces! Please
63
+ # always try to use _all_ available Fisherfaces for
64
+ # classification.
65
+ #
66
+ # If you want to create a FaceRecognizer with a
67
+ # confidence threshold (e.g. 123.0) and use _all_
68
+ # Fisherfaces, then call it with:
69
+ #
70
+ # FisherFaces.new(0, 123.0);
71
+ #
72
+ model = FisherFaces.new
73
+ model.train(images, labels)
74
+
75
+ # The following line predicts the label of a given test image:
76
+ predicted_label, predicted_confidence = model.predict(test_sample)
77
+
78
+ puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
79
+
80
+ eigenvalues = model.get_mat('eigenvalues')
81
+ w = model.get_mat('eigenvectors');
82
+ mean = model.get_mat('mean')
83
+
84
+ if output_folder
85
+ norm_0_255(mean.reshape(1, images[0].rows)).save("#{output_folder}/mean.png")
86
+ else
87
+ w1 = GUI::Window.new('Predicted')
88
+ w2 = GUI::Window.new('Actual')
89
+ w3 = GUI::Window.new('mean')
90
+
91
+ w1.show images[predicted_label]
92
+ w2.show images[test_label]
93
+ w3.show norm_0_255(mean.reshape(1, images[0].rows))
94
+ end
95
+
96
+ # Display or save the first, at most 16 Fisherfaces
97
+ [w.cols, 16].min.times { |i|
98
+ puts "Eigenvalue ##{i} = #{eigenvalues[i][0]}"
99
+ ev = w.get_cols(i).clone()
100
+ grayscale = norm_0_255(ev.reshape(1, height))
101
+
102
+ # Show the image & apply a Bone colormap for better sensing.
103
+ cgrayscale = grayscale.apply_color_map(COLORMAP_BONE)
104
+ if output_folder
105
+ norm_0_255(cgrayscale).save("#{output_folder}/fisherface_#{i}.png")
106
+ else
107
+ w4 = GUI::Window.new("fisherface_#{i}")
108
+ w4.show norm_0_255(cgrayscale)
109
+ end
110
+ }
111
+
112
+ [w.cols, 16].min.times { |num_component|
113
+ # Slice the Fisherface from the model
114
+ ev = w.get_cols(num_component)
115
+ projection = images[0].reshape(1, 1).subspace_project(ev, mean)
116
+ reconstruction = projection.subspace_reconstruct(ev, mean)
117
+
118
+ # Normalize the result:
119
+ reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows))
120
+
121
+ # Display or save:
122
+ if output_folder
123
+ norm_0_255(reconstruction).save("#{output_folder}/fisherface_reconstruction_#{num_component}.png")
124
+ else
125
+ w5 = GUI::Window.new("fisherface_reconstruction_#{num_component}")
126
+ w5.show norm_0_255(reconstruction)
127
+ end
128
+ }
129
+
130
+ GUI::wait_key unless output_folder
131
+
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby; coding: utf-8 -*-
3
+
4
+ # LBPH sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_lbph.cpp
5
+ # See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
6
+ require 'opencv'
7
+ include OpenCV
8
+
9
+ def read_csv(filename, sepalator = ';')
10
+ images = []
11
+ labels = []
12
+ open(filename, 'r') { |f|
13
+ f.each { |line|
14
+ path, label = line.chomp.split(sepalator)
15
+ images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
16
+ labels << label.to_i
17
+ }
18
+ }
19
+
20
+ [images, labels]
21
+ end
22
+
23
+ # Check for valid command line arguments, print usage
24
+ # if no arguments were given.
25
+ if ARGV.size < 1
26
+ puts "usage: ruby #{__FILE__} <csv.ext>"
27
+ exit 1
28
+ end
29
+
30
+ # Get the path to your CSV.
31
+ fn_csv = ARGV.shift
32
+
33
+ # Read in the data. This can fail if no valid
34
+ # input filename is given.
35
+ images, labels = read_csv(fn_csv);
36
+
37
+ # Quit if there are not enough images for this demo.
38
+ raise 'This demo needs at least 2 images to work. Please add more images to your data set!' if images.size <= 1
39
+
40
+ # Get the height from the first image. We'll need this
41
+ # later in code to reshape the images to their original size:
42
+ height = images[0].rows;
43
+
44
+ # The following lines simply get the last images from
45
+ # your dataset and remove it from the vector. This is
46
+ # done, so that the training data (which we learn the
47
+ # cv::FaceRecognizer on) and the test data we test
48
+ # the model with, do not overlap.
49
+ test_sample = images.pop
50
+ test_label = labels.pop
51
+
52
+ # The following lines create an LBPH model for
53
+ # face recognition and train it with the images and
54
+ # labels read from the given CSV file.
55
+ #
56
+ # The LBPHFaceRecognizer uses Extended Local Binary Patterns
57
+ # (it's probably configurable with other operators at a later
58
+ # point), and has the following default values
59
+ #
60
+ # radius = 1
61
+ # neighbors = 8
62
+ # grid_x = 8
63
+ # grid_y = 8
64
+ #
65
+ # So if you want a LBPH FaceRecognizer using a radius of
66
+ # 2 and 16 neighbors, call the factory method with:
67
+ #
68
+ # LBPH.new(2, 16);
69
+ #
70
+ # And if you want a threshold (e.g. 123.0) call it with its default values:
71
+ #
72
+ # LBPH.new(1,8,8,8,123.0)
73
+ #
74
+ model = LBPH.new
75
+ model.train(images, labels)
76
+
77
+ # The following line predicts the label of a given test image:
78
+ predicted_label, predicted_confidence = model.predict(test_sample)
79
+
80
+ # To get the confidence of a prediction call the model with:
81
+ #
82
+ # predicted_label = -1;
83
+ # confidence = 0.0;
84
+ # model.predict(test_sample, predicted_label, confidence)
85
+ #
86
+ puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
87
+
88
+ # Sometimes you'll need to get/set internal model data,
89
+ # which isn't exposed by the public FaceRecognizer.
90
+ # Since each FaceRecognizer is derived from a Algorithm,
91
+ # you can query the data.
92
+ #
93
+ # First we'll use it to set the threshold of the FaceRecognizer
94
+ # to 0.0 without retraining the model. This can be useful if
95
+ # you are evaluating the model:
96
+ model.set_double('threshold', 0.0);
97
+
98
+ # Now the threshold of this model is set to 0.0. A prediction
99
+ # now returns -1, as it's impossible to have a distance below it
100
+ predicted_label, predicted_confidence = model.predict(test_sample)
101
+ puts "Predicted class = #{predicted_label}"
102
+
103
+ # Show some informations about the model, as there's no cool
104
+ # Model data to display as in Eigenfaces/Fisherfaces.
105
+ # Due to efficiency reasons the LBP images are not stored
106
+ # within the model:
107
+ puts 'Model Information:'
108
+ model_info = "\tLBPH(radius=#{model.get_int('radius')}, neighbors=#{model.get_int('neighbors')}, grid_x=#{model.get_int('grid_x')}, grid_y=#{model.get_int('grid_y')}, threshold=#{model.get_double('threshold')})"
109
+ puts model_info
110
+
111
+ # We could get the histograms for example:
112
+ histgrams = model.get_matvector('histograms');
113
+
114
+ # But should I really visualize it? Probably the length is interesting:
115
+ puts "Size of the histograms: #{histgrams[0].dims.reduce(&:*)}"
116
+
@@ -0,0 +1,111 @@
1
+ # Face recognition with ruby-opencv
2
+
3
+ This is a face recognition sample with ruby-opencv, which equivalent to the following OpenCV's tutorial.
4
+
5
+ [Face Recognition with OpenCV](http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html)
6
+
7
+
8
+ ## Running samples
9
+
10
+ ### 1. Get AT&T Facedatabase
11
+
12
+ Get AT&T Facedatabase from http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html and unzip it.
13
+
14
+ ```sh
15
+ $ wget http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip
16
+ $ unzip att_faces.zip
17
+ ```
18
+
19
+ ### 2. Prepare the data
20
+
21
+ Create a CSV file to run samples.
22
+
23
+ ```sh
24
+ $ ruby create_csv.rb att_faces > at.txt
25
+ ```
26
+
27
+ You will get a CSV file which contains lines composed of a filename followed by a ; followed by the label (as integer number).
28
+
29
+ ```sh
30
+ $ cat at.txt
31
+ att_faces/s34/2.pgm;0
32
+ att_faces/s34/3.pgm;0
33
+ att_faces/s34/8.pgm;0
34
+ att_faces/s34/4.pgm;0
35
+ att_faces/s34/5.pgm;0
36
+ att_faces/s34/10.pgm;0
37
+ att_faces/s34/9.pgm;0
38
+ att_faces/s34/7.pgm;0
39
+ att_faces/s34/6.pgm;0
40
+ att_faces/s34/1.pgm;0
41
+ ...
42
+ ```
43
+
44
+ ### 3. Run sample codes
45
+
46
+ #### Eigenfaces
47
+
48
+ ```sh
49
+ $ mkdir output-eigenfaces
50
+ $ ruby facerec_eigenfaces.rb at.txt output-eigenfaces
51
+ ```
52
+
53
+ You will get the predicted class, actual class and eignvalues shown in console.
54
+
55
+ ```sh
56
+ Predicted class: 39 / Actual class: 39
57
+ Eigenvalue #0 = 2823424.500638128
58
+ Eigenvalue #1 = 2062015.3818895558
59
+ Eigenvalue #2 = 1090171.0771557507
60
+ Eigenvalue #3 = 892019.3644237233
61
+ Eigenvalue #4 = 818537.7917991373
62
+ Eigenvalue #5 = 539058.2364753223
63
+ Eigenvalue #6 = 390359.3231975121
64
+ Eigenvalue #7 = 373809.5486713626
65
+ Eigenvalue #8 = 314658.94374918053
66
+ Eigenvalue #9 = 288764.63018440653
67
+ ```
68
+
69
+ The result images will be stored in **output-eigenfaces** .
70
+
71
+
72
+ #### Fisherfaces
73
+
74
+ ```sh
75
+ $ mkdir output-fisherfaces
76
+ $ ruby facerec_fisherfaces.rb at.txt output-fisherfaces
77
+ ```
78
+
79
+ You will get the predicted class, actual class and eignvalues like Eigenfaces sample.
80
+
81
+ The result images will be stored in **output-fisherfaces** .
82
+
83
+
84
+ #### Local Binary Patterns Histograms
85
+
86
+ ```sh
87
+ $ ruby facerec_lbph.rb at.txt
88
+ ```
89
+
90
+ You will get the predicted class, actual class, model information and size of the histgrams.
91
+
92
+ ```
93
+ Predicted class: 39 / Actual class: 39
94
+ Predicted class = -1
95
+ Model Information:
96
+ LBPH(radius=1, neighbors=8, grid_x=8, grid_y=8, threshold=0.0)
97
+ Size of the histograms: 16384
98
+ ```
99
+
100
+ ## Credits
101
+
102
+ ### The Database of Faces
103
+
104
+ The Database of Faces, formerly The ORL Database of Faces, contains a set of face images taken between April 1992 and April 1994. The database was used in the context of a face recognition project carried out in collaboration with the Speech, Vision and Robotics Group of the Cambridge University Engineering Department.
105
+
106
+ There are ten different images of each of 40 distinct subjects. For some subjects, the images were taken at different times, varying the lighting, facial expressions (open / closed eyes, smiling / not smiling) and facial details (glasses / no glasses). All the images were taken against a dark homogeneous background with the subjects in an upright, frontal position (with tolerance for some side movement).
107
+
108
+ The files are in PGM format. The size of each image is 92x112 pixels, with 256 grey levels per pixel. The images are organised in 40 directories (one for each subject), which have names of the form sX, where X indicates the subject number (between 1 and 40). In each of these directories, there are ten different images of that subject, which have names of the form Y.pgm, where Y is the image number for that subject (between 1 and 10).
109
+
110
+ A copy of the database can be retrieved from: http://www.cl.cam.ac.uk/research/dtg/attarchive/pub/data/att_faces.zip.
111
+