Merge branch 'develop'
40
Manifest.txt
|
@ -8,8 +8,6 @@ README.md
|
|||
Rakefile
|
||||
config.yml
|
||||
examples/alpha_blend.rb
|
||||
examples/box.png
|
||||
examples/box_in_scene.png
|
||||
examples/contours/bitmap-contours-with-labels.png
|
||||
examples/contours/bitmap-contours.png
|
||||
examples/contours/bounding-box-detect-canny.rb
|
||||
|
@ -17,14 +15,26 @@ examples/contours/contour_retrieval_modes.rb
|
|||
examples/contours/rotated-boxes.jpg
|
||||
examples/convexhull.rb
|
||||
examples/face_detect.rb
|
||||
examples/facerec/create_csv.rb
|
||||
examples/facerec/facerec_eigenfaces.rb
|
||||
examples/facerec/facerec_fisherfaces.rb
|
||||
examples/facerec/facerec_lbph.rb
|
||||
examples/facerec/readme.md
|
||||
examples/find_obj.rb
|
||||
examples/houghcircle.rb
|
||||
examples/inpaint.png
|
||||
examples/images/box.png
|
||||
examples/images/box_in_scene.png
|
||||
examples/images/inpaint.png
|
||||
examples/images/lena-256x256.jpg
|
||||
examples/images/lena-eyes.jpg
|
||||
examples/images/lenna-rotated.jpg
|
||||
examples/images/lenna.jpg
|
||||
examples/images/stuff.jpg
|
||||
examples/images/tiffany.jpg
|
||||
examples/inpaint.rb
|
||||
examples/lenna-rotated.jpg
|
||||
examples/lenna.jpg
|
||||
examples/match_kdtree.rb
|
||||
examples/matching_to_many_images.rb
|
||||
examples/match_template.rb
|
||||
examples/matching_to_many_images/matching_to_many_images.rb
|
||||
examples/matching_to_many_images/query.png
|
||||
examples/matching_to_many_images/train/1.png
|
||||
examples/matching_to_many_images/train/2.png
|
||||
|
@ -32,8 +42,8 @@ examples/matching_to_many_images/train/3.png
|
|||
examples/matching_to_many_images/train/trainImages.txt
|
||||
examples/paint.rb
|
||||
examples/snake.rb
|
||||
examples/stuff.jpg
|
||||
examples/tiffany.jpg
|
||||
ext/opencv/algorithm.cpp
|
||||
ext/opencv/algorithm.h
|
||||
ext/opencv/curve.cpp
|
||||
ext/opencv/curve.h
|
||||
ext/opencv/cvavgcomp.cpp
|
||||
|
@ -110,13 +120,21 @@ ext/opencv/cvutils.cpp
|
|||
ext/opencv/cvutils.h
|
||||
ext/opencv/cvvideowriter.cpp
|
||||
ext/opencv/cvvideowriter.h
|
||||
ext/opencv/eigenfaces.cpp
|
||||
ext/opencv/eigenfaces.h
|
||||
ext/opencv/extconf.rb
|
||||
ext/opencv/facerecognizer.cpp
|
||||
ext/opencv/facerecognizer.h
|
||||
ext/opencv/fisherfaces.cpp
|
||||
ext/opencv/fisherfaces.h
|
||||
ext/opencv/gui.cpp
|
||||
ext/opencv/gui.h
|
||||
ext/opencv/iplconvkernel.cpp
|
||||
ext/opencv/iplconvkernel.h
|
||||
ext/opencv/iplimage.cpp
|
||||
ext/opencv/iplimage.h
|
||||
ext/opencv/lbph.cpp
|
||||
ext/opencv/lbph.h
|
||||
ext/opencv/mouseevent.cpp
|
||||
ext/opencv/mouseevent.h
|
||||
ext/opencv/opencv.cpp
|
||||
|
@ -135,7 +153,10 @@ lib/opencv.rb
|
|||
lib/opencv/psyched_yaml.rb
|
||||
lib/opencv/version.rb
|
||||
ruby-opencv.gemspec
|
||||
test/eigenfaces_save.xml
|
||||
test/fisherfaces_save.xml
|
||||
test/helper.rb
|
||||
test/lbph_save.xml
|
||||
test/runner.rb
|
||||
test/samples/airplane.jpg
|
||||
test/samples/baboon.jpg
|
||||
|
@ -217,8 +238,11 @@ test/test_cvsurfpoint.rb
|
|||
test/test_cvtermcriteria.rb
|
||||
test/test_cvtwopoints.rb
|
||||
test/test_cvvideowriter.rb
|
||||
test/test_eigenfaces.rb
|
||||
test/test_fisherfaces.rb
|
||||
test/test_iplconvkernel.rb
|
||||
test/test_iplimage.rb
|
||||
test/test_lbph.rb
|
||||
test/test_mouseevent.rb
|
||||
test/test_opencv.rb
|
||||
test/test_pointset.rb
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
An OpenCV wrapper for Ruby.
|
||||
|
||||
* Web site: <https://github.com/ruby-opencv/ruby-opencv>
|
||||
* Ruby 1.9.3, 2.0.0 and OpenCV 2.4.6.1 are supported.
|
||||
* Ruby 1.9.3, 2.0.0 and OpenCV 2.4.7 are supported.
|
||||
|
||||
## Requirement
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
require 'opencv'
|
||||
include OpenCV
|
||||
|
||||
img1 = IplImage.load('lenna.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
||||
img2 = IplImage.load('tiffany.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
||||
img1 = IplImage.load('images/lenna.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
||||
img2 = IplImage.load('images/tiffany.jpg', CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)
|
||||
|
||||
window = GUI::Window.new('Alpha blend')
|
||||
max = 100.0
|
||||
|
|
43
examples/facerec/create_csv.rb
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8 -*-
|
||||
|
||||
# This is a tiny script to help you creating a CSV file from a face
|
||||
# database with a similar hierarchie:
|
||||
#
|
||||
# philipp@mango:~/facerec/data/at$ tree
|
||||
# .
|
||||
# |-- README
|
||||
# |-- s1
|
||||
# | |-- 1.pgm
|
||||
# | |-- ...
|
||||
# | |-- 10.pgm
|
||||
# |-- s2
|
||||
# | |-- 1.pgm
|
||||
# | |-- ...
|
||||
# | |-- 10.pgm
|
||||
# ...
|
||||
# |-- s40
|
||||
# | |-- 1.pgm
|
||||
# | |-- ...
|
||||
# | |-- 10.pgm
|
||||
#
|
||||
# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
|
||||
#
|
||||
if ARGV.size != 1
|
||||
puts "usage: ruby #{__FILE__} <base_path>"
|
||||
exit
|
||||
end
|
||||
|
||||
BASE_PATH = ARGV[0]
|
||||
SEPARATOR = ';'
|
||||
|
||||
label = 0
|
||||
Dir.glob("#{BASE_PATH}/*").each { |dir|
|
||||
if FileTest::directory? dir
|
||||
Dir.glob("#{dir}/*") { |filename|
|
||||
puts "#{filename}#{SEPARATOR}#{label}"
|
||||
}
|
||||
label += 1
|
||||
end
|
||||
}
|
||||
|
132
examples/facerec/facerec_eigenfaces.rb
Executable file
|
@ -0,0 +1,132 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8 -*-
|
||||
|
||||
# Eigenfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_eigenfaces.cpp
|
||||
# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
|
||||
require 'opencv'
|
||||
include OpenCV
|
||||
|
||||
def norm_0_255(src)
|
||||
dst = nil
|
||||
case src.channel
|
||||
when 1
|
||||
dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC1)
|
||||
when 2
|
||||
dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC3)
|
||||
else
|
||||
dst = src.copy
|
||||
end
|
||||
|
||||
dst
|
||||
end
|
||||
|
||||
def read_csv(filename, sepalator = ';')
|
||||
images = []
|
||||
labels = []
|
||||
open(filename, 'r') { |f|
|
||||
f.each { |line|
|
||||
path, label = line.chomp.split(sepalator)
|
||||
images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
labels << label.to_i
|
||||
}
|
||||
}
|
||||
|
||||
[images, labels]
|
||||
end
|
||||
|
||||
if ARGV.size < 1
|
||||
puts "usage: ruby #{__FILE__} <csv.ext> <output_folder>"
|
||||
exit 1
|
||||
end
|
||||
fn_csv = ARGV.shift
|
||||
output_folder = ARGV.shift
|
||||
|
||||
images, labels = read_csv(fn_csv);
|
||||
|
||||
height = images[0].rows;
|
||||
|
||||
# The following lines simply get the last images from your dataset and remove it
|
||||
# from the vector. This is done, so that the training data (which we learn the
|
||||
# cv::FaceRecognizer on) and the test data we test the model with, do not overlap.
|
||||
test_sample = images.pop
|
||||
test_label = labels.pop
|
||||
|
||||
# The following lines create an Eigenfaces model for
|
||||
# face recognition and train it with the images and
|
||||
# labels read from the given CSV file.
|
||||
# This here is a full PCA, if you just want to keep
|
||||
# 10 principal components (read Eigenfaces), then call
|
||||
# the factory method like this:
|
||||
#
|
||||
# EigenFaces.new(10)
|
||||
#
|
||||
# If you want to create a FaceRecognizer with a
|
||||
# confidence threshold (e.g. 123.0), call it with:
|
||||
#
|
||||
# EigenFaces.new(10, 123.0)
|
||||
#
|
||||
# If you want to use _all_ Eigenfaces and have a threshold,
|
||||
# then call the method like this:
|
||||
#
|
||||
# EigenFaces.new(0, 123.0)
|
||||
#
|
||||
model = EigenFaces.new
|
||||
model.train(images, labels)
|
||||
|
||||
# The following line predicts the label of a given test image:
|
||||
predicted_label, predicted_confidence = model.predict(test_sample)
|
||||
|
||||
puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
|
||||
|
||||
eigenvalues = model.get_mat('eigenvalues')
|
||||
w = model.get_mat('eigenvectors');
|
||||
mean = model.get_mat('mean')
|
||||
|
||||
if output_folder
|
||||
norm_0_255(mean.reshape(1, images[0].rows)).save("#{output_folder}/mean.png")
|
||||
else
|
||||
w1 = GUI::Window.new('Predicted')
|
||||
w2 = GUI::Window.new('Actual')
|
||||
w3 = GUI::Window.new('mean')
|
||||
|
||||
w1.show images[predicted_label]
|
||||
w2.show images[test_label]
|
||||
w3.show norm_0_255(mean.reshape(1, images[0].rows))
|
||||
end
|
||||
|
||||
# Display or save the Eigenfaces:
|
||||
[w.cols, 10].min.times { |i|
|
||||
puts "Eigenvalue ##{i} = #{eigenvalues[i][0]}"
|
||||
ev = w.get_cols(i).clone()
|
||||
grayscale = norm_0_255(ev.reshape(1, height))
|
||||
|
||||
# Show the image & apply a Jet colormap for better sensing.
|
||||
cgrayscale = grayscale.apply_color_map(COLORMAP_JET)
|
||||
if output_folder
|
||||
norm_0_255(cgrayscale).save("#{output_folder}/eigenface_#{i}.png")
|
||||
else
|
||||
w4 = GUI::Window.new("eigenface_#{i}")
|
||||
w4.show norm_0_255(cgrayscale)
|
||||
end
|
||||
}
|
||||
|
||||
[w.cols, 10].min.step([w.cols, 300].min, 15) { |num_components|
|
||||
# slice the eigenvectors from the model
|
||||
evs = w.get_cols(0..num_components)
|
||||
projection = images[0].reshape(1, 1).subspace_project(evs, mean)
|
||||
reconstruction = projection.subspace_reconstruct(evs, mean)
|
||||
|
||||
# Normalize the result:
|
||||
reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows))
|
||||
|
||||
# Display or save:
|
||||
if output_folder
|
||||
norm_0_255(reconstruction).save("#{output_folder}/eigenface_reconstruction_#{num_components}.png")
|
||||
else
|
||||
w5 = GUI::Window.new("eigenface_reconstruction_#{num_components}")
|
||||
w5.show norm_0_255(reconstruction)
|
||||
end
|
||||
}
|
||||
|
||||
GUI::wait_key unless output_folder
|
||||
|
131
examples/facerec/facerec_fisherfaces.rb
Executable file
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8 -*-
|
||||
|
||||
# Fisherfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_fisherfaces.cpp
|
||||
# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
|
||||
require 'opencv'
|
||||
include OpenCV
|
||||
|
||||
def norm_0_255(src)
|
||||
dst = nil
|
||||
case src.channel
|
||||
when 1
|
||||
dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC1)
|
||||
when 2
|
||||
dst = src.normalize(0, 255, CV_NORM_MINMAX, CV_8UC3)
|
||||
else
|
||||
dst = src.copy
|
||||
end
|
||||
|
||||
dst
|
||||
end
|
||||
|
||||
def read_csv(filename, sepalator = ';')
|
||||
images = []
|
||||
labels = []
|
||||
open(filename, 'r') { |f|
|
||||
f.each { |line|
|
||||
path, label = line.chomp.split(sepalator)
|
||||
images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
labels << label.to_i
|
||||
}
|
||||
}
|
||||
|
||||
[images, labels]
|
||||
end
|
||||
|
||||
if ARGV.size < 1
|
||||
puts "usage: ruby #{__FILE__} <csv.ext> <output_folder>"
|
||||
exit 1
|
||||
end
|
||||
fn_csv = ARGV.shift
|
||||
output_folder = ARGV.shift
|
||||
|
||||
images, labels = read_csv(fn_csv);
|
||||
|
||||
height = images[0].rows;
|
||||
|
||||
# The following lines simply get the last images from your dataset and remove it
|
||||
# from the vector. This is done, so that the training data (which we learn the
|
||||
# cv::FaceRecognizer on) and the test data we test the model with, do not overlap.
|
||||
test_sample = images.pop
|
||||
test_label = labels.pop
|
||||
|
||||
# The following lines create an Fisherfaces model for
|
||||
# face recognition and train it with the images and
|
||||
# labels read from the given CSV file.
|
||||
# If you just want to keep 10 Fisherfaces, then call
|
||||
# the factory method like this:
|
||||
#
|
||||
# FisherFaces.new(10)
|
||||
#
|
||||
# However it is not useful to discard Fisherfaces! Please
|
||||
# always try to use _all_ available Fisherfaces for
|
||||
# classification.
|
||||
#
|
||||
# If you want to create a FaceRecognizer with a
|
||||
# confidence threshold (e.g. 123.0) and use _all_
|
||||
# Fisherfaces, then call it with:
|
||||
#
|
||||
# FisherFaces.new(0, 123.0);
|
||||
#
|
||||
model = FisherFaces.new
|
||||
model.train(images, labels)
|
||||
|
||||
# The following line predicts the label of a given test image:
|
||||
predicted_label, predicted_confidence = model.predict(test_sample)
|
||||
|
||||
puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
|
||||
|
||||
eigenvalues = model.get_mat('eigenvalues')
|
||||
w = model.get_mat('eigenvectors');
|
||||
mean = model.get_mat('mean')
|
||||
|
||||
if output_folder
|
||||
norm_0_255(mean.reshape(1, images[0].rows)).save("#{output_folder}/mean.png")
|
||||
else
|
||||
w1 = GUI::Window.new('Predicted')
|
||||
w2 = GUI::Window.new('Actual')
|
||||
w3 = GUI::Window.new('mean')
|
||||
|
||||
w1.show images[predicted_label]
|
||||
w2.show images[test_label]
|
||||
w3.show norm_0_255(mean.reshape(1, images[0].rows))
|
||||
end
|
||||
|
||||
# Display or save the first, at most 16 Fisherfaces
|
||||
[w.cols, 16].min.times { |i|
|
||||
puts "Eigenvalue ##{i} = #{eigenvalues[i][0]}"
|
||||
ev = w.get_cols(i).clone()
|
||||
grayscale = norm_0_255(ev.reshape(1, height))
|
||||
|
||||
# Show the image & apply a Bone colormap for better sensing.
|
||||
cgrayscale = grayscale.apply_color_map(COLORMAP_BONE)
|
||||
if output_folder
|
||||
norm_0_255(cgrayscale).save("#{output_folder}/fisherface_#{i}.png")
|
||||
else
|
||||
w4 = GUI::Window.new("fisherface_#{i}")
|
||||
w4.show norm_0_255(cgrayscale)
|
||||
end
|
||||
}
|
||||
|
||||
[w.cols, 16].min.times { |num_component|
|
||||
# Slice the Fisherface from the model
|
||||
ev = w.get_cols(num_component)
|
||||
projection = images[0].reshape(1, 1).subspace_project(ev, mean)
|
||||
reconstruction = projection.subspace_reconstruct(ev, mean)
|
||||
|
||||
# Normalize the result:
|
||||
reconstruction = norm_0_255(reconstruction.reshape(1, images[0].rows))
|
||||
|
||||
# Display or save:
|
||||
if output_folder
|
||||
norm_0_255(reconstruction).save("#{output_folder}/fisherface_reconstruction_#{num_component}.png")
|
||||
else
|
||||
w5 = GUI::Window.new("fisherface_reconstruction_#{num_component}")
|
||||
w5.show norm_0_255(reconstruction)
|
||||
end
|
||||
}
|
||||
|
||||
GUI::wait_key unless output_folder
|
||||
|
116
examples/facerec/facerec_lbph.rb
Executable file
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8 -*-
|
||||
|
||||
# LBPH sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_lbph.cpp
|
||||
# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
|
||||
require 'opencv'
|
||||
include OpenCV
|
||||
|
||||
def read_csv(filename, sepalator = ';')
|
||||
images = []
|
||||
labels = []
|
||||
open(filename, 'r') { |f|
|
||||
f.each { |line|
|
||||
path, label = line.chomp.split(sepalator)
|
||||
images << CvMat.load(path, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
labels << label.to_i
|
||||
}
|
||||
}
|
||||
|
||||
[images, labels]
|
||||
end
|
||||
|
||||
# Check for valid command line arguments, print usage
|
||||
# if no arguments were given.
|
||||
if ARGV.size < 1
|
||||
puts "usage: ruby #{__FILE__} <csv.ext>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Get the path to your CSV.
|
||||
fn_csv = ARGV.shift
|
||||
|
||||
# Read in the data. This can fail if no valid
|
||||
# input filename is given.
|
||||
images, labels = read_csv(fn_csv);
|
||||
|
||||
# Quit if there are not enough images for this demo.
|
||||
raise 'This demo needs at least 2 images to work. Please add more images to your data set!' if images.size <= 1
|
||||
|
||||
# Get the height from the first image. We'll need this
|
||||
# later in code to reshape the images to their original size:
|
||||
height = images[0].rows;
|
||||
|
||||
# The following lines simply get the last images from
|
||||
# your dataset and remove it from the vector. This is
|
||||
# done, so that the training data (which we learn the
|
||||
# cv::FaceRecognizer on) and the test data we test
|
||||
# the model with, do not overlap.
|
||||
test_sample = images.pop
|
||||
test_label = labels.pop
|
||||
|
||||
# The following lines create an LBPH model for
|
||||
# face recognition and train it with the images and
|
||||
# labels read from the given CSV file.
|
||||
#
|
||||
# The LBPHFaceRecognizer uses Extended Local Binary Patterns
|
||||
# (it's probably configurable with other operators at a later
|
||||
# point), and has the following default values
|
||||
#
|
||||
# radius = 1
|
||||
# neighbors = 8
|
||||
# grid_x = 8
|
||||
# grid_y = 8
|
||||
#
|
||||
# So if you want a LBPH FaceRecognizer using a radius of
|
||||
# 2 and 16 neighbors, call the factory method with:
|
||||
#
|
||||
# LBPH.new(2, 16);
|
||||
#
|
||||
# And if you want a threshold (e.g. 123.0) call it with its default values:
|
||||
#
|
||||
# LBPH.new(1,8,8,8,123.0)
|
||||
#
|
||||
model = LBPH.new
|
||||
model.train(images, labels)
|
||||
|
||||
# The following line predicts the label of a given test image:
|
||||
predicted_label, predicted_confidence = model.predict(test_sample)
|
||||
|
||||
# To get the confidence of a prediction call the model with:
|
||||
#
|
||||
# predicted_label = -1;
|
||||
# confidence = 0.0;
|
||||
# model.predict(test_sample, predicted_label, confidence)
|
||||
#
|
||||
puts "Predicted class: #{predicted_label} / Actual class: #{test_label}"
|
||||
|
||||
# Sometimes you'll need to get/set internal model data,
|
||||
# which isn't exposed by the public FaceRecognizer.
|
||||
# Since each FaceRecognizer is derived from a Algorithm,
|
||||
# you can query the data.
|
||||
#
|
||||
# First we'll use it to set the threshold of the FaceRecognizer
|
||||
# to 0.0 without retraining the model. This can be useful if
|
||||
# you are evaluating the model:
|
||||
model.set_double('threshold', 0.0);
|
||||
|
||||
# Now the threshold of this model is set to 0.0. A prediction
|
||||
# now returns -1, as it's impossible to have a distance below it
|
||||
predicted_label = model.predict(test_sample)
|
||||
puts "Predicted class = #{predicted_label}"
|
||||
|
||||
# Show some informations about the model, as there's no cool
|
||||
# Model data to display as in Eigenfaces/Fisherfaces.
|
||||
# Due to efficiency reasons the LBP images are not stored
|
||||
# within the model:
|
||||
puts 'Model Information:'
|
||||
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')})"
|
||||
puts model_info
|
||||
|
||||
# We could get the histograms for example:
|
||||
histgrams = model.get_matvector('histograms');
|
||||
|
||||
# But should I really visualize it? Probably the length is interesting:
|
||||
puts "Size of the histograms: #{histgrams[0].dims.reduce(&:*)}"
|
||||
|
111
examples/facerec/readme.md
Normal file
|
@ -0,0 +1,111 @@
|
|||
# Face recognition with ruby-opencv
|
||||
|
||||
This is a face recognition sample with ruby-opencv, which equivalent to the following OpenCV's tutorial.
|
||||
|
||||
[Face Recognition with OpenCV](http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html)
|
||||
|
||||
|
||||
## Running samples
|
||||
|
||||
### 1. Get AT&T Facedatabase
|
||||
|
||||
Get AT&T Facedatabase from http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html and unzip it.
|
||||
|
||||
```sh
|
||||
$ wget http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip
|
||||
$ unzip att_faces.zip
|
||||
```
|
||||
|
||||
### 2. Prepare the data
|
||||
|
||||
Create a CSV file to run samples.
|
||||
|
||||
```sh
|
||||
$ ruby create_csv.rb att_faces > at.txt
|
||||
```
|
||||
|
||||
You will get a CSV file which contains lines composed of a filename followed by a ; followed by the label (as integer number).
|
||||
|
||||
```sh
|
||||
$ cat at.txt
|
||||
att_faces/s34/2.pgm;0
|
||||
att_faces/s34/3.pgm;0
|
||||
att_faces/s34/8.pgm;0
|
||||
att_faces/s34/4.pgm;0
|
||||
att_faces/s34/5.pgm;0
|
||||
att_faces/s34/10.pgm;0
|
||||
att_faces/s34/9.pgm;0
|
||||
att_faces/s34/7.pgm;0
|
||||
att_faces/s34/6.pgm;0
|
||||
att_faces/s34/1.pgm;0
|
||||
...
|
||||
```
|
||||
|
||||
### 3. Run sample codes
|
||||
|
||||
#### Eigenfaces
|
||||
|
||||
```sh
|
||||
$ mkdir output-eigenfaces
|
||||
$ ruby facerec_eigenfaces.rb at.txt output-eigenfaces
|
||||
```
|
||||
|
||||
You will get the predicted class, actual class and eignvalues shown in console.
|
||||
|
||||
```sh
|
||||
Predicted class: 39 / Actual class: 39
|
||||
Eigenvalue #0 = 2823424.500638128
|
||||
Eigenvalue #1 = 2062015.3818895558
|
||||
Eigenvalue #2 = 1090171.0771557507
|
||||
Eigenvalue #3 = 892019.3644237233
|
||||
Eigenvalue #4 = 818537.7917991373
|
||||
Eigenvalue #5 = 539058.2364753223
|
||||
Eigenvalue #6 = 390359.3231975121
|
||||
Eigenvalue #7 = 373809.5486713626
|
||||
Eigenvalue #8 = 314658.94374918053
|
||||
Eigenvalue #9 = 288764.63018440653
|
||||
```
|
||||
|
||||
The result images will be stored in **output-eigenfaces** .
|
||||
|
||||
|
||||
#### Fisherfaces
|
||||
|
||||
```sh
|
||||
$ mkdir output-fisherfaces
|
||||
$ ruby facerec_fisherfaces.rb at.txt output-fisherfaces
|
||||
```
|
||||
|
||||
You will get the predicted class, actual class and eignvalues like Eigenfaces sample.
|
||||
|
||||
The result images will be stored in **output-fisherfaces** .
|
||||
|
||||
|
||||
#### Local Binary Patterns Histograms
|
||||
|
||||
```sh
|
||||
$ ruby facerec_lbph.rb at.txt
|
||||
```
|
||||
|
||||
You will get the predicted class, actual class, model information and size of the histgrams.
|
||||
|
||||
```
|
||||
Predicted class: 39 / Actual class: 39
|
||||
Predicted class = -1
|
||||
Model Information:
|
||||
LBPH(radius=1, neighbors=8, grid_x=8, grid_y=8, threshold=0.0)
|
||||
Size of the histograms: 16384
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
### The Database of Faces
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
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).
|
||||
|
||||
A copy of the database can be retrieved from: http://www.cl.cam.ac.uk/research/dtg/attarchive/pub/data/att_faces.zip.
|
||||
|
|
@ -100,8 +100,8 @@ puts 'Usage:'
|
|||
puts "ruby #{__FILE__} <object_filename> <scene_filename>, default is box.png and box_in_scene.png"
|
||||
puts
|
||||
|
||||
object_filename = (ARGV.size == 2) ? ARGV[0] : 'box.png'
|
||||
scene_filename = (ARGV.size == 2) ? ARGV[1] : 'box_in_scene.png'
|
||||
object_filename = (ARGV.size == 2) ? ARGV[0] : 'images/box.png'
|
||||
scene_filename = (ARGV.size == 2) ? ARGV[1] : 'images/box_in_scene.png'
|
||||
|
||||
object, image = nil, nil
|
||||
begin
|
||||
|
|
|
@ -7,7 +7,7 @@ include OpenCV
|
|||
original_window = GUI::Window.new "original"
|
||||
hough_window = GUI::Window.new "hough circles"
|
||||
|
||||
image = IplImage::load "stuff.jpg"
|
||||
image = IplImage::load "images/stuff.jpg"
|
||||
gray = image.BGR2GRAY
|
||||
|
||||
result = image.clone
|
||||
|
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
BIN
examples/images/lena-256x256.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
examples/images/lena-eyes.jpg
Normal file
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
@ -20,7 +20,7 @@ owindow = GUI::Window.new('original')
|
|||
mwindow = GUI::Window.new('mask')
|
||||
iwindow = GUI::Window.new('inpaint')
|
||||
|
||||
image = IplImage::load('inpaint.png')
|
||||
image = IplImage::load('images/inpaint.png')
|
||||
noimage = image.zero
|
||||
b, g, r = image.split
|
||||
original_mask = r.threshold(0x00, 0xFF, CV_THRESH_BINARY_INV) & b.threshold(0x00, 0xFF, CV_THRESH_BINARY_INV)
|
||||
|
|
|
@ -11,8 +11,8 @@ USE_EXTENDED_DESCRIPTOR = true
|
|||
THRESHOLD = 1500
|
||||
DESCRIPTOR_SIZE = USE_EXTENDED_DESCRIPTOR ? 128 : 64
|
||||
|
||||
img1 = CvMat.load('lenna.jpg', CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img2 = CvMat.load('lenna-rotated.jpg', CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img1 = CvMat.load('images/lenna.jpg', CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img2 = CvMat.load('images/lenna-rotated.jpg', CV_LOAD_IMAGE_GRAYSCALE)
|
||||
|
||||
puts 'Extracting features from img1 using SURF...'
|
||||
param = CvSURFParams.new(THRESHOLD, USE_EXTENDED_DESCRIPTOR)
|
||||
|
|
|
@ -10,8 +10,8 @@ puts 'Usage:'
|
|||
puts "ruby #{__FILE__} <template_filename> <match_filename>"
|
||||
puts
|
||||
|
||||
template_filename = (ARGV.size == 2) ? ARGV[0] : File.expand_path(File.dirname(__FILE__) + '/../test/samples/lena-eyes.jpg')
|
||||
match_image_filename = (ARGV.size == 2) ? ARGV[1] : File.expand_path(File.dirname(__FILE__) + '/../test/samples/lena-inpaint.jpg')
|
||||
template_filename = (ARGV.size == 2) ? ARGV[0] : File.expand_path(File.dirname(__FILE__) + '/images/lena-eyes.jpg')
|
||||
match_image_filename = (ARGV.size == 2) ? ARGV[1] : File.expand_path(File.dirname(__FILE__) + '/images/lena-256x256.jpg')
|
||||
|
||||
template = CvMat.load(template_filename)
|
||||
match_image = CvMat.load(match_image_filename)
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'opencv'
|
|||
require 'benchmark'
|
||||
include OpenCV
|
||||
|
||||
data = File.join(File.dirname(__FILE__), 'matching_to_many_images')
|
||||
data = File.dirname(__FILE__)
|
||||
|
||||
query = IplImage.load File.join(data, 'query.png'), CV_LOAD_IMAGE_GRAYSCALE
|
||||
image_files = ['1.png', '2.png', '3.png'].map{|f| File.join(data, 'train', f)}
|
286
ext/opencv/algorithm.cpp
Normal file
|
@ -0,0 +1,286 @@
|
|||
/************************************************************
|
||||
|
||||
algorithm.cpp -
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "algorithm.h"
|
||||
/*
|
||||
* Document-class: OpenCV::Algorithm
|
||||
*
|
||||
*/
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_ALGORITHM
|
||||
|
||||
VALUE rb_klass;
|
||||
|
||||
VALUE
|
||||
rb_class()
|
||||
{
|
||||
return rb_klass;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_int(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
try {
|
||||
ALGORITHM(self)->setInt(StringValueCStr(parameter), NUM2INT(value));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_double(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
try {
|
||||
ALGORITHM(self)->setDouble(StringValueCStr(parameter), NUM2DBL(value));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_bool(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
try {
|
||||
bool val = TRUE_OR_FALSE(value) ? true : false;
|
||||
ALGORITHM(self)->setBool(StringValueCStr(parameter), val);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_string(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
Check_Type(value, T_STRING);
|
||||
try {
|
||||
ALGORITHM(self)->setString(StringValueCStr(parameter), StringValueCStr(value));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_mat(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
try {
|
||||
CvMat* val = CVMAT_WITH_CHECK(value);
|
||||
cv::Mat mat(val);
|
||||
ALGORITHM(self)->setMat(StringValueCStr(parameter), mat);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_matvector(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
Check_Type(value, T_ARRAY);
|
||||
try {
|
||||
long len = RARRAY_LEN(value);
|
||||
VALUE* value_ptr = RARRAY_PTR(value);
|
||||
std::vector<cv::Mat> mat_vector;
|
||||
for (int i = 0; i < len; i++) {
|
||||
CvMat* val = CVMAT_WITH_CHECK(value_ptr[i]);
|
||||
cv::Mat mat(val);
|
||||
mat_vector.push_back(mat);
|
||||
}
|
||||
ALGORITHM(self)->setMatVector(StringValueCStr(parameter), mat_vector);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_set_algorithm(VALUE self, VALUE parameter, VALUE value)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
try {
|
||||
ALGORITHM(self)->setAlgorithm(StringValueCStr(parameter), ALGORITHM(value));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
VALUE
|
||||
rb_get_int(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
int value = 0;
|
||||
try {
|
||||
value = ALGORITHM(self)->getInt(StringValueCStr(parameter));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return INT2NUM(value);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_get_double(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
double value = 0.0;
|
||||
try {
|
||||
value = ALGORITHM(self)->getDouble(StringValueCStr(parameter));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return DBL2NUM(value);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_get_bool(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
bool value = false;
|
||||
try {
|
||||
value = ALGORITHM(self)->getBool(StringValueCStr(parameter));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return value ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_get_string(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
std::string value = "";
|
||||
try {
|
||||
value = ALGORITHM(self)->getString(StringValueCStr(parameter));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return rb_str_new_cstr(value.c_str());
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_get_mat(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
VALUE mat = Qnil;
|
||||
try {
|
||||
cv::Mat value = ALGORITHM(self)->getMat(StringValueCStr(parameter));
|
||||
cv::Size size = value.size();
|
||||
mat = cCvMat::new_object(size.height, size.width, value.type());
|
||||
cv::Mat dst(CVMAT(mat));
|
||||
value.copyTo(dst);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_get_matvector(VALUE self, VALUE parameter)
|
||||
{
|
||||
Check_Type(parameter, T_STRING);
|
||||
VALUE array = Qnil;
|
||||
try {
|
||||
std::vector<cv::Mat> value = ALGORITHM(self)->getMatVector(StringValueCStr(parameter));
|
||||
int len = value.size();
|
||||
array = rb_ary_new2(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
cv::Mat m = value[i];
|
||||
cv::Size size = m.size();
|
||||
VALUE mat = cCvMat::new_object(size.height, size.width, m.type());
|
||||
cv::Mat dst(CVMAT(mat));
|
||||
m.copyTo(dst);
|
||||
rb_ary_store(array, i, mat);
|
||||
}
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_name(VALUE self)
|
||||
{
|
||||
VALUE name = Qnil;
|
||||
try {
|
||||
name = rb_str_new_cstr(ALGORITHM(self)->name().c_str());
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
define_ruby_class()
|
||||
{
|
||||
if (rb_klass)
|
||||
return;
|
||||
/*
|
||||
* opencv = rb_define_module("OpenCV");
|
||||
*
|
||||
* note: this comment is used by rdoc.
|
||||
*/
|
||||
VALUE opencv = rb_module_opencv();
|
||||
rb_klass = rb_define_class_under(opencv, "Algorithm", rb_cObject);
|
||||
rb_define_method(rb_klass, "set_int", RUBY_METHOD_FUNC(rb_set_int), 2);
|
||||
rb_define_method(rb_klass, "set_double", RUBY_METHOD_FUNC(rb_set_double), 2);
|
||||
rb_define_method(rb_klass, "set_bool", RUBY_METHOD_FUNC(rb_set_bool), 2);
|
||||
rb_define_method(rb_klass, "set_string", RUBY_METHOD_FUNC(rb_set_string), 2);
|
||||
rb_define_method(rb_klass, "set_mat", RUBY_METHOD_FUNC(rb_set_mat), 2);
|
||||
rb_define_method(rb_klass, "set_matvector", RUBY_METHOD_FUNC(rb_set_matvector), 2);
|
||||
rb_define_method(rb_klass, "set_algorithm", RUBY_METHOD_FUNC(rb_set_algorithm), 2);
|
||||
|
||||
rb_define_method(rb_klass, "get_int", RUBY_METHOD_FUNC(rb_get_int), 1);
|
||||
rb_define_method(rb_klass, "get_double", RUBY_METHOD_FUNC(rb_get_double), 1);
|
||||
rb_define_method(rb_klass, "get_bool", RUBY_METHOD_FUNC(rb_get_bool), 1);
|
||||
rb_define_method(rb_klass, "get_string", RUBY_METHOD_FUNC(rb_get_string), 1);
|
||||
rb_define_method(rb_klass, "get_mat", RUBY_METHOD_FUNC(rb_get_mat), 1);
|
||||
rb_define_method(rb_klass, "get_matvector", RUBY_METHOD_FUNC(rb_get_matvector), 1);
|
||||
|
||||
rb_define_method(rb_klass, "name", RUBY_METHOD_FUNC(rb_name), 0);
|
||||
}
|
||||
|
||||
__NAMESPACE_END_ALGORITM
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
38
ext/opencv/algorithm.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/************************************************************
|
||||
|
||||
algorithm.h
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#ifndef RUBY_OPENCV_ALGORITHM_H
|
||||
#define RUBY_OPENCV_ALGORITHM_H
|
||||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_ALGORITHM namespace cAlgorithm {
|
||||
#define __NAMESPACE_END_ALGORITM }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_ALGORITHM
|
||||
|
||||
VALUE rb_class();
|
||||
|
||||
void define_ruby_class();
|
||||
|
||||
__NAMESPACE_END_ALGORITM
|
||||
|
||||
inline cv::Algorithm*
|
||||
ALGORITHM(VALUE object)
|
||||
{
|
||||
cv::Algorithm *ptr;
|
||||
Data_Get_Struct(object, cv::Algorithm, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
||||
#endif // RUBY_OPENCV_ALGORITHM_H
|
||||
|
|
@ -254,7 +254,7 @@ void define_ruby_class()
|
|||
rb_define_method(rb_klass, "range", RUBY_METHOD_FUNC(rb_range), 2);
|
||||
rb_define_method(rb_klass, "range!", RUBY_METHOD_FUNC(rb_range_bang), 2);
|
||||
|
||||
rb_define_method(rb_klass, "reshape", RUBY_METHOD_FUNC(rb_reshape), 1);
|
||||
rb_define_method(rb_klass, "reshape", RUBY_METHOD_FUNC(rb_reshape), -1);
|
||||
rb_define_method(rb_klass, "repeat", RUBY_METHOD_FUNC(rb_repeat), 1);
|
||||
rb_define_method(rb_klass, "flip", RUBY_METHOD_FUNC(rb_flip), -1);
|
||||
rb_define_method(rb_klass, "flip!", RUBY_METHOD_FUNC(rb_flip_bang), -1);
|
||||
|
@ -392,6 +392,7 @@ void define_ruby_class()
|
|||
rb_define_method(rb_klass, "inpaint", RUBY_METHOD_FUNC(rb_inpaint), 3);
|
||||
|
||||
rb_define_method(rb_klass, "equalize_hist", RUBY_METHOD_FUNC(rb_equalize_hist), 0);
|
||||
rb_define_method(rb_klass, "apply_color_map", RUBY_METHOD_FUNC(rb_apply_color_map), 1);
|
||||
rb_define_method(rb_klass, "match_template", RUBY_METHOD_FUNC(rb_match_template), -1);
|
||||
rb_define_method(rb_klass, "match_shapes", RUBY_METHOD_FUNC(rb_match_shapes), -1);
|
||||
rb_define_method(rb_klass, "match_descriptors", RUBY_METHOD_FUNC(rb_match_descriptors), -1);
|
||||
|
@ -411,6 +412,9 @@ void define_ruby_class()
|
|||
|
||||
rb_define_method(rb_klass, "extract_surf", RUBY_METHOD_FUNC(rb_extract_surf), -1);
|
||||
|
||||
rb_define_method(rb_klass, "subspace_project", RUBY_METHOD_FUNC(rb_subspace_project), 2);
|
||||
rb_define_method(rb_klass, "subspace_reconstruct", RUBY_METHOD_FUNC(rb_subspace_reconstruct), 2);
|
||||
|
||||
rb_define_method(rb_klass, "save_image", RUBY_METHOD_FUNC(rb_save_image), -1);
|
||||
rb_define_alias(rb_klass, "save", "save_image");
|
||||
|
||||
|
@ -1598,25 +1602,22 @@ rb_range_bang(VALUE self, VALUE start, VALUE end)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* reshape(<i>[:rows => num][, :channel => cn]</i>) -> cvmat(refer self)
|
||||
* reshape(cn, rows=0) -> cvmat(refer self)
|
||||
*
|
||||
* Change shape of matrix/image without copying data.
|
||||
*
|
||||
* e.g.
|
||||
* mat = CvMat.new(3, 3, CV_8U, 3) #=> 3x3 3-channel matrix
|
||||
* vec = mat.reshape(:rows => 1) #=> 1x9 3-channel matrix
|
||||
* ch1 = mat.reshape(:channel => 1) #=> 9x9 1-channel matrix
|
||||
* Parameter:
|
||||
* * cn - New number of channels. If the parameter is 0, the number of channels remains the same.
|
||||
* * rows - New number of rows. If the parameter is 0, the number of rows remains the same.
|
||||
*/
|
||||
VALUE
|
||||
rb_reshape(VALUE self, VALUE hash)
|
||||
rb_reshape(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
Check_Type(hash, T_HASH);
|
||||
VALUE channel = LOOKUP_HASH(hash, "channel");
|
||||
VALUE rows = LOOKUP_HASH(hash, "rows");
|
||||
VALUE cn, rows;
|
||||
CvMat *mat = NULL;
|
||||
rb_scan_args(argc, argv, "11", &cn, &rows);
|
||||
try {
|
||||
mat = cvReshape(CVARR(self), RB_CVALLOC(CvMat), NIL_P(channel) ? 0 : NUM2INT(channel),
|
||||
NIL_P(rows) ? 0 : NUM2INT(rows));
|
||||
mat = cvReshape(CVARR(self), RB_CVALLOC(CvMat), NUM2INT(cn), IF_INT(rows, 0));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
if (mat != NULL)
|
||||
|
@ -2378,38 +2379,50 @@ rb_abs_diff(VALUE self, VALUE val)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* normalize(...) -> cvmat
|
||||
* normalize(alpha=1, beta=0, norm_type=NORM_L2, dtype=-1, mask=nil) -> cvmat
|
||||
*
|
||||
* Normalizes the norm or value range of an array
|
||||
* Normalizes the norm or value range of an array.
|
||||
*
|
||||
* Parameters:
|
||||
* * alpha - norm value to normalize to or the lower range boundary in case of the range normalization.
|
||||
* * beta - upper range boundary in case of the range normalization; it is not used for the norm normalization.
|
||||
* * norm_type - normalization type.
|
||||
* * dtype - when negative, the output array has the same type as src; otherwise, it has the same number of channels as src and the depth
|
||||
* * mask - optional operation mask.
|
||||
*/
|
||||
VALUE
|
||||
rb_normalize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE alphaVal, betaVal, normTypeVal, maskVal;
|
||||
rb_scan_args(argc, argv, "04", &alphaVal, &betaVal, &normTypeVal, &maskVal);
|
||||
|
||||
const double alpha = alphaVal != Qnil ? NUM2DBL(alphaVal) : 1.0;
|
||||
const double beta = betaVal != Qnil ? NUM2DBL(betaVal) : 0.0;
|
||||
const int normType = normTypeVal != Qnil ? NUM2INT(normTypeVal) : cv::NORM_L2;
|
||||
|
||||
VALUE dest = new_mat_kind_object(cvGetSize(CVARR(self)), self);
|
||||
VALUE alpha_val, beta_val, norm_type_val, dtype_val, mask_val;
|
||||
rb_scan_args(argc, argv, "05", &alpha_val, &beta_val, &norm_type_val, &dtype_val, &mask_val);
|
||||
|
||||
double alpha = NIL_P(alpha_val) ? 1.0 : NUM2DBL(alpha_val);
|
||||
double beta = NIL_P(beta_val) ? 0.0 : NUM2DBL(beta_val);
|
||||
int norm_type = NIL_P(norm_type_val) ? cv::NORM_L2 : NUM2INT(norm_type_val);
|
||||
int dtype = NIL_P(dtype_val) ? -1 : NUM2INT(dtype_val);
|
||||
VALUE dst;
|
||||
|
||||
try {
|
||||
const cv::Mat selfMat(CVMAT(self));
|
||||
cv::Mat destMat(CVMAT(dest));
|
||||
|
||||
if (NIL_P(maskVal)) {
|
||||
cv::normalize(selfMat, destMat, alpha, beta, normType);
|
||||
cv::Mat self_mat(CVMAT(self));
|
||||
cv::Mat dst_mat;
|
||||
|
||||
if (NIL_P(mask_val)) {
|
||||
cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype);
|
||||
}
|
||||
else {
|
||||
cv::Mat maskMat(MASK(maskVal));
|
||||
cv::normalize(selfMat, destMat, alpha, beta, normType, -1, maskMat);
|
||||
cv::Mat mask(MASK(mask_val));
|
||||
cv::normalize(self_mat, dst_mat, alpha, beta, norm_type, dtype, mask);
|
||||
}
|
||||
|
||||
} catch (cv::Exception& e) {
|
||||
dst = new_mat_kind_object(cvGetSize(CVARR(self)), self, dst_mat.depth(), dst_mat.channels());
|
||||
|
||||
CvMat tmp = dst_mat;
|
||||
cvCopy(&tmp, CVMAT(dst));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return dest;
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5198,6 +5211,35 @@ rb_equalize_hist(VALUE self)
|
|||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* apply_color_map(colormap) -> cvmat
|
||||
*
|
||||
* Applies a GNU Octave/MATLAB equivalent colormap on a given image.
|
||||
*
|
||||
* Parameters:
|
||||
* colormap - The colormap to apply.
|
||||
*/
|
||||
VALUE
|
||||
rb_apply_color_map(VALUE self, VALUE colormap)
|
||||
{
|
||||
VALUE dst;
|
||||
try {
|
||||
cv::Mat dst_mat;
|
||||
cv::Mat self_mat(CVMAT(self));
|
||||
|
||||
cv::applyColorMap(self_mat, dst_mat, NUM2INT(colormap));
|
||||
CvMat tmp = dst_mat;
|
||||
dst = new_object(tmp.rows, tmp.cols, tmp.type);
|
||||
cvCopy(&tmp, CVMAT(dst));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* match_template(<i>template[,method = :sqdiff]</i>) -> cvmat(result)
|
||||
|
@ -5800,6 +5842,55 @@ rb_extract_surf(int argc, VALUE *argv, VALUE self)
|
|||
return rb_assoc_new(_keypoints, _descriptors);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* subspace_project(w, mean) -> cvmat
|
||||
*/
|
||||
VALUE
|
||||
rb_subspace_project(VALUE self, VALUE w, VALUE mean)
|
||||
{
|
||||
VALUE projection;
|
||||
try {
|
||||
cv::Mat w_mat(CVMAT_WITH_CHECK(w));
|
||||
cv::Mat mean_mat(CVMAT_WITH_CHECK(mean));
|
||||
cv::Mat self_mat(CVMAT(self));
|
||||
cv::Mat pmat = cv::subspaceProject(w_mat, mean_mat, self_mat);
|
||||
projection = new_object(pmat.rows, pmat.cols, pmat.type());
|
||||
CvMat tmp = pmat;
|
||||
cvCopy(&tmp, CVMAT(projection));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return projection;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* subspace_reconstruct(w, mean) -> cvmat
|
||||
*/
|
||||
VALUE
|
||||
rb_subspace_reconstruct(VALUE self, VALUE w, VALUE mean)
|
||||
{
|
||||
VALUE result;
|
||||
try {
|
||||
cv::Mat w_mat(CVMAT_WITH_CHECK(w));
|
||||
cv::Mat mean_mat(CVMAT_WITH_CHECK(mean));
|
||||
cv::Mat self_mat(CVMAT(self));
|
||||
cv::Mat rmat = cv::subspaceReconstruct(w_mat, mean_mat, self_mat);
|
||||
result = new_object(rmat.rows, rmat.cols, rmat.type());
|
||||
CvMat tmp = rmat;
|
||||
cvCopy(&tmp, CVMAT(result));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VALUE
|
||||
new_object(int rows, int cols, int type)
|
||||
{
|
||||
|
|
|
@ -78,7 +78,7 @@ VALUE rb_set_identity_bang(int argc, VALUE *argv, VALUE self);
|
|||
VALUE rb_range(VALUE self, VALUE start, VALUE end);
|
||||
VALUE rb_range_bang(VALUE self, VALUE start, VALUE end);
|
||||
/* Transforms and Permutations */
|
||||
VALUE rb_reshape(VALUE self, VALUE hash);
|
||||
VALUE rb_reshape(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_repeat(VALUE self, VALUE object);
|
||||
VALUE rb_flip(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_flip_bang(int argc, VALUE *argv, VALUE self);
|
||||
|
@ -214,6 +214,9 @@ VALUE rb_dist_transform(int argc, VALUE *argv, VALUE self);
|
|||
VALUE rb_inpaint(VALUE self, VALUE inpaint_method, VALUE mask, VALUE radius);
|
||||
|
||||
VALUE rb_equalize_hist(VALUE self);
|
||||
|
||||
VALUE rb_apply_color_map(VALUE self, VALUE colormap);
|
||||
|
||||
/* Matching*/
|
||||
VALUE rb_match_template(int argc, VALUE *argv, VALUE self);
|
||||
VALUE rb_match_shapes(int argc, VALUE *argv, VALUE self);
|
||||
|
@ -236,6 +239,9 @@ VALUE rb_compute_correspond_epilines(VALUE klass, VALUE points, VALUE which_imag
|
|||
/* Feature detection and description */
|
||||
VALUE rb_extract_surf(int argc, VALUE *argv, VALUE self);
|
||||
|
||||
VALUE rb_subspace_project(VALUE self, VALUE w, VALUE mean);
|
||||
VALUE rb_subspace_reconstruct(VALUE self, VALUE w, VALUE mean);
|
||||
|
||||
// HighGUI function
|
||||
VALUE rb_save_image(int argc, VALUE *argv, VALUE self);
|
||||
|
||||
|
|
67
ext/opencv/eigenfaces.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/************************************************************
|
||||
|
||||
eigenfaces.cpp -
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "eigenfaces.h"
|
||||
/*
|
||||
* Document-class: OpenCV::EigenFaces
|
||||
*
|
||||
*/
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_EIGENFACES
|
||||
|
||||
VALUE rb_klass;
|
||||
|
||||
VALUE
|
||||
rb_class()
|
||||
{
|
||||
return rb_klass;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* EigenFaces.new(num_components=0, threshold=DBL_MAX)
|
||||
*/
|
||||
VALUE
|
||||
rb_initialize(int argc, VALUE argv[], VALUE self)
|
||||
{
|
||||
VALUE num_components_val, threshold_val;
|
||||
rb_scan_args(argc, argv, "02", &num_components_val, &threshold_val);
|
||||
|
||||
int num_components = NIL_P(num_components_val) ? 0 : NUM2INT(num_components_val);
|
||||
double threshold = NIL_P(threshold_val) ? DBL_MAX : NUM2DBL(threshold_val);
|
||||
|
||||
free(DATA_PTR(self));
|
||||
cv::Ptr<cv::FaceRecognizer> ptr = cv::createEigenFaceRecognizer(num_components, threshold);
|
||||
DATA_PTR(self) = ptr;
|
||||
|
||||
cFaceRecognizer::guard_facerecognizer(DATA_PTR(self), ptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
define_ruby_class()
|
||||
{
|
||||
if (rb_klass)
|
||||
return;
|
||||
/*
|
||||
* opencv = rb_define_module("OpenCV");
|
||||
*
|
||||
* note: this comment is used by rdoc.
|
||||
*/
|
||||
VALUE opencv = rb_module_opencv();
|
||||
rb_klass = rb_define_class_under(opencv, "EigenFaces", cFaceRecognizer::rb_class());
|
||||
rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer);
|
||||
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
||||
}
|
||||
|
||||
__NAMESPACE_END_EIGENFACES
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
30
ext/opencv/eigenfaces.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/************************************************************
|
||||
|
||||
eigenfaces.h
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#ifndef RUBY_OPENCV_EIGENFACES_H
|
||||
#define RUBY_OPENCV_EIGENFACES_H
|
||||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_EIGENFACES namespace cEigenFaces {
|
||||
#define __NAMESPACE_END_EIGENFACES }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_EIGENFACES
|
||||
|
||||
VALUE rb_class();
|
||||
|
||||
void define_ruby_class();
|
||||
VALUE rb_initialize(int argc, VALUE argv[], VALUE self);
|
||||
|
||||
__NAMESPACE_END_EIGENFACES
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
||||
#endif // RUBY_OPENCV_EIGENFACES_H
|
||||
|
174
ext/opencv/facerecognizer.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
/************************************************************
|
||||
|
||||
facerecognizer.cpp -
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "facerecognizer.h"
|
||||
/*
|
||||
* Document-class: OpenCV::FaceRecognizer
|
||||
*
|
||||
*/
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_FACERECOGNIZER
|
||||
|
||||
VALUE rb_klass;
|
||||
|
||||
std::map< long, cv::Ptr<cv::FaceRecognizer> > ptr_guard_map;
|
||||
|
||||
void
|
||||
guard_facerecognizer(void* data_ptr, cv::Ptr<cv::FaceRecognizer> ptr)
|
||||
{
|
||||
ptr_guard_map[(long)data_ptr] = ptr;
|
||||
}
|
||||
|
||||
void
|
||||
release_facerecognizer(void *ptr)
|
||||
{
|
||||
long key = (long)ptr;
|
||||
ptr_guard_map[key].release();
|
||||
ptr_guard_map.erase(key);
|
||||
}
|
||||
|
||||
VALUE
|
||||
allocate_facerecognizer(VALUE klass)
|
||||
{
|
||||
return Data_Wrap_Struct(klass, 0, release_facerecognizer, NULL);
|
||||
}
|
||||
|
||||
|
||||
VALUE
|
||||
rb_class()
|
||||
{
|
||||
return rb_klass;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* train(src, labels)
|
||||
*
|
||||
* Trains a FaceRecognizer with given data and associated labels.
|
||||
*/
|
||||
VALUE
|
||||
rb_train(VALUE self, VALUE src, VALUE labels)
|
||||
{
|
||||
Check_Type(src, T_ARRAY);
|
||||
Check_Type(labels, T_ARRAY);
|
||||
|
||||
VALUE *src_ptr = RARRAY_PTR(src);
|
||||
int src_size = RARRAY_LEN(src);
|
||||
std::vector<cv::Mat> images;
|
||||
for (int i = 0; i < src_size; i++) {
|
||||
images.push_back(cv::Mat(CVMAT_WITH_CHECK(src_ptr[i])));
|
||||
}
|
||||
|
||||
VALUE *labels_ptr = RARRAY_PTR(labels);
|
||||
int labels_size = RARRAY_LEN(labels);
|
||||
std::vector<int> local_labels;
|
||||
for (int i = 0; i < labels_size; i++) {
|
||||
local_labels.push_back(NUM2INT(labels_ptr[i]));
|
||||
}
|
||||
|
||||
cv::FaceRecognizer *self_ptr = FACERECOGNIZER(self);
|
||||
try {
|
||||
self_ptr->train(images, local_labels);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* predict(src)
|
||||
*
|
||||
* Predicts a label and associated confidence (e.g. distance) for a given input image.
|
||||
*/
|
||||
VALUE
|
||||
rb_predict(VALUE self, VALUE src)
|
||||
{
|
||||
cv::Mat mat = cv::Mat(CVMAT_WITH_CHECK(src));
|
||||
cv::FaceRecognizer *self_ptr = FACERECOGNIZER(self);
|
||||
int label;
|
||||
double confidence;
|
||||
try {
|
||||
self_ptr->predict(mat, label, confidence);
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return rb_ary_new3(2, INT2NUM(label), DBL2NUM(confidence));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* save(filename)
|
||||
*
|
||||
* Saves this model to a given filename, either as XML or YAML.
|
||||
*/
|
||||
VALUE
|
||||
rb_save(VALUE self, VALUE filename)
|
||||
{
|
||||
Check_Type(filename, T_STRING);
|
||||
cv::FaceRecognizer *self_ptr = FACERECOGNIZER(self);
|
||||
try {
|
||||
char* s = StringValueCStr(filename);
|
||||
self_ptr->save(std::string(s));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* load(filename)
|
||||
*
|
||||
* Loads a FaceRecognizer and its model state.
|
||||
*/
|
||||
VALUE
|
||||
rb_load(VALUE self, VALUE filename)
|
||||
{
|
||||
Check_Type(filename, T_STRING);
|
||||
cv::FaceRecognizer *self_ptr = FACERECOGNIZER(self);
|
||||
try {
|
||||
char* s = StringValueCStr(filename);
|
||||
self_ptr->load(std::string(s));
|
||||
}
|
||||
catch (cv::Exception& e) {
|
||||
raise_cverror(e);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void
|
||||
define_ruby_class()
|
||||
{
|
||||
if (rb_klass)
|
||||
return;
|
||||
/*
|
||||
* opencv = rb_define_module("OpenCV");
|
||||
*
|
||||
* note: this comment is used by rdoc.
|
||||
*/
|
||||
VALUE opencv = rb_module_opencv();
|
||||
rb_klass = rb_define_class_under(opencv, "FaceRecognizer", cAlgorithm::rb_class());
|
||||
rb_define_method(rb_klass, "train", RUBY_METHOD_FUNC(rb_train), 2);
|
||||
rb_define_method(rb_klass, "predict", RUBY_METHOD_FUNC(rb_predict), 1);
|
||||
rb_define_method(rb_klass, "save", RUBY_METHOD_FUNC(rb_save), 1);
|
||||
rb_define_method(rb_klass, "load", RUBY_METHOD_FUNC(rb_load), 1);
|
||||
}
|
||||
|
||||
__NAMESPACE_END_FACERECOGNIZER
|
||||
__NAMESPACE_END_OPENCV
|
46
ext/opencv/facerecognizer.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/************************************************************
|
||||
|
||||
facerecognizer.h
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#ifndef RUBY_OPENCV_FACERECOGNIZER_H
|
||||
#define RUBY_OPENCV_FACERECOGNIZER_H
|
||||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_FACERECOGNIZER namespace cFaceRecognizer {
|
||||
#define __NAMESPACE_END_FACERECOGNIZER }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_FACERECOGNIZER
|
||||
|
||||
VALUE rb_class();
|
||||
|
||||
void define_ruby_class();
|
||||
VALUE rb_train(VALUE self, VALUE src, VALUE labels);
|
||||
VALUE rb_predict(VALUE self, VALUE src);
|
||||
VALUE rb_save(VALUE self, VALUE filename);
|
||||
VALUE rb_load(VALUE self, VALUE filename);
|
||||
|
||||
void guard_facerecognizer(void* data_ptr, cv::Ptr<cv::FaceRecognizer> ptr);
|
||||
void release_facerecognizer(void *ptr);
|
||||
VALUE allocate_facerecognizer(VALUE klass);
|
||||
|
||||
__NAMESPACE_END_FACERECOGNIZER
|
||||
|
||||
inline cv::FaceRecognizer*
|
||||
FACERECOGNIZER(VALUE object)
|
||||
{
|
||||
cv::FaceRecognizer *ptr;
|
||||
Data_Get_Struct(object, cv::FaceRecognizer, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
||||
#endif // RUBY_OPENCV_FACERECOGNIZER_H
|
||||
|
67
ext/opencv/fisherfaces.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/************************************************************
|
||||
|
||||
fisherfaces.cpp -
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "fisherfaces.h"
|
||||
/*
|
||||
* Document-class: OpenCV::FisherFaces
|
||||
*
|
||||
*/
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_FISHERFACES
|
||||
|
||||
VALUE rb_klass;
|
||||
|
||||
VALUE
|
||||
rb_class()
|
||||
{
|
||||
return rb_klass;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* FisherFaces.new(num_components=0, threshold=DBL_MAX)
|
||||
*/
|
||||
VALUE
|
||||
rb_initialize(int argc, VALUE argv[], VALUE self)
|
||||
{
|
||||
VALUE num_components_val, threshold_val;
|
||||
rb_scan_args(argc, argv, "02", &num_components_val, &threshold_val);
|
||||
|
||||
int num_components = NIL_P(num_components_val) ? 0 : NUM2INT(num_components_val);
|
||||
double threshold = NIL_P(threshold_val) ? DBL_MAX : NUM2DBL(threshold_val);
|
||||
|
||||
free(DATA_PTR(self));
|
||||
cv::Ptr<cv::FaceRecognizer> ptr = cv::createFisherFaceRecognizer(num_components, threshold);
|
||||
DATA_PTR(self) = ptr;
|
||||
|
||||
cFaceRecognizer::guard_facerecognizer(DATA_PTR(self), ptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
define_ruby_class()
|
||||
{
|
||||
if (rb_klass)
|
||||
return;
|
||||
/*
|
||||
* opencv = rb_define_module("OpenCV");
|
||||
*
|
||||
* note: this comment is used by rdoc.
|
||||
*/
|
||||
VALUE opencv = rb_module_opencv();
|
||||
rb_klass = rb_define_class_under(opencv, "FisherFaces", cFaceRecognizer::rb_class());
|
||||
rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer);
|
||||
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
||||
}
|
||||
|
||||
__NAMESPACE_END_FISHERFACES
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
30
ext/opencv/fisherfaces.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/************************************************************
|
||||
|
||||
fisherfaces.h
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#ifndef RUBY_OPENCV_FISHERFACES_H
|
||||
#define RUBY_OPENCV_FISHERFACES_H
|
||||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_FISHERFACES namespace cFisherFaces {
|
||||
#define __NAMESPACE_END_FISHERFACES }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_FISHERFACES
|
||||
|
||||
VALUE rb_class();
|
||||
|
||||
void define_ruby_class();
|
||||
VALUE rb_initialize(int argc, VALUE argv[], VALUE self);
|
||||
|
||||
__NAMESPACE_END_FISHERFACES
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
||||
#endif // RUBY_OPENCV_FISHERFACES_H
|
||||
|
70
ext/opencv/lbph.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/************************************************************
|
||||
|
||||
lbph.cpp -
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "lbph.h"
|
||||
/*
|
||||
* Document-class: OpenCV::LBPH
|
||||
*
|
||||
*/
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_LBPH
|
||||
|
||||
VALUE rb_klass;
|
||||
|
||||
VALUE
|
||||
rb_class()
|
||||
{
|
||||
return rb_klass;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* LBPH.new(radius=1, neighbors=8, grid_x=8, grid_y=8, threshold=DBL_MAX) -> cvmat
|
||||
*/
|
||||
VALUE
|
||||
rb_initialize(int argc, VALUE argv[], VALUE self)
|
||||
{
|
||||
VALUE radius_val, neighbors_val, grid_x_val, grid_y_val, threshold_val;
|
||||
rb_scan_args(argc, argv, "05", &radius_val, &neighbors_val, &grid_x_val, &grid_y_val, &threshold_val);
|
||||
|
||||
int radius = NIL_P(radius_val) ? 1 : NUM2INT(radius_val);
|
||||
int neighbors = NIL_P(neighbors_val) ? 8 : NUM2INT(neighbors_val);
|
||||
int grid_x = NIL_P(grid_x_val) ? 8 : NUM2INT(grid_x_val);
|
||||
int grid_y = NIL_P(grid_y_val) ? 8 : NUM2INT(grid_y_val);
|
||||
double threshold = NIL_P(threshold_val) ? DBL_MAX : NUM2INT(threshold_val);
|
||||
|
||||
free(DATA_PTR(self));
|
||||
cv::Ptr<cv::FaceRecognizer> ptr = cv::createLBPHFaceRecognizer(radius, neighbors, grid_x, grid_y, threshold);
|
||||
DATA_PTR(self) = ptr;
|
||||
|
||||
cFaceRecognizer::guard_facerecognizer(DATA_PTR(self), ptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
define_ruby_class()
|
||||
{
|
||||
if (rb_klass)
|
||||
return;
|
||||
/*
|
||||
* opencv = rb_define_module("OpenCV");
|
||||
*
|
||||
* note: this comment is used by rdoc.
|
||||
*/
|
||||
VALUE opencv = rb_module_opencv();
|
||||
rb_klass = rb_define_class_under(opencv, "LBPH", cFaceRecognizer::rb_class());
|
||||
rb_define_alloc_func(rb_klass, cFaceRecognizer::allocate_facerecognizer);
|
||||
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
||||
}
|
||||
|
||||
__NAMESPACE_END_LBPH
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
30
ext/opencv/lbph.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/************************************************************
|
||||
|
||||
lbph.h
|
||||
|
||||
$Author: ser1zw $
|
||||
|
||||
Copyright (C) 2013 ser1zw
|
||||
|
||||
************************************************************/
|
||||
#ifndef RUBY_OPENCV_LBPH_H
|
||||
#define RUBY_OPENCV_LBPH_H
|
||||
|
||||
#include "opencv.h"
|
||||
|
||||
#define __NAMESPACE_BEGIN_LBPH namespace cLBPH {
|
||||
#define __NAMESPACE_END_LBPH }
|
||||
|
||||
__NAMESPACE_BEGIN_OPENCV
|
||||
__NAMESPACE_BEGIN_LBPH
|
||||
|
||||
VALUE rb_class();
|
||||
|
||||
void define_ruby_class();
|
||||
VALUE rb_initialize(int argc, VALUE argv[], VALUE self);
|
||||
|
||||
__NAMESPACE_END_LBPH
|
||||
__NAMESPACE_END_OPENCV
|
||||
|
||||
#endif // RUBY_OPENCV_LBPH_H
|
||||
|
|
@ -185,7 +185,37 @@ define_ruby_module()
|
|||
rb_define_const(rb_module, "CV_32F", INT2FIX(CV_32F));
|
||||
/* 6: 64bit floating-point */
|
||||
rb_define_const(rb_module, "CV_64F", INT2FIX(CV_64F));
|
||||
|
||||
|
||||
/* Other depth */
|
||||
rb_define_const(rb_module, "CV_8UC1", INT2FIX(CV_8UC1));
|
||||
rb_define_const(rb_module, "CV_8UC2", INT2FIX(CV_8UC2));
|
||||
rb_define_const(rb_module, "CV_8UC3", INT2FIX(CV_8UC3));
|
||||
rb_define_const(rb_module, "CV_8UC4", INT2FIX(CV_8UC4));
|
||||
rb_define_const(rb_module, "CV_8SC1", INT2FIX(CV_8SC1));
|
||||
rb_define_const(rb_module, "CV_8SC2", INT2FIX(CV_8SC2));
|
||||
rb_define_const(rb_module, "CV_8SC3", INT2FIX(CV_8SC3));
|
||||
rb_define_const(rb_module, "CV_8SC4", INT2FIX(CV_8SC4));
|
||||
rb_define_const(rb_module, "CV_16UC1", INT2FIX(CV_16UC1));
|
||||
rb_define_const(rb_module, "CV_16UC2", INT2FIX(CV_16UC2));
|
||||
rb_define_const(rb_module, "CV_16UC3", INT2FIX(CV_16UC3));
|
||||
rb_define_const(rb_module, "CV_16UC4", INT2FIX(CV_16UC4));
|
||||
rb_define_const(rb_module, "CV_16SC1", INT2FIX(CV_16SC1));
|
||||
rb_define_const(rb_module, "CV_16SC2", INT2FIX(CV_16SC2));
|
||||
rb_define_const(rb_module, "CV_16SC3", INT2FIX(CV_16SC3));
|
||||
rb_define_const(rb_module, "CV_16SC4", INT2FIX(CV_16SC4));
|
||||
rb_define_const(rb_module, "CV_32SC1", INT2FIX(CV_32SC1));
|
||||
rb_define_const(rb_module, "CV_32SC2", INT2FIX(CV_32SC2));
|
||||
rb_define_const(rb_module, "CV_32SC3", INT2FIX(CV_32SC3));
|
||||
rb_define_const(rb_module, "CV_32SC4", INT2FIX(CV_32SC4));
|
||||
rb_define_const(rb_module, "CV_32FC1", INT2FIX(CV_32FC1));
|
||||
rb_define_const(rb_module, "CV_32FC2", INT2FIX(CV_32FC2));
|
||||
rb_define_const(rb_module, "CV_32FC3", INT2FIX(CV_32FC3));
|
||||
rb_define_const(rb_module, "CV_32FC4", INT2FIX(CV_32FC4));
|
||||
rb_define_const(rb_module, "CV_64FC1", INT2FIX(CV_64FC1));
|
||||
rb_define_const(rb_module, "CV_64FC2", INT2FIX(CV_64FC2));
|
||||
rb_define_const(rb_module, "CV_64FC3", INT2FIX(CV_64FC3));
|
||||
rb_define_const(rb_module, "CV_64FC4", INT2FIX(CV_64FC4));
|
||||
|
||||
/* Color types of loaded images */
|
||||
rb_define_const(rb_module, "CV_LOAD_IMAGE_UNCHANGED", INT2FIX(CV_LOAD_IMAGE_UNCHANGED));
|
||||
rb_define_const(rb_module, "CV_LOAD_IMAGE_GRAYSCALE", INT2FIX(CV_LOAD_IMAGE_GRAYSCALE));
|
||||
|
@ -342,6 +372,19 @@ define_ruby_module()
|
|||
rb_define_const(rb_module, "CV_CALIB_CB_FILTER_QUADS", INT2FIX(CV_CALIB_CB_FILTER_QUADS));
|
||||
rb_define_const(rb_module, "CV_CALIB_CB_FAST_CHECK", INT2FIX(CV_CALIB_CB_FAST_CHECK));
|
||||
|
||||
/* Color map for cv::applyColorMap */
|
||||
rb_define_const(rb_module, "COLORMAP_AUTUMN", INT2FIX(cv::COLORMAP_AUTUMN));
|
||||
rb_define_const(rb_module, "COLORMAP_BONE", INT2FIX(cv::COLORMAP_BONE));
|
||||
rb_define_const(rb_module, "COLORMAP_JET", INT2FIX(cv::COLORMAP_JET));
|
||||
rb_define_const(rb_module, "COLORMAP_WINTER", INT2FIX(cv::COLORMAP_WINTER));
|
||||
rb_define_const(rb_module, "COLORMAP_RAINBOW", INT2FIX(cv::COLORMAP_RAINBOW));
|
||||
rb_define_const(rb_module, "COLORMAP_OCEAN", INT2FIX(cv::COLORMAP_OCEAN));
|
||||
rb_define_const(rb_module, "COLORMAP_SUMMER", INT2FIX(cv::COLORMAP_SUMMER));
|
||||
rb_define_const(rb_module, "COLORMAP_SPRING", INT2FIX(cv::COLORMAP_SPRING));
|
||||
rb_define_const(rb_module, "COLORMAP_COOL", INT2FIX(cv::COLORMAP_COOL));
|
||||
rb_define_const(rb_module, "COLORMAP_HSV", INT2FIX(cv::COLORMAP_HSV));
|
||||
rb_define_const(rb_module, "COLORMAP_PINK", INT2FIX(cv::COLORMAP_PINK));
|
||||
rb_define_const(rb_module, "COLORMAP_HOT", INT2FIX(cv::COLORMAP_HOT));
|
||||
|
||||
VALUE inversion_method = rb_hash_new();
|
||||
/* {:lu, :svd, :svd_sym(:svd_symmetric)}: Inversion method */
|
||||
|
@ -711,6 +754,13 @@ extern "C" {
|
|||
mOpenCV::cCvConnectedComp::define_ruby_class();
|
||||
mOpenCV::cCvAvgComp::define_ruby_class();
|
||||
mOpenCV::cCvHaarClassifierCascade::define_ruby_class();
|
||||
|
||||
mOpenCV::cAlgorithm::define_ruby_class();
|
||||
mOpenCV::cFaceRecognizer::define_ruby_class();
|
||||
mOpenCV::cEigenFaces::define_ruby_class();
|
||||
mOpenCV::cFisherFaces::define_ruby_class();
|
||||
mOpenCV::cLBPH::define_ruby_class();
|
||||
|
||||
mOpenCV::mGUI::define_ruby_module();
|
||||
mOpenCV::mGUI::cWindow::define_ruby_class();
|
||||
mOpenCV::mGUI::cTrackbar::define_ruby_class();
|
||||
|
|
|
@ -130,6 +130,12 @@ extern "C" {
|
|||
|
||||
#include "cvfeaturetree.h"
|
||||
|
||||
#include "algorithm.h"
|
||||
#include "facerecognizer.h"
|
||||
#include "eigenfaces.h"
|
||||
#include "fisherfaces.h"
|
||||
#include "lbph.h"
|
||||
|
||||
// GUI
|
||||
#include "gui.h"
|
||||
#include "window.h"
|
||||
|
|
7524
test/eigenfaces_save.xml
Normal file
7530
test/fisherfaces_save.xml
Normal file
4304
test/lbph_save.xml
Normal file
|
@ -888,7 +888,7 @@ class TestCvMat < OpenCVTestCase
|
|||
def test_reshape
|
||||
m = create_cvmat(2, 3, CV_8U, 3)
|
||||
|
||||
vec = m.reshape(:rows => 1)
|
||||
vec = m.reshape(0, 1)
|
||||
assert_equal(6, vec.width)
|
||||
assert_equal(1, vec.height)
|
||||
size = m.width * m.height
|
||||
|
@ -896,7 +896,7 @@ class TestCvMat < OpenCVTestCase
|
|||
assert_cvscalar_equal(m[i], vec[i])
|
||||
}
|
||||
|
||||
ch1 = m.reshape(:channel => 1)
|
||||
ch1 = m.reshape(1)
|
||||
assert_equal(9, ch1.width)
|
||||
assert_equal(2, ch1.height)
|
||||
|
||||
|
@ -909,10 +909,11 @@ class TestCvMat < OpenCVTestCase
|
|||
}
|
||||
}
|
||||
|
||||
[DUMMY_OBJ, { :rows => DUMMY_OBJ }, { :channel => DUMMY_OBJ }].each { |arg|
|
||||
assert_raise(TypeError) {
|
||||
m.reshape(arg)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
m.reshape(DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
m.reshape(0, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -2053,10 +2054,16 @@ class TestCvMat < OpenCVTestCase
|
|||
assert_in_delta(x, mminmax[i][0], 0.001)
|
||||
}
|
||||
|
||||
minf = mat.normalize(1, 0, CV_NORM_INF, CV_32FC3)
|
||||
expected = [0.0, 0.333, 0.666, 1.0]
|
||||
expected.each_with_index { |x, i|
|
||||
assert_in_delta(x, minf[i][0], 0.001)
|
||||
}
|
||||
|
||||
mask = mat.to_8u.zero
|
||||
mask[0, 0] = CvScalar.new(255, 0, 0)
|
||||
mask[1, 0] = CvScalar.new(255, 0, 0)
|
||||
minf = mat.normalize(1, 0, CV_NORM_INF, mask)
|
||||
minf = mat.normalize(1, 0, CV_NORM_INF, -1, mask)
|
||||
expected = [0.0, 0.0, 1.0, 0.0]
|
||||
expected.each_with_index { |x, i|
|
||||
assert_in_delta(x, minf[i][0], 0.001)
|
||||
|
@ -2794,11 +2801,11 @@ class TestCvMat < OpenCVTestCase
|
|||
CvMat.find_fundamental_mat(mat1, mat2, CV_FM_LMEDS)].each { |f_mat|
|
||||
assert_equal(3, f_mat.rows)
|
||||
assert_equal(3, f_mat.cols)
|
||||
expected = [-2.79e-05, -0.0009362, 0.0396139,
|
||||
0.0010285, -2.48e-05, -0.3946452,
|
||||
-0.0322220, 0.3695115, 1.0]
|
||||
expected = [0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0]
|
||||
expected.each_with_index { |val, i|
|
||||
assert_in_delta(val, f_mat[i][0], 1.0e-5)
|
||||
assert_in_delta(val, f_mat[i][0], 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2810,13 +2817,13 @@ class TestCvMat < OpenCVTestCase
|
|||
assert_equal(1, status.rows)
|
||||
assert_equal(num_points, status.cols)
|
||||
|
||||
expected_f_mat = [6.48e-05, 0.001502, -0.086036,
|
||||
-0.001652, 3.86e-05, 0.638690,
|
||||
0.059998, -0.597778, 1.0]
|
||||
expected_fmat = [0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0]
|
||||
expected_f_mat.each_with_index { |val, i|
|
||||
assert_in_delta(val, f_mat[i][0], 1.0e-5)
|
||||
assert_in_delta(val, f_mat[i][0], 0.1)
|
||||
}
|
||||
expected_status = [1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
|
||||
expected_status = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1]
|
||||
expected_status.each_with_index { |val, i|
|
||||
assert_equal(val, status[i][0].to_i)
|
||||
}
|
||||
|
@ -2943,5 +2950,54 @@ class TestCvMat < OpenCVTestCase
|
|||
CvMat.compute_correspond_epilines(mat1, 1, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_apply_color_map
|
||||
mat = CvMat.new(64, 256, :cv8u, 1)
|
||||
mat.cols.times { |c|
|
||||
mat.rows.times { |r|
|
||||
mat[r, c] = c
|
||||
}
|
||||
}
|
||||
|
||||
results = []
|
||||
[COLORMAP_AUTUMN, COLORMAP_BONE, COLORMAP_JET, COLORMAP_WINTER,
|
||||
COLORMAP_RAINBOW, COLORMAP_OCEAN, COLORMAP_SUMMER, COLORMAP_SPRING,
|
||||
COLORMAP_COOL, COLORMAP_HSV, COLORMAP_PINK, COLORMAP_HOT].each { |colormap|
|
||||
cmap = mat.apply_color_map(colormap)
|
||||
assert_equal(CvMat, cmap.class)
|
||||
assert_equal(mat.rows, cmap.rows)
|
||||
assert_equal(mat.cols, cmap.cols)
|
||||
results << cmap
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
mat.apply_color_map(DUMMY_OBJ)
|
||||
}
|
||||
|
||||
# Uncomment the following line to show the result
|
||||
# snap *results
|
||||
end
|
||||
|
||||
def test_subspace_project
|
||||
w = CvMat.new(10, 20, :cv32f, 1)
|
||||
mean = CvMat.new(w.rows, 1, :cv32f, 1)
|
||||
mat = CvMat.new(w.cols, w.rows, :cv32f, 1)
|
||||
result = mat.subspace_project(w, mean)
|
||||
|
||||
assert_equal(CvMat, result.class)
|
||||
assert_equal(w.cols, result.rows)
|
||||
assert_equal(w.cols, result.cols)
|
||||
end
|
||||
|
||||
def test_subspace_reconstruct
|
||||
w = CvMat.new(10, 20, :cv32f, 1)
|
||||
mean = CvMat.new(w.rows, 1, :cv32f, 1)
|
||||
mat = CvMat.new(w.cols, w.cols, :cv32f, 1)
|
||||
result = mat.subspace_reconstruct(w, mean)
|
||||
|
||||
assert_equal(CvMat, result.class)
|
||||
assert_equal(w.cols, result.rows)
|
||||
assert_equal(w.rows, result.cols)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1009,10 +1009,18 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
test_proc = lambda { |type, type_sym, expected_mat, expected_threshold|
|
||||
mat1 = mat0.threshold(expected_threshold, 7, type)
|
||||
mat2 = mat0.threshold(expected_threshold, 7, type_sym)
|
||||
[mat1, mat2].each { |m|
|
||||
expected_mat.each_with_index { |x, i|
|
||||
assert_equal(x, m[i][0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_proc_with_otsu = lambda { |type, type_sym, expected_mat, expected_threshold|
|
||||
mat3, th3 = mat0.threshold(5, 7, type | CV_THRESH_OTSU)
|
||||
mat4, th4 = mat0.threshold(3, 7, type_sym, true)
|
||||
mat5, th5 = mat0.threshold(5, 7, type | CV_THRESH_OTSU, true)
|
||||
[mat1, mat2, mat3, mat4, mat5].each { |m|
|
||||
[mat3, mat4, mat5].each { |m|
|
||||
expected_mat.each_with_index { |x, i|
|
||||
assert_equal(x, m[i][0])
|
||||
}
|
||||
|
@ -1021,36 +1029,62 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
assert_in_delta(expected_threshold, th, 0.001)
|
||||
}
|
||||
}
|
||||
|
||||
# Binary
|
||||
expected = [0, 0, 0,
|
||||
0, 0, 7,
|
||||
7, 7, 7]
|
||||
test_proc.call(CV_THRESH_BINARY, :binary, expected, 4)
|
||||
|
||||
expected = [0, 0, 0,
|
||||
0, 7, 7,
|
||||
7, 7, 7]
|
||||
test_proc_with_otsu.call(CV_THRESH_BINARY, :binary, expected, 3)
|
||||
|
||||
# Binary inverse
|
||||
expected = [7, 7, 7,
|
||||
7, 7, 0,
|
||||
0, 0, 0]
|
||||
test_proc.call(CV_THRESH_BINARY_INV, :binary_inv, expected, 4)
|
||||
|
||||
expected = [7, 7, 7,
|
||||
7, 0, 0,
|
||||
0, 0, 0]
|
||||
test_proc_with_otsu.call(CV_THRESH_BINARY_INV, :binary_inv, expected, 3)
|
||||
|
||||
# Trunc
|
||||
expected = [0, 1, 2,
|
||||
3, 4, 4,
|
||||
4, 4, 4]
|
||||
test_proc.call(CV_THRESH_TRUNC, :trunc, expected, 4)
|
||||
|
||||
expected = [0, 1, 2,
|
||||
3, 3, 3,
|
||||
3, 3, 3]
|
||||
test_proc_with_otsu.call(CV_THRESH_TRUNC, :trunc, expected, 3)
|
||||
|
||||
# To zero
|
||||
expected = [0, 0, 0,
|
||||
0, 0, 5,
|
||||
6, 7, 8]
|
||||
test_proc.call(CV_THRESH_TOZERO, :tozero, expected, 4)
|
||||
|
||||
expected = [0, 0, 0,
|
||||
0, 4, 5,
|
||||
6, 7, 8]
|
||||
test_proc_with_otsu.call(CV_THRESH_TOZERO, :tozero, expected, 3)
|
||||
|
||||
# To zero inverse
|
||||
expected = [0, 1, 2,
|
||||
3, 4, 0,
|
||||
0, 0, 0]
|
||||
test_proc.call(CV_THRESH_TOZERO_INV, :tozero_inv, expected, 4)
|
||||
|
||||
expected = [0, 1, 2,
|
||||
3, 0, 0,
|
||||
0, 0, 0]
|
||||
test_proc_with_otsu.call(CV_THRESH_TOZERO_INV, :tozero_inv, expected, 3)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
mat0.threshold(DUMMY_OBJ, 2, :binary)
|
||||
}
|
||||
|
@ -1603,7 +1637,9 @@ class TestCvMat_imageprocessing < OpenCVTestCase
|
|||
def test_equalize_hist
|
||||
mat = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
result = mat.equalize_hist
|
||||
assert_equal('de235065c746193d7f3de9359f63a7af', hash_img(result))
|
||||
assert_equal(CvMat, result.class)
|
||||
assert_equal(mat.rows, result.rows)
|
||||
assert_equal(mat.cols, result.cols)
|
||||
|
||||
assert_raise(CvStsAssert) {
|
||||
CvMat.new(10, 10, :cv32f, 3).equalize_hist
|
||||
|
|
93
test/test_eigenfaces.rb
Executable file
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8-unix -*-
|
||||
require 'test/unit'
|
||||
require 'opencv'
|
||||
require 'date'
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
||||
|
||||
include OpenCV
|
||||
|
||||
# Tests for OpenCV::EigenFaces
|
||||
class TestEigenFaces < OpenCVTestCase
|
||||
def setup
|
||||
@eigenfaces = EigenFaces.new
|
||||
|
||||
@eigenfaces_trained = EigenFaces.new
|
||||
@images = [CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)] * 2
|
||||
@labels = [1, 2]
|
||||
@eigenfaces_trained.train(@images, @labels)
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
[EigenFaces.new, EigenFaces.new(1), EigenFaces.new(1, 99999)].each { |ef|
|
||||
assert_equal(EigenFaces, ef.class)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
EigenFaces.new(DUMMY_OBJ)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
EigenFaces.new(1, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_train
|
||||
assert_nil(@eigenfaces.train(@images, @labels))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces.train(DUMMY_OBJ, @labels)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces.train(@images, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_predict
|
||||
predicted_label, predicted_confidence = @eigenfaces_trained.predict(@images[0])
|
||||
assert_equal(@labels[0], predicted_label)
|
||||
assert_in_delta(0.0, predicted_confidence, 0.01)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces_trained.predict(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_save
|
||||
filename = "eigenfaces_save-#{DateTime.now.strftime('%Y%m%d%H%M%S')}.xml"
|
||||
begin
|
||||
@eigenfaces_trained.save(filename)
|
||||
assert(File.exist? filename)
|
||||
ensure
|
||||
File.delete filename
|
||||
end
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces_trained.save(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_load
|
||||
assert_nothing_raised {
|
||||
@eigenfaces_trained.load('eigenfaces_save.xml')
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces_trained.load(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_name
|
||||
assert_equal('FaceRecognizer.Eigenfaces', @eigenfaces.name)
|
||||
end
|
||||
|
||||
def test_get_mat
|
||||
mat = @eigenfaces_trained.get_mat('eigenvalues')
|
||||
assert_not_nil(mat)
|
||||
assert_equal(CvMat, mat.class)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@eigenfaces_trained.get_mat(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
93
test/test_fisherfaces.rb
Executable file
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8-unix -*-
|
||||
require 'test/unit'
|
||||
require 'opencv'
|
||||
require 'date'
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
||||
|
||||
include OpenCV
|
||||
|
||||
# Tests for OpenCV::FisherFaces
|
||||
class TestFisherFaces < OpenCVTestCase
|
||||
def setup
|
||||
@fisherfaces = FisherFaces.new
|
||||
|
||||
@fisherfaces_trained = FisherFaces.new
|
||||
@images = [CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)] * 2
|
||||
@labels = [1, 2]
|
||||
@fisherfaces_trained.train(@images, @labels)
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
[FisherFaces.new, FisherFaces.new(1), FisherFaces.new(1, 99999)].each { |ff|
|
||||
assert_equal(FisherFaces, ff.class)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
FisherFaces.new(DUMMY_OBJ)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
FisherFaces.new(1, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_train
|
||||
assert_nil(@fisherfaces.train(@images, @labels))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces.train(DUMMY_OBJ, @labels)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces.train(@images, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_predict
|
||||
predicted_label, predicted_confidence = @fisherfaces_trained.predict(@images[0])
|
||||
assert_equal(@labels[0], predicted_label)
|
||||
assert_in_delta(0.0, predicted_confidence, 0.01)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces_trained.predict(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_save
|
||||
filename = "fisherfaces_save-#{DateTime.now.strftime('%Y%m%d%H%M%S')}.xml"
|
||||
begin
|
||||
@fisherfaces_trained.save(filename)
|
||||
assert(File.exist? filename)
|
||||
ensure
|
||||
File.delete filename
|
||||
end
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces_trained.save(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_load
|
||||
assert_nothing_raised {
|
||||
@fisherfaces.load('fisherfaces_save.xml')
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces.load(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_name
|
||||
assert_equal('FaceRecognizer.Fisherfaces', @fisherfaces.name)
|
||||
end
|
||||
|
||||
def test_get_mat
|
||||
mat = @fisherfaces_trained.get_mat('eigenvalues')
|
||||
assert_not_nil(mat)
|
||||
assert_equal(CvMat, mat.class)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@fisherfaces_trained.get_mat(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -80,28 +80,24 @@ class TestIplImage < OpenCVTestCase
|
|||
img4 = IplImage.decode(data, CV_LOAD_IMAGE_COLOR)
|
||||
img5 = IplImage.decode(data_ary, CV_LOAD_IMAGE_COLOR)
|
||||
img6 = IplImage.decode(data_mat, CV_LOAD_IMAGE_COLOR)
|
||||
expected_hash = hash_img(expected)
|
||||
|
||||
[img1, img2, img3, img4, img5, img6].each { |img|
|
||||
assert_equal(IplImage, img.class)
|
||||
assert_equal(expected.rows, img.rows)
|
||||
assert_equal(expected.cols, img.cols)
|
||||
assert_equal(expected.channel, img.channel)
|
||||
assert_equal(expected_hash, hash_img(img))
|
||||
}
|
||||
|
||||
expected_c1 = IplImage.load(FILENAME_CAT, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img1c1 = IplImage.decode(data, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img2c1 = IplImage.decode(data_ary, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
img3c1 = IplImage.decode(data_mat, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
expected_hash_c1 = hash_img(expected_c1)
|
||||
|
||||
[img1c1, img2c1, img3c1].each { |img|
|
||||
assert_equal(IplImage, img.class)
|
||||
assert_equal(expected_c1.rows, img.rows)
|
||||
assert_equal(expected_c1.cols, img.cols)
|
||||
assert_equal(expected_c1.channel, img.channel)
|
||||
assert_equal(expected_hash_c1, hash_img(img))
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
|
|
152
test/test_lbph.rb
Executable file
|
@ -0,0 +1,152 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- mode: ruby; coding: utf-8-unix -*-
|
||||
require 'test/unit'
|
||||
require 'opencv'
|
||||
require 'date'
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
||||
|
||||
include OpenCV
|
||||
|
||||
# Tests for OpenCV::LBPH
|
||||
class TestLBPH < OpenCVTestCase
|
||||
def setup
|
||||
@lbph = LBPH.new
|
||||
|
||||
@lbph_trained = LBPH.new
|
||||
@images = [CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)] * 2
|
||||
@labels = [1, 2]
|
||||
@lbph_trained.train(@images, @labels)
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
[LBPH.new, LBPH.new(1), LBPH.new(1, 2, 3, 4, 5.0)].each { |lbph|
|
||||
assert_equal(LBPH, lbph.class)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
LBPH.new(DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
LBPH.new(1, DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
LBPH.new(1, 2, DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
LBPH.new(1, 2, 3, DUMMY_OBJ)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
LBPH.new(1, 2, 3, 4, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_train
|
||||
assert_nil(@lbph.train(@images, @labels))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.train(DUMMY_OBJ, @labels)
|
||||
}
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.train(@images, DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_predict
|
||||
predicted_label, predicted_confidence = @lbph_trained.predict(@images[0])
|
||||
assert_equal(@labels[0], predicted_label)
|
||||
assert_in_delta(0.0, predicted_confidence, 0.01)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph_trained.predict(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_save
|
||||
filename = "lbph_save-#{DateTime.now.strftime('%Y%m%d%H%M%S')}.xml"
|
||||
begin
|
||||
@lbph_trained.save(filename)
|
||||
assert(File.exist? filename)
|
||||
ensure
|
||||
File.delete filename
|
||||
end
|
||||
assert_raise(TypeError) {
|
||||
@lbph_trained.save(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_load
|
||||
assert_nothing_raised {
|
||||
@lbph.load('lbph_save.xml')
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
@lbph.load(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_name
|
||||
assert_equal('FaceRecognizer.LBPH', @lbph.name)
|
||||
end
|
||||
|
||||
def test_get_int
|
||||
assert_equal(1, @lbph.get_int('radius'))
|
||||
assert_equal(8, @lbph.get_int('neighbors'))
|
||||
assert_equal(8, @lbph.get_int('grid_x'))
|
||||
assert_equal(8, @lbph.get_int('grid_y'))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.get_int(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_get_double
|
||||
assert_equal(Float::MAX, @lbph.get_double('threshold'))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.get_double(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_get_matvector
|
||||
histgrams = @lbph_trained.get_matvector('histograms')
|
||||
assert_equal(Array, histgrams.class)
|
||||
assert_equal(2, histgrams.size)
|
||||
assert_equal(CvMat, histgrams[0].class)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.get_matvector(DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_set_int
|
||||
@lbph.set_int('radius', 2)
|
||||
@lbph.set_int('neighbors', 3)
|
||||
@lbph.set_int('grid_x', 4)
|
||||
@lbph.set_int('grid_y', 5)
|
||||
|
||||
assert_equal(2, @lbph.get_int('radius'))
|
||||
assert_equal(3, @lbph.get_int('neighbors'))
|
||||
assert_equal(4, @lbph.get_int('grid_x'))
|
||||
assert_equal(5, @lbph.get_int('grid_y'))
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.set_int(DUMMY_OBJ, 1)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
@lbph.set_int('radius', DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
|
||||
def test_set_double
|
||||
@lbph.set_double('threshold', 1.0)
|
||||
assert_in_delta(1.0, @lbph.get_double('threshold'), 0.001)
|
||||
|
||||
assert_raise(TypeError) {
|
||||
@lbph.set_double(DUMMY_OBJ, 1.0)
|
||||
}
|
||||
assert_raise(TypeError) {
|
||||
@lbph.set_double('threshold', DUMMY_OBJ)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -9,15 +9,15 @@ include OpenCV
|
|||
class TestOpenCV < OpenCVTestCase
|
||||
def test_constants
|
||||
# OpenCV version
|
||||
assert_equal('2.4.6.1', CV_VERSION)
|
||||
assert_equal('2.4.7', CV_VERSION)
|
||||
assert_equal(2, CV_MAJOR_VERSION)
|
||||
assert_equal(4, CV_MINOR_VERSION)
|
||||
assert_equal(6, CV_SUBMINOR_VERSION)
|
||||
assert_equal(7, CV_SUBMINOR_VERSION)
|
||||
|
||||
assert_equal(2, CV_VERSION_EPOCH)
|
||||
assert_equal(4, CV_VERSION_MAJOR)
|
||||
assert_equal(6, CV_VERSION_MINOR)
|
||||
assert_equal(1, CV_VERSION_REVISION)
|
||||
assert_equal(7, CV_VERSION_MINOR)
|
||||
assert_equal(0, CV_VERSION_REVISION)
|
||||
|
||||
# Depths
|
||||
assert_equal(0, CV_8U)
|
||||
|
@ -28,6 +28,35 @@ class TestOpenCV < OpenCVTestCase
|
|||
assert_equal(5, CV_32F)
|
||||
assert_equal(6, CV_64F)
|
||||
|
||||
assert_equal(0, CV_8UC1)
|
||||
assert_equal(8, CV_8UC2)
|
||||
assert_equal(16, CV_8UC3)
|
||||
assert_equal(24, CV_8UC4)
|
||||
assert_equal(1, CV_8SC1)
|
||||
assert_equal(9, CV_8SC2)
|
||||
assert_equal(17, CV_8SC3)
|
||||
assert_equal(25, CV_8SC4)
|
||||
assert_equal(2, CV_16UC1)
|
||||
assert_equal(10, CV_16UC2)
|
||||
assert_equal(18, CV_16UC3)
|
||||
assert_equal(26, CV_16UC4)
|
||||
assert_equal(3, CV_16SC1)
|
||||
assert_equal(11, CV_16SC2)
|
||||
assert_equal(19, CV_16SC3)
|
||||
assert_equal(27, CV_16SC4)
|
||||
assert_equal(4, CV_32SC1)
|
||||
assert_equal(12, CV_32SC2)
|
||||
assert_equal(20, CV_32SC3)
|
||||
assert_equal(28, CV_32SC4)
|
||||
assert_equal(5, CV_32FC1)
|
||||
assert_equal(13, CV_32FC2)
|
||||
assert_equal(21, CV_32FC3)
|
||||
assert_equal(29, CV_32FC4)
|
||||
assert_equal(6, CV_64FC1)
|
||||
assert_equal(14, CV_64FC2)
|
||||
assert_equal(22, CV_64FC3)
|
||||
assert_equal(30, CV_64FC4)
|
||||
|
||||
# Load image flags
|
||||
assert_equal(-1, CV_LOAD_IMAGE_UNCHANGED)
|
||||
assert_equal(0, CV_LOAD_IMAGE_GRAYSCALE)
|
||||
|
|
|
@ -38,11 +38,13 @@ class TestPointSet < OpenCVTestCase
|
|||
assert_equal(64, center.y.to_i)
|
||||
|
||||
size = box.size
|
||||
assert_in_delta(63.116, size.width, 0.001)
|
||||
assert_in_delta(63.116, size.height, 0.001)
|
||||
assert_in_delta(180, box.angle, 0.001)
|
||||
assert_in_delta(63, size.width, 1.0)
|
||||
assert_in_delta(63, size.height, 1.0)
|
||||
|
||||
assert_raise(CvStsBadArg) {
|
||||
angle = [box.angle, 180 - box.angle].min
|
||||
assert_in_delta(0, angle, 0.1)
|
||||
|
||||
assert_raise(CvStsBadSize) {
|
||||
@contour2.fit_ellipse2
|
||||
}
|
||||
end
|
||||
|
@ -102,7 +104,7 @@ class TestPointSet < OpenCVTestCase
|
|||
size = box.size
|
||||
assert_in_delta(63.356, size.width, 0.001)
|
||||
assert_in_delta(63.356, size.height, 0.001)
|
||||
assert_in_delta(-8.130, box.angle, 0.001)
|
||||
assert_in_delta(-81.30, box.angle, 1.0)
|
||||
|
||||
flunk('FIXME: Currently PointSet#min_area_rect2 causes segmentation fault when "self" is invalid.')
|
||||
assert_raise(CvStsBadSize) {
|
||||
|
|