OpenSeeFace/Source/SVMWrapper.cpp
2020-02-08 21:08:21 +01:00

192 lines
No EOL
5.8 KiB
C++

// SVMWrapper.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include <cmath>
#include "svm.h"
using namespace std;
extern "C" void __cdecl print_log(const char *str) {
return;
}
struct SVMWrapper {
struct svm_model *model;
int cols;
double *means;
double *sdevs;
struct svm_parameter param;
struct svm_problem *problem;
};
typedef struct svm_node svmnode;
svmnode **make_svmnode_array(float features[], int rows, int cols, double *means, double *sdevs, int rescale) {
svmnode **x = new svmnode*[rows];
svmnode *nodes = new svmnode[rows * (cols + 1)];
double row_factor = 1.0 / (double)rows;
if (rescale) {
for (int c = 0; c < cols; c++) {
means[c] = 0;
sdevs[c] = 0;
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
means[c] += (double)features[r * cols + c];
}
}
for (int c = 0; c < cols; c++) {
means[c] *= row_factor;
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
double sq_diff = ((double)features[r * cols + c] - means[c]);
sq_diff *= sq_diff;
sdevs[c] += sq_diff;
}
}
for (int c = 0; c < cols; c++) {
sdevs[c] *= row_factor;
sdevs[c] = sqrt(sdevs[c]);
sdevs[c] = 1.0 / sdevs[c];
}
}
for (int r = 0; r < rows; r++) {
x[r] = &(nodes[r * (cols + 1)]);
int idx = 0;
for (int c = 0; c < cols; c++) {
x[r][c].index = c + 1;
x[r][c].value = ((double)features[r * cols + c] - means[c]) * sdevs[c];
}
x[r][cols].index = -1;
}
return x;
}
void make_problem(struct svm_problem *problem, float features[], float labels[], int rows, int cols, double *means, double *sdevs) {
problem->l = rows;
problem->y = new double[rows];
for (int i = 0; i < rows; i++)
problem->y[i] = (double)labels[i];
problem->x = make_svmnode_array(features, rows, cols, means, sdevs, 1);
}
void destroy_svmnode_array(svmnode **x) {
delete x[0];
delete x;
}
void destroy_problem(struct svm_problem *problem) {
delete problem->y;
destroy_svmnode_array(problem->x);
}
extern "C" {
__declspec(dllexport) void *__cdecl trainModel(float features[], float labels[], int rows, int cols) {
if (!(rows > 0 && cols > 0))
return NULL;
svm_set_print_string_function(print_log);
struct SVMWrapper *sw = new SVMWrapper();
sw->cols = cols;
sw->means = new double[cols];
sw->sdevs = new double[cols];
sw->param.svm_type = C_SVC;
sw->param.kernel_type = RBF;
sw->param.degree = 3;
sw->param.gamma = 1.0 / (double)cols;
sw->param.coef0 = 0;
sw->param.nu = 0.5;
sw->param.cache_size = 100;
sw->param.C = 4;
sw->param.eps = 0.001;
sw->param.p = 0.1;
sw->param.shrinking = 1;
sw->param.probability = 0;
sw->param.nr_weight = 0;
sw->param.weight_label = NULL;
sw->param.weight = NULL;
sw->problem = new struct svm_problem();
make_problem(sw->problem, features, labels, rows, cols, sw->means, sw->sdevs);
sw->model = svm_train(sw->problem, &sw->param);
return sw;
}
__declspec(dllexport) void __cdecl predict(void *ptr, float features[], float predictions[], int rows) {
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
int cols = sw->cols;
svmnode **x = make_svmnode_array(features, rows, cols, sw->means, sw->sdevs, 0);
for (int r = 0; r < rows; r++)
predictions[r] = (float)svm_predict(sw->model, x[r]);
destroy_svmnode_array(x);
return;
}
__declspec(dllexport) void *__cdecl loadModel(char *filename, int cols, double means[], double sdevs[]) {
struct SVMWrapper *sw = new SVMWrapper();
sw->cols = cols;
sw->model = svm_load_model(filename);
sw->means = new double[cols];
sw->sdevs = new double[cols];
for (int c = 0; c < cols; c++) {
sw->means[c] = means[c];
sw->sdevs[c] = sdevs[c];
}
return sw;
}
__declspec(dllexport) void *__cdecl loadModelString(char *modelString, int cols, double means[], double sdevs[]) {
struct SVMWrapper *sw = new SVMWrapper();
sw->cols = cols;
sw->model = svm_load_model_string(modelString);
sw->means = new double[cols];
sw->sdevs = new double[cols];
for (int c = 0; c < cols; c++) {
sw->means[c] = means[c];
sw->sdevs[c] = sdevs[c];
}
sw->problem = NULL;
return sw;
}
__declspec(dllexport) void __cdecl getScales(void *ptr, double means[], double sdevs[]) {
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
int cols = sw->cols;
for (int c = 0; c < cols; c++) {
means[c] = sw->means[c];
sdevs[c] = sw->sdevs[c];
}
}
__declspec(dllexport) char *__cdecl getModel(void *ptr) {
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
return svm_save_model_string(sw->model);
}
__declspec(dllexport) int __cdecl saveModel(void *ptr, char *filename) {
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
return svm_save_model(filename, sw->model);
}
__declspec(dllexport) void __cdecl destroyModel(void *ptr) {
struct SVMWrapper *sw = (struct SVMWrapper *)ptr;
delete sw->means;
delete sw->sdevs;
svm_free_and_destroy_model(&sw->model);
if (sw->problem != NULL) {
destroy_problem(sw->problem);
delete sw->problem;
}
delete sw;
}
}