Random tree CvRTrees persistence issue opencv - c++

I'm trying to implement a random tree classifier using Opencv. I succeed implementing it with opencv and it is working.
Then I decided to separate the training part from the classification part.
The idea is to save the trained forest and load it back when you want to classify something.
I tried in two different way:
using write and read methods of the super class CvStatModel
using store and load methods of the super class CvStatModel
But results form the older implementation that did not save trees to file are different and worst.
Following code is the implementation of 2nd point:
To store it:
for (unsigned i=0; i<scenes.size(); ++i) {
char class_fname[50];
char output[100];
sprintf(class_fname,"class_%d.xml",i);
sprintf(output,"class_%d",i);
//classifiers[i]->save(class_fname,output);
classifiers[i]->save(class_fname);
}
To load them back:
for (unsigned int i = 0; i<CLUSTERING_N_CENTERS;i++){
char class_fname[50];
char output[100];
sprintf(class_fname,"class_%d.xml",i);
sprintf(output,"class_%d",i);
classifiers[i] = new CvRTrees();
//classifiers[i]->load(class_fname,output);
classifiers[i]->load(class_fname);
}
I'm using opencv 2.4.6
Does anyone have suggestions on this code?

It was an error due to file mistake!
So the persistency is working!
But I leave the post as sample if someone needs to implement it!

Related

itk OtsuMultipleThresholdsImageFilter does not process

I am trying to use ITK's OtsuMultipleThresholdsImageFilter filter in a project but I do not have output.
My aim is to make a simple interface between OpenCV and ITK.
To convert my data from OpenCV's Mat container to itk::Image I use ITK's bridge to OpenCV and I could check that the data are properly sent to ITK.
I am even able to display thanks to QuickView.
But When I setup the filter inspired by this example the object returned by the method GetThresholds() is empty.
Here is the code I wrote:
typedef itk::Image<uchar,2> image_type;
typedef itk::OtsuMultipleThresholdsImageFilter<image_type, image_type> filter_type;
image_type::Pointer img = itk::OpenCVImageBridge::CVMatToITKImage<image_type>(src);
image_type::SizeType size = img->GetLargestPossibleRegion().GetSize();
filter_type::Pointer filter = filter_type::New();
filter->SetInput(img);
filter->SetNumberOfHistogramBins(256);
filter->SetNumberOfThresholds(K);
filter_type::ThresholdVectorType tmp = filter->GetThresholds();
std::cout<<"CHECK: "<<tmp.size()<<std::endl;
src is OpenCV's Mat of CV_8U(C1) type.
A fundamental and basic concept to using ITK is that it is a pipeline architecture. You must connect the input's and output's then update the pipeline.
You have connected the pipeline but you have not executed it. You must call filter->Update().
Please read the ITK Software Guide to understand the fundamentals of ITK:
https://itk.org/ItkSoftwareGuide.pdf

How do you use load data from a CSV in C++ TensorFlow?

I'm trying to load a model trained in Python into C++ and classify some data from a CSV. I found this tutorial:
https://medium.com/#hamedmp/exporting-trained-tensorflow-models-to-c-the-right-way-cf24b609d183#.3bmbyvby0
Which lead me to this piece of example code:
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/label_image/main.cc
Which is looking very hopeful for me. However, the data I want to load is in a CSV, and not an image file, so I'm trying to rewrite the ReadTensorFromImageFile function. I was able to find a class DecodeCSV, but it's a little different than the DecodePNG and DecodeJpeg classes in the example code, and I end up with an OutputList instead of and Output. Using the [] operator on the list seems to crash my program. If anyone happens to know how to deal with this, it would be greatly appreciated. He are the relevant changes to the code:
// inside ReadTensorFromText
Output image_reader;
std::initializer_list<Input>* x = new std::initializer_list<Input>;
::tensorflow::ops::InputList defaults = ::tensorflow::ops::InputList(*x);
OutputList image_read_list;
image_read_list = DecodeCSV(root.WithOpName("csv_reader"), file_reader, defaults).output;
// Now cast the image data to float so we can do normal math on it.
// image_read_list.at(0) crashes the executable.
auto float_caster =
Cast(root.WithOpName("float_caster"), image_read_list.at(0), tensorflow::DT_FLOAT);

C++ - Using a variable without knowing what it is called

I have a program that uses plug-ins. As I'm in development, these plug-ins are currently just .h and .cpp files that I add or remove from my project before re-compiling, but eventually they will be libraries.
Each plug-in contains lists of data in vectors, and I need to dynamically load data from the plug-ins without knowing which plug-ins are present. For instance:
// plugin1.h
extern vector<int> plugin1Data;
// plugin2.h
extern vector<int> plugin2Data;
// main.cpp
vector<vector<int>> pluginDataList;
int CountPlugins () {
// Some function that counts how many plug-ins are present, got this bit covered ;)
}
int main() {
int numPlugins = CountPlugins();
for (int i = 0; i < numPlugins; i++) {
vector<int> newPluginData = /***WAY TO ADD PLUGIN DATA!!!***/;
pluginDataList.push_back(newPluginData);
}
}
I already access the names of each plugin present during my CountPlugins() function, and have a list of names, so my first gut feeling was to use the name from each plugin to create a variable name like:
vector<string> pluginNames = /*filled by CountPlugins*/;
string pluginDataName = pluginNames.at(i) + "Data";
// Use pluginDataName to locate plugin1Data or plugin2Data
That's something I've done before in c# when I used to mess around with unity, but I've read a few stackoverflow posts clearly stating that it's not possible in c++. It's also a fairly messy solution in C# anyway as far as I remember.
If each plugin was a class instead of just a group of vectors, I could access the specific data doing something like plugin2.data... but then I still need to be able to reference the object stored within each plugin, and that'll mean that when I get round to compiling the plugins as libraries, I'll always have to link to class declaration and definition, which isn't ideal (though not out of the question if it'll give a nicer solution over all).
I'm all out of ideas after that, any help you can offer will be most welcome!
Thanks! Pete
Why dont you save the data as JSON between the application and the plugins ? That way you will also allow other types of tech to plug-into your app, like javascript based plugins via an embedded version of v8 or c#/.net plugins via mono.'

How to predict class of a instance in Waffles c++ API

my name is titiri and happy that I found waffle library to classification. I think waffle is a good library for machine learning algorithms.
I have a question about waffle library.
After training a model, I want print a prediction, for a instance:
my code is:
GMatrix Instance(1,8);//instance have 8 real attribute and
double out;// value in attribute 'class' is nomial
Instance[0][0]=6;
Instance[0][1]=148;
Instance[0][2]=72;
Instance[0][3]=35;
Instance[0][4]=0;
Instance[0][5]=33.6;
Instance[0][6]=0.62;
Instance[0][7]=50;
modell->predict(Instance[0],&out);
cout<<&out;
This code do not work true and does not print anything.
Please help me!
What do I need to predict class of a instance , then print its class,
have a good performance 'predict' method for classify a instance?
Or is there a better method for this work ?
thanks,
Be happy and win
I suspect the reason your code does not print anything is because you forgot the endl. (This is what Joachim Pileborg mentioned in his comment.)
If you are using Visual Studio, you may want to add a breakpoint at the end of your code (maybe on the return statement) because in certain modes it can close your application before you get to see the output, which can make it seem as if nothing happened.
Example
What follows is a full example that works fine for me. It includes your instance. It loads a K-nearest neighbors learner from 2blobs_knn.json and then evaluates your instance on it. You can replace that file name with the name of any trained supervised model generated by the waffles tools.
With the model I used, the program prints "1" and exits.
If you want to use the exact model that I tested my code with (in case your method of constructing your learner is the problem) see the section after the example code.
#include <GClasses/GMatrix.h>
#include <GClasses/GHolders.h>
#include <GClasses/GRand.h>
#include <GClasses/GLearner.h>
#include <GClasses/GDom.h>
#include <iostream>
#include <cassert>
using namespace GClasses;
using std::cout; using std::endl;
int main(int argc, char *argv[])
{
//Load my trained learner from a file named 2blobs_knn.json and put
//it in hModel which is a shared-pointer class.
GLearnerLoader ll(GRand::global());
GDom dom;
dom.loadJson("2blobs_knn.json");
Holder<GSupervisedLearner> hModel(ll.loadSupervisedLearner(dom.root()));
assert(hModel.get() != NULL);
//Here is your code
GMatrix Instance(1,8);// Instance has 8 real attributes and one row
double out; // The value in attribute 'class' is nominal
Instance[0][0]=6;
Instance[0][1]=148;
Instance[0][2]=72;
Instance[0][3]=35;
Instance[0][4]=0;
Instance[0][5]=33.6;
Instance[0][6]=0.62;
Instance[0][7]=50;
hModel.get()->predict(Instance[0],&out);
cout << out << endl;
return 0;
}
How the learner I used in the example was constructed
To get the learner, I used Matlab (Octave is the free imitator) to generate a CSV file in which class 0 was an 8-dimensional spherical unit Gaussian centered at (0,0,0,0,0,0,0,0) and class 1 had the same distribution but centered at (2,2,2,2,2,2,2,2)
m=[[randn(200,8);randn(200,8)+2], [repmat(0,200,1);repmat(1,200,1)]];
csvwrite('2blobs.csv',m)
Then, I took that CSV, converted it to ARFF using
waffles_transform import 2blobs.csv > 2blobs.arff
Next, I changed the last attribute from #ATTRIBUTE attr8 real to
#ATTRIBUTE class {0,1} in a text editor so it would be nominal.
Finally, I trained the model with
waffles_learn train 2blobs.arff knn -neighbors 10 > 2blobs_knn.json

Serialize CvKNearest class using Boost Serialization library

Is there a simple way to save a KNN classifier in OpenCV by using the C++ API?
I have tried to save a KNN classifier described here after wrapping CvKNearest class inside another class.
It successfully saves to disk, but when I read from it running predict method gives me segmentation fault (core dumped) error.
My wrapper class is as follows:
class KNNWrapper
{
CvKNearest knn;
bool train(Mat& traindata, Mat& trainclasses)
{
}
void test(Mat& testdata, Mat& testclasses)
{
}
}
I've heard that Boost Serialization library is more robust and safe. Can anyone point me to proper resources where I can get this done with Boost library?
#tisch is totally right and I'd like to correct myself. The CvKNearest doesn't override the load and save functions of the CVStatModel.
But since a CvKNearest doesn't compute a model, there's no internal state to store. Of course, you want to store the training and test cv::Mat data you have passed. You can use the FileStorage class for this, a great description and tutorial is given at:
http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html
If you want to offer the same API as in the other statistical models in OpenCV (which makes sense) I suppose to subclass the CvKNearest and offer a save and load function, which respectively serialize the training/test data and deserialize it by using the FileStorage.