How to load previously stored svm classifier? - c++

I'm working with openCV SVM in Visual Studio. (OpenCV 2.4.4.0)
I trained it:
mySVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
Saved it:
mySVM.save("classifier.xml");
I'm loading it like this:
CvSVM mySVM1;
mySVM1.load("C:\classifier.xml");
mySVM1.predict(testingDataMat0,result0);
And i want to use in other project. But when i try to load classifier this error bumps all the time:
"Bad argument (The SVM should be trained first) in CvSVM::predict"
Path is correct, and .xml seems correctly stored.
Does anybody know what am I doing wrong or where the problem might be?
classifier.xml:
<?xml version="1.0"?>
<opencv_storage>
<my_svm type_id="opencv-ml-svm">
<svm_type>C_SVC</svm_type>
<kernel><type>RBF</type>
<gamma>5.0625000000000009e-001</gamma></kernel>
<C>2.5000000000000000e+000</C>
<term_criteria><epsilon>2.2204460492503131e-016</epsilon>
<iterations>100</iterations></term_criteria>
<var_all>3</var_all>
<var_count>3</var_count>
<class_count>2</class_count>
<class_labels type_id="opencv-matrix">
<rows>1</rows>
<cols>2</cols>
<dt>i</dt>
<data>
-1 1</data></class_labels>
<sv_total>10</sv_total>
<support_vectors>
<_>
9.09866020e-002 5.56291997e-001 2.43510995e-002</_>
<_>
9.46519971e-001 2.94328004e-001 2.08841003e-002</_>
<_>
1. 3.68389994e-001 1.15272999e-002</_>
<_>
9.41470027e-001 3.73109013e-001 1.25126000e-002</_>
<_>
1. 2.23776996e-001 9.57737025e-003</_>
<_>
4.68845010e-001 3.62690985e-002 9.11400989e-002</_>
<_>
7.98106015e-001 2.73550004e-002 9.26491022e-002</_>
<_>
7.02144980e-001 3.98130007e-002 9.00894031e-002</_>
<_>
4.99359012e-001 4.31513004e-002 8.61563012e-002</_>
<_>
7.39947975e-001 4.39946018e-002 9.60593969e-002</_></support_vectors>
<decision_functions>
<_>
<sv_count>10</sv_count>
<rho>-5.7845965027809154e-001</rho>
<alpha>
2.5000000000000000e+000 2.5000000000000000e+000
1.4641912158132706e+000 2.5000000000000000e+000
2.5000000000000000e+000 -1.4641912158132708e+000
-2.5000000000000000e+000 -2.5000000000000000e+000
-2.5000000000000000e+000 -2.5000000000000000e+000</alpha>
<index>
0 1 2 3 4 5 6 7 8 9</index></_></decision_functions></my_svm>
</opencv_storage>

I had this problem and found that in SVM codes ,at least in OpenCV, predict function uses the same kernel witch is used in train function to determine input class. So when you run predict separately it doesn't know what kind of kernel should it uses. So, I think running train function exactly before predict function is avoidable.

Related

OpenMVG mainComputeMatches.cpp input explanation

How can i compute descriptor matches using --pair_list option file (using main_ComputeMatches.cpp).
What is the format of data in the file specified by input --pair_list?
Thanks in advance for any suggestion.
You must list the image view index.
See your sfm_data.json, each image is linked to a view index.
In the pair_list file you just connect the image pair your wanna try to compute like
0 1
0 2
1 2
1 6
...
Expanding #Jack answer, you could also compact it like this:
0 1 2
1 2 6
...

How to load svm train data.model by LibSVM in OpenCV 3.1

