JNI

1. JNI

Carolini
carolini

(usa Ubuntu)

Enviado em 24/03/2013 - 16:27h

Estou tentando usar o jni para integrar c++ com java pelo terminal linux, contudo estou tentando o seguinte erro:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/carolini/svn/application/polen/src/bow/codigo_fonte/Arff/src/libolanativo.so: /home/carolini/svn/application/polen/src/bow/codigo_fonte/Arff/src/libolanativo.so: undefined symbol: _ZNK2cv15FeatureDetector6detectERKSt6vectorINS_3MatESaIS2_EERS1_IS1_INS_8KeyPointESaIS7_EESaIS9_EES6_
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
at java.lang.Runtime.loadLibrary0(Runtime.java:840)
at java.lang.System.loadLibrary(System.java:1047)
at CriarArff.<clinit>(CriarArff.java:7)
Could not find the main class: CriarArff. Program will exit.

estou seguindo esse site para fazer:

http://eupodiatamatando.com/estudos/tutorial-jni/

Eu não tenho certeza se estou fazendo certo pois, estou colocando JNIEXPORT void JNICALL Java_OlaMundo_diga (JNIEnv * env, jobject jobj){} no lugar da minha main, ele gera a biblioteca porém não consigo linkar....


Agradeço se puderem me ajudar ok!






  


2. Re: JNI

???
gokernel

(usa Linux Mint)

Enviado em 25/03/2013 - 07:45h

nao entendi direito .

vc consegue gerar o arquivo ( .so ou .dll ) ???

se a resposta for positiva, tente copiar o arquivo ( .so ) para a pasta /usr/lib

informe mais detalhes ...


3. Re: JNI

Carolini
carolini

(usa Ubuntu)

Enviado em 25/03/2013 - 16:42h

Sim, ele gera o .so. Eu movi o arquivo e continua com o erro.
Creio que eu esteja fazendo errado no código c++.

Esse é código:


#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/ml/ml.hpp"

#include "cv.h"
#include "cxcore.h"
#include "math.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <time.h>
#include <sys/stat.h>
#include <pthread.h>
#include <errno.h>
#include "CriarArff.h"


using namespace cv;
using namespace std;





//-------------------------------------------------------------------------------------------------------------------------
//--- Global Variables

const char configFileName[] = "../data/config.xml";


// All these variable will be read from data/config.xml file
int numberOfClasses = 3; // Will be calculated automatically from the number of subfolders in the images folder
int kindOfIncrement = 0; // 0 = Linear Increment 1 = Exponential Increment
int defaultDictionarySize = 26; // Size of the dictionary
int incrementDictionarySize = 3; // Add this number to the default Dictionary Size for the next execution (usefull for batch experiments) if kindOfIncrement = 0 (linear), but if kindOfIncrement = 1 (exponential), the size of dictionary will be multiplied by incrementDictionarySize

// Configure Machine Learning Related Stuff
string dataSetName = "vogais"; // You must change the config.xml to insert the name of the dataset
string detectorType = "SURF";
string descriptorType = "SURF";
string matcherType = "FlannBased";

string fileWithTrainImageNames = "../data/"+dataSetName+"/train.txt";
string fileWithClassesNames = "../data/"+dataSetName+"/classes.txt";
string dirWithImages = "../data/"+dataSetName+"/images";
string arffFileName = "../data/"+dataSetName+"/dataset.arff";




//-------------------------------------------------------------------------------------------------------------------------
//--- Auxiliary Functions Declarations. See functions definitions for help

void adjustFileNames(void);
int getClassNumber(String fileImageName, vector<String> classesNames);
bool fexists(const char *filename);
bool initializeImagesAndClassesNames(vector<string>& classesNames);
void saveTrainingImage(IplImage * src, int i,int imageClass);
void saveConfiguration(void);
void readConfiguration(void);
bool createDetectorDescriptorMatcher( const string& detectorType, const string& descriptorType, const string& matcherType,
Ptr<FeatureDetector>& featureDetector,
Ptr<DescriptorExtractor>& descriptorExtractor,
Ptr<DescriptorMatcher>& descriptorMatcher );
void readFilenames( const string& filename, string& dirName, vector<string>& trainFilenames );
bool readImages( const string& trainFilename,
vector <Mat>& trainImages, vector<string>& trainImageNames );
void detectKeypoints( const Mat& queryImage, vector<KeyPoint>& queryKeypoints,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints,
Ptr<FeatureDetector>& featureDetector );
void computeDescriptors( const Mat& queryImage, vector<KeyPoint>& queryKeypoints, Mat& queryDescriptors,
const vector<Mat>& trainImages, vector<vector<KeyPoint> >& trainKeypoints, vector<Mat>& trainDescriptors,
Ptr<DescriptorExtractor>& descriptorExtractor );






