2016-06-27 10 views
1

OpenCVでSVMを学ぶ簡単な例を試していますが、トレーニング後に正しいサポートベクトルが得られません。この問題を理解するための助けが必要です。 私のコードは次のとおりです。私は期待どおり単純なデータセット(Opencv 2.4.9)のSVMトレーニングの問題

#include <iostream> 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/ml/ml.hpp> 

using namespace cv; 
using namespace std; 

int main() { 

Mat frame(Size(640,360), CV_8UC3, Scalar::all(255)); 
float train[15][2] = { {296, 296}, {296, 312}, {312, 8}, {312, 56}, {312, 88}, {328, 88}, {328, 104}, {328, 264}, {344, 8}, {344, 40}, {360, 8}, {360, 56}, {376, 8}, {376, 40}, {376, 56} }; 
Mat trainingDataMat(15, 2, CV_32FC1, train); 
float labels[15] = { -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1 }; 
Mat labelsMat(15, 1, CV_32FC1, labels); 

CvSVMParams param; 
param.svm_type  = CvSVM::C_SVC; 
param.C   = 0.1; 
param.kernel_type = SVM::LINEAR; 
param.term_crit = TermCriteria(CV_TERMCRIT_ITER, 1000, 1e-6); 

CvSVM SVM; 

SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), param); 
cout<< "Training Finished..." << endl; 
for(int i = 0; i < frame.rows; ++i) { 
    for(int j = 0; j < frame.cols; ++j) { 
     Mat sampleMat = (Mat_<float>(1,2) << i,j); 
     float response = SVM.predict(sampleMat); 
     //cout << response << endl; 
     if(response == 1) { 
      frame.at<Vec3b>(i,j)[2] = 0; 
     } else { 
      frame.at<Vec3b>(i,j)[0] = 0; 
     } 
    } 
} 
for(int dis = 0; dis < trainingDataMat.rows; dis++) { 
    if(labels[dis] == 1) { 
     circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 0, 0), -1); 
    } else { 
     circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 255, 0), -1); 
    } 
}  
int n = SVM.get_support_vector_count(); 
for(int i = 0; i < n; i++) { 
      const float* v = SVM.get_support_vector(i); 
      cout << "support Vectors : " << v[0] << " " << v[1] <<endl; 
      circle(frame,Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), 2, 8); 
} 
imwrite("frame.jpg",frame); 
imshow("output", frame); 
waitKey(0); 

return 0; 
} 

Output image is attached

SVMラインは2つのクラスを分離されていません。サポート・ベクターのための

結果はSVMがOKであるべき

support Vectors : 0 0.0125 

答えて

1

です。問題はあなたのディスプレイにあると思います。 circle(frame, Point((int)train[dis][0], (int)train[dis][1]), 3, Scalar (0, 0, 0), -1);に電話をすると、OpenCVは行番号train[dis][1]と列番号train[dis][0]の円が必要であることを理解しています。 OpenCVの特異性は、行列や点に異なる座標系を使用しているためです。 image.at<float>(Point(i,j))image.at<float>(j,i)に相当します。

は、これであなたのcircle通話交換してみてください:

if(labels[dis] == 1) { 
    circle(frame, Point((int)train[dis][1], (int)train[dis][0]), 3, Scalar (0, 0, 0), -1); 
} else { 
    circle(frame, Point((int)train[dis][1], (int)train[dis][0]), 3, Scalar (0, 255, 0), -1); 
} 
+0

をあなたに@Sunreefをありがとう、それは助けたが、それでも私は 'サポートベクトル、としてサポートベクトルを取得しています:それはいないようです0.0125 0 ' – venkat

+0

あなたの2つのグループ間の分離が垂直であるので、私にとっては不条理です(したがって、法線ベクトルはx =/0とy = 0でなければなりません)。 @venkatsubramanian – Sunreef

+0

私はOpenCv 2.4.9 **を使用していますが、SVMの例(non_linear_svms.cpp)をsrcファイルから試してみました。サポートベクトルが「Support Vectors:-0.06105730 0.0133702'、それが正しいか?またはOpencvのバグですか?私の出力イメージはhttps://drive.google.com/file/d/0BzXZDZFGar7BdVBUekthYm1yVlk/です。サポートベクトルは左上隅に表示され、opencvドキュメントの出力はhttp://ですdocs.opencv.org/2.4/_images/result1.png、私の画像とopencvのサンプル画像の違いは、サポートベクターポイントマーカーがないことです – venkat