mirror of
https://github.com/ruby-opencv/ruby-opencv
synced 2023-03-27 23:22:12 -04:00
add minimal functions of EigenFaces
This commit is contained in:
parent
2ffd26a887
commit
336e9c4ad2
7 changed files with 250 additions and 4 deletions
|
@ -109,6 +109,8 @@ ext/opencv/cvutils.cpp
|
||||||
ext/opencv/cvutils.h
|
ext/opencv/cvutils.h
|
||||||
ext/opencv/cvvideowriter.cpp
|
ext/opencv/cvvideowriter.cpp
|
||||||
ext/opencv/cvvideowriter.h
|
ext/opencv/cvvideowriter.h
|
||||||
|
ext/opencv/eigenfaces.cpp
|
||||||
|
ext/opencv/eigenfaces.h
|
||||||
ext/opencv/gui.cpp
|
ext/opencv/gui.cpp
|
||||||
ext/opencv/gui.h
|
ext/opencv/gui.h
|
||||||
ext/opencv/iplconvkernel.cpp
|
ext/opencv/iplconvkernel.cpp
|
||||||
|
@ -216,6 +218,7 @@ test/test_cvsurfpoint.rb
|
||||||
test/test_cvtermcriteria.rb
|
test/test_cvtermcriteria.rb
|
||||||
test/test_cvtwopoints.rb
|
test/test_cvtwopoints.rb
|
||||||
test/test_cvvideowriter.rb
|
test/test_cvvideowriter.rb
|
||||||
|
test/test_eigenfaces.rb
|
||||||
test/test_iplconvkernel.rb
|
test/test_iplconvkernel.rb
|
||||||
test/test_iplimage.rb
|
test/test_iplimage.rb
|
||||||
test/test_mouseevent.rb
|
test/test_mouseevent.rb
|
||||||
|
|
143
ext/opencv/eigenfaces.cpp
Normal file
143
ext/opencv/eigenfaces.cpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/************************************************************
|
||||||
|
|
||||||
|
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;
|
||||||
|
std::map<long, cv::Ptr<cv::FaceRecognizer> > ptr_guard_map;
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_class()
|
||||||
|
{
|
||||||
|
return rb_klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release_facerecognizer(void *ptr) {
|
||||||
|
long key = (long)ptr;
|
||||||
|
ptr_guard_map[key].release();
|
||||||
|
ptr_guard_map.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_allocate(VALUE klass)
|
||||||
|
{
|
||||||
|
return Data_Wrap_Struct(klass, 0, release_facerecognizer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
long key = (long)(DATA_PTR(self));
|
||||||
|
ptr_guard_map[key] = ptr; // To avoid cv::Ptr's GC
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
try {
|
||||||
|
label = self_ptr->predict(mat);
|
||||||
|
}
|
||||||
|
catch (cv::Exception& e) {
|
||||||
|
raise_cverror(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return INT2NUM(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
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", rb_cObject);
|
||||||
|
rb_define_alloc_func(rb_klass, rb_allocate);
|
||||||
|
rb_define_private_method(rb_klass, "initialize", RUBY_METHOD_FUNC(rb_initialize), -1);
|
||||||
|
rb_define_method(rb_klass, "train", RUBY_METHOD_FUNC(rb_train), 2);
|
||||||
|
rb_define_method(rb_klass, "predict", RUBY_METHOD_FUNC(rb_predict), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__NAMESPACE_END_EIGENFACES
|
||||||
|
__NAMESPACE_END_OPENCV
|
||||||
|
|
42
ext/opencv/eigenfaces.h
Normal file
42
ext/opencv/eigenfaces.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/************************************************************
|
||||||
|
|
||||||
|
eigenfacerecognizer.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_allocate(VALUE klass);
|
||||||
|
VALUE rb_initialize(int argc, VALUE argv[], VALUE self);
|
||||||
|
VALUE rb_train(VALUE self, VALUE src, VALUE labels);
|
||||||
|
|
||||||
|
__NAMESPACE_END_EIGENFACES
|
||||||
|
|
||||||
|
inline cv::FaceRecognizer*
|
||||||
|
FACERECOGNIZER(VALUE object)
|
||||||
|
{
|
||||||
|
cv::FaceRecognizer *ptr;
|
||||||
|
Data_Get_Struct(object, cv::FaceRecognizer, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
__NAMESPACE_END_OPENCV
|
||||||
|
|
||||||
|
#endif // RUBY_OPENCV_EIGENFACES_H
|
||||||
|
|
||||||
|
|
|
@ -706,6 +706,9 @@ extern "C" {
|
||||||
mOpenCV::cCvConnectedComp::define_ruby_class();
|
mOpenCV::cCvConnectedComp::define_ruby_class();
|
||||||
mOpenCV::cCvAvgComp::define_ruby_class();
|
mOpenCV::cCvAvgComp::define_ruby_class();
|
||||||
mOpenCV::cCvHaarClassifierCascade::define_ruby_class();
|
mOpenCV::cCvHaarClassifierCascade::define_ruby_class();
|
||||||
|
|
||||||
|
mOpenCV::cEigenFaces::define_ruby_class();
|
||||||
|
|
||||||
mOpenCV::mGUI::define_ruby_module();
|
mOpenCV::mGUI::define_ruby_module();
|
||||||
mOpenCV::mGUI::cWindow::define_ruby_class();
|
mOpenCV::mGUI::cWindow::define_ruby_class();
|
||||||
mOpenCV::mGUI::cTrackbar::define_ruby_class();
|
mOpenCV::mGUI::cTrackbar::define_ruby_class();
|
||||||
|
|
|
@ -130,6 +130,8 @@ extern "C" {
|
||||||
|
|
||||||
#include "cvfeaturetree.h"
|
#include "cvfeaturetree.h"
|
||||||
|
|
||||||
|
#include "eigenfaces.h"
|
||||||
|
|
||||||
// GUI
|
// GUI
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
File diff suppressed because one or more lines are too long
53
test/test_eigenfaces.rb
Executable file
53
test/test_eigenfaces.rb
Executable file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# -*- mode: ruby; coding: utf-8-unix -*-
|
||||||
|
require 'test/unit'
|
||||||
|
require 'opencv'
|
||||||
|
require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
||||||
|
|
||||||
|
include OpenCV
|
||||||
|
|
||||||
|
# Tests for OpenCV::EigenFaces
|
||||||
|
class TestEigenFaces < OpenCVTestCase
|
||||||
|
def setup
|
||||||
|
@eigenfaces = EigenFaces.new
|
||||||
|
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
|
||||||
|
img = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)
|
||||||
|
assert_nil(@eigenfaces.train([img], [1]))
|
||||||
|
|
||||||
|
assert_raise(TypeError) {
|
||||||
|
@eigenfaces.train(DUMMY_OBJ, [1])
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_raise(TypeError) {
|
||||||
|
@eigenfaces.train([img], DUMMY_OBJ)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_predict
|
||||||
|
img = CvMat.load(FILENAME_LENA256x256, CV_LOAD_IMAGE_GRAYSCALE)
|
||||||
|
label = 1
|
||||||
|
@eigenfaces.train([img], [label])
|
||||||
|
assert_equal(label, @eigenfaces.predict(img))
|
||||||
|
|
||||||
|
assert_raise(TypeError) {
|
||||||
|
@eigenfaces.predict(DUMMY_OBJ)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue