-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
647 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
|
||
VLFEATDIR=$(TMPDIR)/vlfeat | ||
ENCEVALDIR=$(TMPDIR)/enceval | ||
|
||
VLFEATURL = "http://www.vlfeat.org/download/vlfeat-0.9.20-bin.tar.gz" | ||
ENCEVALURL = "http://www.robots.ox.ac.uk/~vgg/software/enceval_toolkit/downloads/enceval-toolkit-1.1.tar.gz" | ||
|
||
CC = g++ | ||
CFLAGS = -O2 | ||
|
||
#Auto-detect architecture | ||
Darwin_x86_64_ARCH := maci64 | ||
Linux_x86_64_ARCH := glnxa64 | ||
|
||
UNAME := $(shell uname -sm) | ||
VLARCH ?= $($(shell echo "$(UNAME)" | tr \ _)_ARCH) | ||
|
||
VLFEATOBJ = $(VLFEATDIR)/vlfeat-0.9.20/bin/$(VLARCH)/objs | ||
|
||
#Set dynamic lib extension for architecture | ||
Darwin_x86_64_EXT := jnilib | ||
Linux_x86_64_EXT := so | ||
|
||
SOEXT ?= $($(shell echo "$(UNAME)" | tr \ _)_EXT) | ||
|
||
#Set java extension for architecture | ||
Darwin_x86_64_JAVA := darwin | ||
Linux_x86_64_JAVA := linux | ||
|
||
JAVAEXT ?= $($(shell echo "$(UNAME)" | tr \ _)_JAVA) | ||
|
||
SRCDIR := src/main/cpp | ||
|
||
ODIR = $(TMPDIR)/obj | ||
LDIR = lib | ||
|
||
_OBJ = siftExtractor.o fisherExtractor.o | ||
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) | ||
|
||
_EVDEPS = gmm.o fisher.o stat.o simd_math.o | ||
EVDEPS = $(patsubst %,$(ENCEVALDIR)/%,$(_EVDEPS)) | ||
|
||
VLDEPS = $(shell find $(VLFEATOBJ) -type f -name '*.o') | ||
|
||
all: $(LDIR)/libImageEncoders.$(SOEXT) | ||
|
||
$(VLFEATDIR): | ||
mkdir -p $(VLFEATDIR) | ||
wget $(VLFEATURL) -O $(VLFEATDIR)/vlfeat.tgz | ||
cd $(VLFEATDIR) && tar zxvf $(VLFEATDIR)/vlfeat.tgz | ||
|
||
$(ENCEVALDIR): | ||
mkdir -p $(ENCEVALDIR) | ||
wget $(ENCEVALURL) -O $(ENCEVALDIR)/enceval.tgz | ||
cd $(ENCEVALDIR) && tar zxvf enceval.tgz | ||
|
||
vlfeat: $(VLFEATDIR) | ||
make -C $(VLFEATDIR)/vlfeat-0.9.20 ARCH=$(VLARCH) bin-all | ||
|
||
$(ENCEVALDIR)/%.o: $(ENCEVALDIR)/lib/gmm-fisher/%.cxx | ||
$(CC) -c -o $@ $< $(CFLAGS) | ||
|
||
$(ODIR)/%.o: $(SRCDIR)/%.cxx $(ENCEVALDIR) $(VLFEATDIR) | ||
$(CC) -I$(ENCEVALDIR)/lib/gmm-fisher -I$(VLFEATDIR)/vlfeat-0.9.20 -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/$(JAVAEXT) -c -o $@ $< $(CFLAGS) | ||
|
||
$(LDIR)/libImageEncoders.$(SOEXT): $(OBJ) $(EVDEPS) vlfeat | ||
$(CC) -dynamiclib -o $@ $(OBJ) $(EVDEPS) $(VLDEPS) $(CFLAGS) | ||
|
||
.PHONY: clean vlfeat | ||
|
||
clean: | ||
rm -f $(LDIR)/libImageEncoder.$(SOEXT) | ||
rm -rf $(VLFEATDIR) $(ENCEVALDIR) $(ODIR) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/** @internal | ||
** @file FisherExtractor.cxx | ||
** @author Evan Sparks | ||
** @brief JNI Wrapper for enceval GMM and Fisher Vector | ||
**/ | ||
|
||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <assert.h> | ||
#include <ctype.h> | ||
#include <string.h> | ||
#include <iostream> | ||
#include <fstream> | ||
|
||
#include <gmm.h> | ||
#include <fisher.h> | ||
|
||
#include "fisher_handle.h" | ||
#include "siftExtractor.h" | ||
|
||
JNIEXPORT jfloatArray JNICALL Java_extLibrary_SIFTExtractor_calcAndGetFVs( | ||
JNIEnv* env, | ||
jobject obj, | ||
jfloatArray means, | ||
jint n_dim, | ||
jint n_gauss, | ||
jfloatArray covariances, | ||
jfloatArray priors, | ||
jfloatArray dsiftdescriptors) | ||
{ | ||
printf("Calling 'calcAndGetFVs', starting...\n"); | ||
fflush(stdout); | ||
// get C/C++ access to the JNI input data | ||
jsize means_length = env->GetArrayLength(means); | ||
jfloat* means_body = env->GetFloatArrayElements(means, 0); | ||
jsize covar_length = env->GetArrayLength(covariances); | ||
jfloat* covar_body = env->GetFloatArrayElements(covariances, 0); | ||
jsize prior_length = env->GetArrayLength(priors); | ||
jfloat* prior_body = env->GetFloatArrayElements(priors, 0); | ||
jsize descs_length = env->GetArrayLength(dsiftdescriptors)/n_dim; | ||
jfloat* descs_body = env->GetFloatArrayElements(dsiftdescriptors, 0); | ||
|
||
printf("means : %i, covars %i, priors %i, descs %i, \n", means_length, covar_length, prior_length, descs_length); | ||
printf("means : %i, covars %i, priors %i, descs %i, \n", | ||
means_length/n_gauss, covar_length/n_gauss, prior_length, descs_length); | ||
fflush(stdout); | ||
|
||
float * fk = 0; | ||
// malloc the result | ||
jsize fvenc_length = 2 * n_dim * n_gauss; | ||
fk = (float*) malloc( sizeof(float) * fvenc_length); | ||
printf("Allocating result vector of size %d, n_dim %d, n_gauss %d\n", fvenc_length, n_dim, n_gauss); | ||
|
||
if ( fk == NULL ) { | ||
printf("Error allocating memory for the FVenc buffer\n"); | ||
fflush(stdout); | ||
exit(-1); | ||
} | ||
|
||
// ## comput the fisher vector... ####### | ||
// *** This is all just part of the if("init") from the MEX ********************* | ||
// convert GMM field arrays to vectors | ||
printf("input to vectors\n"); | ||
fflush(stdout); | ||
std::vector<float*> mean(n_gauss); | ||
std::vector<float*> variance(n_gauss); | ||
for (int j = 0; j < n_gauss; ++j) { | ||
mean[j] = &means_body[j*n_dim]; | ||
variance[j] = &covar_body[j*n_dim]; | ||
} | ||
std::vector<float> coef(prior_body, prior_body + n_gauss); | ||
|
||
// prepare a GMM model with data from the structure | ||
gaussian_mixture<float> gmmproc(n_gauss,n_dim); | ||
printf("make gmm\n"); | ||
fflush(stdout); | ||
gmmproc.set(mean, variance, coef); | ||
|
||
// construct a c++ struct with default parameter values | ||
// in the Mex the settings are sent as a third variable, we stick to defaults. | ||
fisher_param fisher_encoder_params; | ||
fisher_encoder_params.alpha = 1.0f; | ||
fisher_encoder_params.pnorm = 0.0f; | ||
|
||
fisher_encoder_params.print(); | ||
|
||
// What is the role of this fhisher_handle.. can we perhaps keep it between calls.. (save time)? | ||
printf("make handle \n"); | ||
fflush(stdout); | ||
fisher_handle<float> fisher_encoder(gmmproc,fisher_encoder_params); | ||
// initialise encoder with a GMM model (vocabulary) | ||
printf(".. and set gmm model to handle \n"); | ||
fflush(stdout); | ||
fisher_encoder.set_model(gmmproc); | ||
|
||
// ************************************* end of if ("init") in the MEX ********** | ||
|
||
// *** else if ("encode") from the Mex ******************************************* | ||
// in the mex they get the fisher_handle we computed above sent.. so we can skip that :) | ||
// MEXCODE: fisher_handle<float> *fisher_encoder = convertMat2Ptr<float>(prhs[1]); | ||
// Next they get the matrix of descriptors to encode.. as a damm vector :( | ||
// convert input vectors to c++ std::vector format | ||
printf("descriptors to vector \n"); | ||
printf("descriptors length: %d\n", descs_length); | ||
fflush(stdout); | ||
std::vector<float*> x(descs_length); | ||
|
||
for (int j = 0; j < descs_length; ++j) { | ||
x[j] = &descs_body[j*n_dim]; | ||
} | ||
|
||
bool weights = false; | ||
// load in weights if specified | ||
// do encoding | ||
|
||
printf("encode without weights \n"); | ||
fflush(stdout); | ||
fisher_encoder.compute(x, fk); | ||
|
||
// ************************************* end of else if ("encode") in the Mex **** | ||
|
||
jfloatArray result = env->NewFloatArray(fvenc_length); | ||
if (result == NULL) { | ||
printf("Error geting memory in the JNI for the result fisher vector\n"); | ||
fflush(stdout); | ||
return NULL; | ||
} | ||
// get a pointer to the new array | ||
printf("Copy to JNI return memory\n"); | ||
fflush(stdout); | ||
env->SetFloatArrayRegion(result, 0, fvenc_length, fk); | ||
printf("Calling free on fvenc\n"); | ||
fflush(stdout); | ||
|
||
env->ReleaseFloatArrayElements(means, means_body, 0); | ||
env->ReleaseFloatArrayElements(covariances, covar_body, 0); | ||
env->ReleaseFloatArrayElements(priors, prior_body, 0); | ||
env->ReleaseFloatArrayElements(dsiftdescriptors, descs_body, 0); | ||
free(fk); | ||
return result; | ||
} | ||
|
||
|
||
JNIEXPORT jfloatArray JNICALL Java_extLibrary_SIFTExtractor_computeGMM( | ||
JNIEnv * env, | ||
jobject obj, | ||
jint n_gauss, | ||
jint n_dim, | ||
jfloatArray gmm_samples) | ||
{ | ||
//For now this returns everything as one big fat array. This is absolutely disgusting. | ||
|
||
//Get samples from Java. | ||
jsize n_samples = env->GetArrayLength(gmm_samples)/n_dim; | ||
jfloat* samples_body = env->GetFloatArrayElements(gmm_samples, 0); | ||
|
||
//Copy to C vectors. We assume things come at us sample at a time. | ||
std::vector<float*> samples(n_samples); | ||
for (int i = 0; i < n_samples; ++i) { | ||
samples[i] = &samples_body[i*n_dim]; | ||
} | ||
|
||
//Create a default empty gmm parameter set. | ||
em_param gmm_params; | ||
gaussian_mixture<float> gmmproc(gmm_params, n_gauss, n_dim); | ||
|
||
//We don't yet accept initial means/variances/coefs yet. | ||
int seed = 42; | ||
//int seed = time(NULL); | ||
gmmproc.random_init(samples, seed); | ||
|
||
//Run EM. | ||
gmmproc.em(samples); | ||
|
||
//Copy final stuff back out. | ||
int meanResSize = n_gauss*n_dim; | ||
int varResSize = n_gauss*n_dim; | ||
int coefResSize = n_gauss; | ||
int totalResSize = meanResSize + varResSize + coefResSize; | ||
|
||
//Allocate output arrays. | ||
float* meanRes = (float *) malloc(meanResSize*sizeof (float)); //array of size(ndim,ngauss) | ||
float* varRes = (float *) malloc(varResSize*sizeof (float)); //array of size(ndim,ngauss) | ||
float* coefRes = (float *) malloc(coefResSize*sizeof (float)); //array of size(ndim) | ||
|
||
for (int j = 0; j < n_gauss; ++j) { | ||
float* componentmean = gmmproc.get_mean(j); | ||
float* componentvariance = gmmproc.get_variance(j); | ||
|
||
for (int i = 0; i < n_dim; ++i) { | ||
printf("%d,", i); | ||
fflush(stdout); | ||
meanRes[i+j*n_dim] = componentmean[i]; | ||
varRes[i+j*n_dim] = componentvariance[i]; | ||
} | ||
|
||
coefRes[j] = gmmproc.get_mixing_coefficients(j); | ||
} | ||
|
||
//Copy the results back to Java land. | ||
jfloatArray result = env->NewFloatArray(totalResSize); | ||
env->SetFloatArrayRegion(result, 0, meanResSize, meanRes); | ||
env->SetFloatArrayRegion(result, meanResSize, varResSize, varRes); | ||
env->SetFloatArrayRegion(result, meanResSize+varResSize, coefResSize, coefRes); | ||
|
||
//Cleanup structs created; | ||
free(meanRes); | ||
meanRes = NULL; | ||
|
||
free(varRes); | ||
varRes = NULL; | ||
|
||
free(coefRes); | ||
coefRes = NULL; | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
/// \Class fisher_handle fisher_handle.h "fisher_handle.h" | ||
/// | ||
/// \brief | ||
/// | ||
/// \version 1.0 | ||
/// \author Ken Chatfield | ||
/// \date 08/07/2011 | ||
|
||
#ifndef __FISHER_HANDLE_H | ||
#define __FISHER_HANDLE_H | ||
|
||
#include <fisher.h> | ||
#include <gmm.h> | ||
#include <stdint.h> | ||
|
||
#define CLASS_HANDLE_SIGNATURE 0xa5a50f0f | ||
template<class T> class fisher_handle: public fisher<T> | ||
{ | ||
public: | ||
fisher_handle(gaussian_mixture<T> &gmm, fisher_param params): fisher<T>(params) { signature = CLASS_HANDLE_SIGNATURE; gmmproc = &gmm; } | ||
~fisher_handle() { signature = 0; } | ||
bool isValid() { return (signature == CLASS_HANDLE_SIGNATURE); } | ||
gaussian_mixture<T>* getGmmPtr() { return gmmproc; } | ||
private: | ||
uint32_t signature; | ||
gaussian_mixture<T> *gmmproc; | ||
}; | ||
|
||
#endif |
Oops, something went wrong.