/* Class: Bow
* Description: Incapsulate some of the BOW functions
* Functionalities:
- Create and maitain a vocabulary
*/
class Bow {

public:


BOWKMeansTrainer * bowTrainer;
BOWImgDescriptorExtractor * bowDE;
Ptr<FeatureDetector> bowFeatureDetector;

Ptr<DescriptorExtractor> descriptorExtractor;
Ptr<DescriptorMatcher> descriptorMatcher;


int dictionarySize;
Mat dictionary;

Bow() {
dictionarySize = defaultDictionarySize;
TermCriteria tc(CV_TERMCRIT_ITER,100,0.001);
int retries=1;
int flags=KMEANS_PP_CENTERS;
bowTrainer = new BOWKMeansTrainer(dictionarySize, tc, retries, flags );
}


void createVocabulary(vector<Mat>& descriptors) {
for ( int i = 0; i < descriptors.size(); ++i) {
Mat descriptor = descriptors[i];
for ( int j = 0; j < descriptor.rows; ++j) {
bowTrainer->add(descriptor.row(j));
}
}
dictionary = bowTrainer->cluster();
};

void setAuxiliaryAlgorithms(Ptr<DescriptorExtractor> extractor, Ptr<DescriptorMatcher> matcher,Ptr<FeatureDetector> feature) {
bowFeatureDetector = feature;
descriptorExtractor = extractor;
descriptorMatcher = matcher;
bowDE = new BOWImgDescriptorExtractor(extractor,matcher);
bowDE->setVocabulary(dictionary);
}

};











/* Class: Weka
* Description: Use weka to learn and classify
* Functionalities:
* - Generate and ARFF file with all dataset using BoW features
* - Call weka with the name of the classifier as a parameter [NOT IMPLEMENTED YET] *
* - Use weka results to classify the query image [NOET IMPLEMENTED YET]
*/
class Weka {

public:

String fileName;
int dictionarySize;
ofstream out; // output file

BOWImgDescriptorExtractor * bowDE;
Ptr<FeatureDetector> bowFeatureDetector;
Ptr<DescriptorExtractor> descriptorExtractor;
Ptr<DescriptorMatcher> descriptorMatcher;

Weka() {
fileName = arffFileName;
dictionarySize = defaultDictionarySize;
}
~Weka() {
out.close();
String command = "rm " + fileWithTrainImageNames + "; rm " + fileWithClassesNames + "; rm temp.txt";
system(command.c_str());


}



void setAuxiliaryAlgorithms(Ptr<DescriptorExtractor> extractor, Ptr<DescriptorMatcher> matcher,Ptr<FeatureDetector> feature, Mat dictionary) {
bowFeatureDetector = feature;
descriptorExtractor = extractor;
descriptorMatcher = matcher;
bowDE = new BOWImgDescriptorExtractor(extractor,matcher);
bowDE->setVocabulary(dictionary);
}

void insertArfffHeader(vector<String> classesNames) {

char dicSize[6];
sprintf(dicSize,"%02d",defaultDictionarySize);

out.open(fileName.c_str());
out << "% ARFF containing Bow Feature for all " << dataSetName << " images" << endl;
out << endl;
out << "@relation " << dataSetName+"_Dic"+dicSize << endl;
out << endl;
for ( int i = 0; i < dictionarySize; ++i) {
out << "@attribute A" << i+1 << " numeric" << endl;
}
out << "@attribute class {";
for ( int i = 0; i < classesNames.size()-1; ++i) {
out << classesNames[i] << ",";
}
out << classesNames[classesNames.size()-1] << "}" << endl;
out << endl;
out << "@data" << endl;
}


void insertArffInstance(Mat bowDescriptor, String className) {

double binValue;
for ( int i = 0; i < bowDescriptor.rows; ++i) {
Mat row = bowDescriptor.row(i);
for ( int j = 0; j < row.cols; ++j) {
binValue = row.data[j];
out << binValue << ",";
}
}
out << className << endl;
}

void insertArffInstance(Mat image, String imageFileName, vector<String> classesNames) {
int classIndex = getClassNumber(imageFileName,classesNames);
String className = classesNames[classIndex];
vector<KeyPoint> keypoints;
bowFeatureDetector->detect(image,keypoints);
Mat bowDescriptor;
bowDE->compute(image,keypoints,bowDescriptor);

insertArffInstance(bowDescriptor, className);
}

void insertArffInstances(vector<Mat>& trainImages, vector<String>& trainImagesNames, vector<String>& classesNames) {
insertArfffHeader(classesNames);
for ( int i = 0; i < trainImages.size(); ++i ) {
insertArffInstance(trainImages[i],trainImagesNames[i],classesNames);
}
}

void closeArff() {
out.close();

}
};












