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.