Я пытаюсь создать классификатор для набора слов. Я нашел на этом веб-сайте вопрос (здесь), который помог я собрал приведенный ниже код вместе, но я застрял на classifier->train(trainingData,ml::ROW_SAMPLE, labels);
. По сути, программа работает нормально, но когда доходит до этой строки, происходит сбой. Судя по всему, линия выполняет деление на ноль и, следовательно, дает сбой. Я просмотрел код и не нашел ошибки. Это может быть ошибка перевода из openCV 2 -> 3, не совсем уверен. Любая помощь будет принята с благодарностью!
#include <opencv2/core/core.hpp>
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
using namespace std;
using namespace cv;
#define TRAINING_DATA_DIR "testImages/"
#define EVAL_DATA_DIR "evalImages/"
int dictSize = 1000;
TermCriteria tc(CV_TERMCRIT_ITER, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
Ptr<FeatureDetector> detector = xfeatures2d::SURF::create();
Ptr<DescriptorExtractor> extractor = xfeatures2d::SURF::create();
Ptr<DescriptorMatcher> matcher = FlannBasedMatcher::create("FlannBased");
BOWKMeansTrainer bowTrainer(dictSize, tc, retries, flags);
BOWImgDescriptorExtractor bowDE(extractor, matcher);
void extractTrainingVocabulary(string path){
struct dirent *de = NULL;
DIR *d = NULL;
d = opendir(path.c_str());
if(d == NULL)
{
cerr << "Couldn't open directory" << endl;
} else {
// Add all the names of the files to be processed to a vector
vector<string> files;
while ((de = readdir(d))) {
string nameOfFile(de->d_name);
if ((strcmp(de->d_name,".") != 0) && (strcmp(de->d_name,"..") != 0) && (strcmp(de->d_name,".DS_Store") != 0)) {
files.push_back(nameOfFile);
}
}
// Loop through all elements
for (int f = 0; f < files.size(); f++){
string fullPath = "./";
fullPath += TRAINING_DATA_DIR;
fullPath += files[f];
cout << "[" << f+1 << "/" << files.size() << "]\tProcessing image: " << fullPath << endl;
Mat input = imread(fullPath);
if (!input.empty()){
// Find all keypoints
vector<KeyPoint> keypoints;
detector->detect(input, keypoints);
if (keypoints.empty()){
cerr << "Warning! could not find any keypoints in image " << fullPath << endl;
} else {
// Extract the features
Mat features;
extractor->compute(input, keypoints, features);
// Add them to the trainer
bowTrainer.add(features);
}
} else {
cerr << "Could not read image " << fullPath << endl;
}
}
}
}
void extractBOWDescriptor(string path, Mat& descriptors, Mat& labels){
struct dirent *de = NULL;
DIR *d = NULL;
d = opendir(path.c_str());
if(d == NULL)
{
cerr << "Couldn't open directory" << endl;
} else {
// Add all the names of the files to be processed to a vector
vector<string> files;
while ((de = readdir(d))) {
string nameOfFile(de->d_name);
if ((strcmp(de->d_name,".") != 0) && (strcmp(de->d_name,"..") != 0) && (strcmp(de->d_name,".DS_Store") != 0)) {
files.push_back(nameOfFile);
}
}
// Loop through all elements
for (int f = 0; f < files.size(); f++){
string fullPath = "./";
fullPath += EVAL_DATA_DIR;
fullPath += files[f];
cout << "[" << f+1 << "/" << files.size() << "]\tProcessing image: " << fullPath << endl;
Mat input = imread(fullPath);
if (!input.empty()){
// Find all keypoints
vector<KeyPoint> keypoints;
detector->detect(input, keypoints);
if (keypoints.empty()){
cerr << "Warning! could not find any keypoints in image " << fullPath << endl;
} else {
Mat bowDescriptor;
bowDE.compute(input, keypoints, bowDescriptor);
descriptors.push_back(bowDescriptor);
// Current file
string fileName = files[f];
// Strip extension
fileName.erase (fileName.end()-4, fileName.end());
float label = atof(fileName.c_str());
cout << "Filename: " << fileName << endl;
labels.push_back(label);
}
} else {
cerr << "Could not read image " << fullPath << endl;
}
}
}
}
int main(int argc, char ** argv) {
// ============================ LEARN ============================
cout << "Creating dict" << endl;
extractTrainingVocabulary(TRAINING_DATA_DIR);
vector<Mat> descriptors = bowTrainer.getDescriptors();
int count=0;
for(vector<Mat>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++){
count+=iter->rows;
}
cout << "Clustering " << count << " features. This might take a while..." << endl;
Mat dictionary = bowTrainer.cluster();
cout << "Writing to dict...";
FileStorage fs("dict.yml",FileStorage::WRITE);
fs << "vocabulary" << dictionary;
fs.release();
cout << "Done!" << endl;
// =========================== EXTRACT ===========================
// This will have to be loaded if we run it in two different instances
bowDE.setVocabulary(dictionary);
cout << "Processing training data..." << endl;
Mat trainingData(0, dictSize, CV_32FC1);
Mat labels(0,1,CV_32FC1);
extractBOWDescriptor(EVAL_DATA_DIR, trainingData, labels);
Ptr<ml::NormalBayesClassifier> classifier = ml::NormalBayesClassifier::create();
if (trainingData.data == NULL || labels.data == NULL){
cerr << "Mats are NULL!!" << endl;
} else {
classifier->train(trainingData,ml::ROW_SAMPLE, labels);
}
//#warning Not yet tested
// cout << "Processing evaluation data" << endl;
// Mat evalData(0,dictSize,CV_32FC1);
// Mat groundTruth(0,1,CV_32FC1);
// extractBOWDescriptor(EVAL_DATA_DIR, evalData, groundTruth);
return 0;
}
РЕДАКТИРОВАТЬ
Как и было запрошено, вот ошибка.
- Через терминал:
Floating point exception: 8
- XCode 6:
Thread 1:EXC_ARITHMETIC (code=EXC_i386_DIV, subcode=0x0)