//-------------------------------------------------------------------------------------------------------------------------
//--- Main

JNIEXPORT jint JNICALL Java_CriarArff_diga (JNIEnv *, jobject){
readConfiguration();



Ptr<FeatureDetector> featureDetector;
Ptr<DescriptorExtractor> descriptorExtractor;
Ptr<DescriptorMatcher> descriptorMatcher;

Bow bow;
Weka weka;


vector<Mat> trainImages;
vector<string> trainImageNames;
vector<string> classesNames;
vector<vector<KeyPoint> > trainKeypoints;
vector<Mat> trainDescriptors;

if ( !createDetectorDescriptorMatcher( detectorType, descriptorType, matcherType, featureDetector, descriptorExtractor, descriptorMatcher ) )
{
cout << "Problems to create detector or extractor ..." << endl;
return -1;
}



cout << "Reading images ..." << endl;
initializeImagesAndClassesNames(classesNames);
readImages( fileWithTrainImageNames, trainImages, trainImageNames );
cout << "Detecting keypoints using " << detectorType << " ..." << endl;
featureDetector->detect( trainImages, trainKeypoints );
cout << "Describing keypoints using " << descriptorType << " ..." << endl;
descriptorExtractor->compute( trainImages, trainKeypoints, trainDescriptors );



cout << "Creating vocabulary with size = " << defaultDictionarySize << endl;
bow.createVocabulary(trainDescriptors);
weka.setAuxiliaryAlgorithms(descriptorExtractor,descriptorMatcher,featureDetector,bow.dictionary);
weka.insertArffInstances(trainImages,trainImageNames,classesNames);
weka.closeArff();
cout << "Arff created and saved in " << arffFileName << endl;


saveConfiguration();

return 0;

}




// Return the index of the class from the name of the training image
int getClassNumber(String fileImageName, vector<String> classesNames) {
for (int i = 0; i < classesNames.size();++i) {
int res = fileImageName.find("/"+classesNames[i]+"/",0);
if (res > 0) {
return i;
}
}
cout << "Problem finding the class name inside trainImageName";
}



// Test if a file exist
bool fexists(const char *filename)
{
ifstream ifile(filename);
return ifile;
}


// Randomly select the training and testing images. Extract classes names from folder names
bool initializeImagesAndClassesNames(vector<string>& classesNames) {

// This command will list all folders in the images folder this way getting the classes names automatically
string command = "ls " + dirWithImages + " > " + fileWithClassesNames;
system(command.c_str());

string dirName;
readFilenames( fileWithClassesNames, dirName, classesNames );
if ( classesNames.empty() )
{
cout << "Could not generate classes names from directories names." << endl << ">" << endl;
return false;
}

numberOfClasses = classesNames.size();

command = "echo -n > " + fileWithTrainImageNames;
system(command.c_str());


for ( size_t i = 0; i < classesNames.size(); i++ )
{
command = "ls " + dirWithImages + "/" + classesNames[i] + " > " + "temp.txt";
system(command.c_str());

vector<string> classesFiles;
readFilenames( "temp.txt" , dirName, classesFiles );


for ( size_t j = 0; j < classesFiles.size(); j++ )
{
command = "echo " + dirWithImages + "/" + classesNames[i] + "/" ;
command += classesFiles[j] + " >> " + fileWithTrainImageNames;
system(command.c_str());

}

}
return true;
}





//------------------------------------------------------------------------------------------------
// Create feature detector, descritor extractor and the descriptor matcher
bool createDetectorDescriptorMatcher( const string& detectorType, const string& descriptorType, const string& matcherType,
Ptr<FeatureDetector>& featureDetector,
Ptr<DescriptorExtractor>& descriptorExtractor,
Ptr<DescriptorMatcher>& descriptorMatcher )
{
initModule_nonfree();
featureDetector = FeatureDetector::create( detectorType );
descriptorExtractor = DescriptorExtractor::create( descriptorType );
descriptorMatcher = DescriptorMatcher::create( matcherType );
cout << ">" << endl;

bool isCreated = !( featureDetector.empty() || descriptorExtractor.empty() || descriptorMatcher.empty() );
if ( !isCreated )
if( featureDetector.empty()) cout << "Can not create feature detector of given types." << endl << ">" << endl;
if( descriptorExtractor.empty()) cout << "Can not create descriptor extractor of given types." << endl << ">" << endl;
if( descriptorMatcher.empty()) cout << "Can not create descriptor matcher of given types." << endl << ">" << endl;

return isCreated;
}