I have a problem for loading SVM data.modelin Opencv 3.1 .I look code for loading SVM in train_hog.cpp sample :
// Load the trained SVM.
svm = StatModel::load<SVM>( "my_people_detector.yml" );
// Set the trained svm to my_hog
vector< float > hog_detector;
get_svm_detector( svm, hog_detector );
my_hog.setSVMDetector( hog_detector );
And this is an example my SVM train data.model by using LibSVM :
svm_type nu_svc
kernel_type linear
nr_class 2
total_sv 41
rho -0.4447
label 1 -1
nr_sv 21 20
SV
0.06074145976542984 1:0.0516209 2:0.0526671 3:0.0621273 4:0.162602 5:0.252267 6:0.220246 7:0.116933 8:0.0665012 9:0.040535 10:0.0810178 11:0.0799648 12:0.0989393 13:0.204468 14:0.252267 15:0.232619 16:0.10104 17:0.0503855 18:0.0872255 19:0.109535 20:0.135352 21:0.252267 22:0.252267 23:0.252267 24:0.19159 25:0.139957 26:0.0849861 27:0.0621954 28:0.180085 29:0.220934 30:0.252267 31:0.252267 32:0.252267 33:0.14686 34:0.133376 35:0.0798698 36:0.143804 37:0.154667 38:0.175837 39:0.175819 40:0.185156 41:0.242682 42:0.143323 43:0.0656771
44:0.0752698 45:0.120002 46:0.125042 47:0.137929 48:0.141668 49:0.238362 50:0.242682 51:0.187268 52:0.0587663 53:0.0820198 54:0.0561508 55:0.173739 56:0.235661 57:0.176866 58:0.242682 59:0.242682 60:0.120697 61:0.0926801 62:0.074838 63:0.120294 64:0.099418 65:0.165938 66:0.223667 67:0.242682 68:0.242682
So, What I must to do next ?. Until now, I'm very confusing for understanding load my model data.Which i know statModel::load<SVM> load .xml or .yml.Do you have an idea ?
The easiest way might be to use libsvm inside your OpenCV project, like in the answer here: https://stackoverflow.com/a/22354047/4966367

Moving GroupBys

My Data Set Looks like
1
2
3
4
5
...
I have an intermediate step which should do the folowing
1
1,2
1,2,3
1,2,3,4
1,2,3,4,5
....
And finally calculate its mean
1
1.5
2
2.5
3
...
Questions
a) Is there a way to implement this in python / py-spark?.
b) Is there a method/api which does this out of the box.
c) I googled around for this kind of solution the closest i got was to moving mean/ rolling average / moving group. Is there a term for this operation?
In Pandas, this is called an expanding_mean:
import pandas as pd
df = pd.Series(range(1,6))
s = pd.Series(range(1,6))
pd.expanding_mean(s)
Out[128]:
0 1.0
1 1.5
2 2.0
3 2.5
4 3.0
dtype: float64
I'm not sure how you'd do this in Spark, but that said, I'm also not sure if this is a "parallelalizable" task: since each step relies on the previous step, I'm not sure how you'd break this up into steps.

Loading Collada animation joints?

I'm having trouble loading joint data information from 'animation' node of collada file.
First, I try to load joints from 'library_visual_scenes' :
The first 2 joints look like that :
<visual_scene id="" name="">
<node name="joint1" id="joint1" sid="joint1" type="JOINT">
<translate sid="translate">0.000000 -2.000000 0.000000</translate>
<rotate sid="jointOrientZ">0 0 1 90.000000</rotate>
<rotate sid="rotateZ">0 0 1 0.000000</rotate>
<rotate sid="rotateY">0 1 0 0.000000</rotate>
<rotate sid="rotateX">1 0 0 0.000000</rotate>
<scale sid="scale">1.000000 1.000000 1.000000</scale>
<extra>
<node name="joint2" id="joint2" sid="joint2" type="JOINT">
<translate sid="translate">2.000000 0.000000 0.000000</translate>
<rotate sid="rotateZ">0 0 1 0.000000</rotate>
<rotate sid="rotateY">0 1 0 0.000000</rotate>
<rotate sid="rotateX">1 0 0 0.000000</rotate>
<scale sid="scale">1.000000 1.000000 1.000000</scale>
<extra>
which went well !
Maya joints :
My joints :
I would like to put a picture but as a new member, i'm not allowed. You'll have to trust me on this case, in my engine, joints are in the same place as in maya.
Then, I try to load joints from 'animation' node. Here is the problem, I can't find any jointOrient.
<animation id="joint1-anim" name="joint1">
<animation>
<source id="joint1-translate.Y-output">
<float_array id="joint1-translate.Y-output-array" count="2">-2.000000 -2.000000</float_array>
<animation>
<source id="joint1-rotateZ.ANGLE-output">
<float_array id="joint1-rotateZ.ANGLE-output-array" count="2">0.000000 0.000000</float_array>
<animation id="joint2-anim" name="joint2">
<animation>
<source id="joint2-translate.X-output">
<float_array id="joint2-translate.X-output-array" count="2">2.000000 2.000000</float_array>
So after loading joints, they look like that :
Anybody here could help ?
Thanks.
(Sorry as I don't have more than 10 reputations, i'm not allowed to put pictures.)
I finally figured out the answer, for those who might be interested.
The visual_scene node from collada will give you the bind pose for your joints.
So, I'm going to load visual_scene joint coordinates in a structure :
Something like that :
struct Pose
{
vec3 translation,
orientation,
rotation,
scale;
};
Pose bind_pose;
Then I'm going to create another instanciation of "Pose" struct, with a constructor which take a Pose as parameter :
Pose anim_pose(bind_pose);
So after construction, bind_pose from visual_scene and anim_pose are the same.
Then I'm going to iterate through all the animation node in library_animations, find the channel and get interested with :
the source data, which tell where to find joint animations info ("n" float(s) for "n" animation(s) :))
and the target joint.
<channel source="#joint1-translate.X" target="joint1/translate.X"></channel>
This tell us (and that's where I was a little lost) that we are going to REPLACE the targeted value with the source value.
If the source data find in channel node is the same as the target data, ie. :
bind_pose.translation.x has -3.0 as a value after loading visual_scene data, and
<source id="joint1-translate.X-output">
<float_array id="joint1-translate.X-output-array" count="1">-3.000000</float_array>
I do nothing.
If the source data is different from the target data, I simply replace in anim_pose with the good value.
And that's pretty much all you have to do to properly load animated joints from collada.
If you see anything wrong here, please tell me.
Hope this will help.

CFCHART - How do I get the Y-Axis to start at 1 instead of 0

Here is the example style I am using:
<?xml version="1.0" encoding="UTF-8"?>
<frameChart is3D="false">
<frame xDepth="3" yDepth="1" leftAxisPlacement="Back" isHStripVisible="true">
<background minColor="#FDFEF6"/>
</frame>
<yAxis scaleMin="1" scaleMax="500">
<labelFormat pattern="#,##0.###"/>
<parseFormat pattern="#,##0.###"/>
</yAxis>
<legend>
<decoration style="None"/>
</legend>
<elements place="Default" shape="Line" drawShadow="true">
<morph morph="Grow"/>
</elements>
</frameChart>
The above code will show 0 instead of 1.
This seems to be a common problem using cfchart, but it appears to be a problem in the web charts program as well.
Does anyone have a good solution?
Short answer: It is possible, but there are some side effects in your specific case.
Longer answer:
You can force the y-axis to start at 1 by specifying the number of labels (ie grid lines). But as long the range is an odd number (ie 500 - 1 ==> 499) some of the y-axis values may not line up evenly.
<!--- labelCount is number of grid lines + 1 --->
<yAxis scaleMin="1" scaleMax="500" labelCount="6">
<labelFormat style="Integer" pattern="#,##0"/>
</yAxis>
That is because y-axis values are calculated by dividing the scale range by the number of grid lines. With odd ranges that typically produces fractional numbers. For example, if you generated five (5) grid lines, the axis values would be:
Actual => Rounded Value
500.0 => 500
400.2 => 400
300.4 => 300
200.6 => 201 **
100.8 => 101 **
1.0 => 1
The only way to have complete control over all y-axis values is to ensure the range / grid lines works out to a whole number.