//------------------------------------------------------------------------------------------------
// Read the txt file containing all the image names and put the names in a vector
void readFilenames( const string& filename, string& dirName, vector<string>& trainFilenames )
{
const char dlmtr = '/';

trainFilenames.clear();

ifstream file( filename.c_str() );
if ( !file.is_open() )
return;

size_t pos = filename.rfind(dlmtr);
dirName = pos == string::npos ? "" : filename.substr(0, pos) + dlmtr;
while ( !file.eof() )
{
string str;
getline( file, str );
if ( str.empty() ) break;
trainFilenames.push_back(str);
}
file.close();
}





//------------------------------------------------------------------------------------------------
// Read the training or testing images to a vector
bool readImages( const string& trainFilename,
vector <Mat>& trainImages, vector<string>& trainImageNames )
{
string trainDirName;
trainImages.clear();
readFilenames( trainFilename, trainDirName, trainImageNames );
if ( trainImageNames.empty() )
{
cout << "Train image filenames can not be read." << endl << ">" << endl;
return false;
}
int readImageCount = 0;

for ( size_t i = 0; i < trainImageNames.size(); i++ )
{
string filename = trainImageNames[i];
Mat img = imread( filename, CV_LOAD_IMAGE_GRAYSCALE );
if ( img.empty() )
cout << "Train image " << filename << " can not be read." << endl;
else
readImageCount++;
trainImages.push_back( img );
}
if ( !readImageCount )
{
cout << "All train or test images can not be read." << endl << ">" << endl;
return false;
}
else
cout << readImageCount << " images read from " << trainFilename << endl;

return true;
}







//-------------------------------------------------------------------------------------------------
// Adjust the file names
void adjustFileNames() {
fileWithTrainImageNames = "../data/"+dataSetName+"/train.txt";
fileWithClassesNames = "../data/"+dataSetName+"/classes.txt";
dirWithImages = "../data/"+dataSetName+"/images";

char dicSize[6];
sprintf(dicSize,"%02d",defaultDictionarySize);
arffFileName = "../data/"+dataSetName+"/"+dataSetName+"_Dic"+dicSize+".arff";

}
void cvDestroyAllWindows(void);


//-------------------------------------------------------------------------------------------------
// Save configuration parameters on disk
void saveConfiguration(void) {

CvFileStorage* fs=cvOpenFileStorage(configFileName, 0,CV_STORAGE_WRITE);

cvWriteString( fs, "dataSetName", dataSetName.c_str());
cvWriteInt( fs, "incrementDictionarySize", incrementDictionarySize);
cvWriteInt( fs, "kindOfIncrement", kindOfIncrement);

if(kindOfIncrement == 0) {
cvWriteInt( fs, "defaultDictionarySize", defaultDictionarySize + incrementDictionarySize);
} else {
cvWriteInt( fs, "defaultDictionarySize", defaultDictionarySize * incrementDictionarySize);
}
cvWriteString( fs, "detectorType", detectorType.c_str());
cvWriteString( fs, "descriptorType", descriptorType.c_str());
cvWriteString( fs, "matcherType", matcherType.c_str());


cvReleaseFileStorage( &fs);
}




//-------------------------------------------------------------------------------------------------
// Recover configuration parameters from disk
void readConfiguration(void) {
CvFileStorage* fs= cvOpenFileStorage(configFileName, 0, CV_STORAGE_READ);
if (fs) {
dataSetName = cvReadStringByName( fs, 0, "dataSetName");
kindOfIncrement = cvReadIntByName( fs, 0, "kindOfIncrement");
incrementDictionarySize = cvReadIntByName( fs, 0, "incrementDictionarySize");
defaultDictionarySize = cvReadIntByName( fs, 0, "defaultDictionarySize");


detectorType = cvReadStringByName( fs, 0, "detectorType");
descriptorType = cvReadStringByName( fs, 0, "descriptorType");
matcherType = cvReadStringByName( fs, 0, "matcherType");


adjustFileNames();

}
cvReleaseFileStorage( &fs);
}

Eu estou colocando JNIEXPORT void JNICALL Java_CriarArff_diga (JNIEnv * env, jobject jobj){} no lugar da main. Creio q seja por isso que ele não consegue linkar pois não consegue reconhecer o restante do código, contudo não sei como fazer para que todo o código seja importado para o java.


4. Re: JNI

???
gokernel

(usa Linux Mint)

Enviado em 26/03/2013 - 16:45h

so para info:
vc compilou e testou o pequeno tutorial do cara do link ? funcionou ?

dica:
fazer o seu programa em pequena escala para testar ( tipo o do tutorial ).



5. Re: JNI

Carolini
carolini

(usa Ubuntu)

Enviado em 26/03/2013 - 16:52h

Sim eu segui o tutorial e deu certo!!!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts