前提・実現したいこと
OpenCVでSVMを利用するため,サンプルコードを実行して動作を勉強したいと考えています.
発生している問題・エラーメッセージ
古いコードだったので色々修正を加えて動作する段階までこぎつけたものの,train()の部分がうまく動作してくれません.
分類結果の出力の形式に問題があると言っているように見えるのですが,具体的にどこを修正すれば良いかがわかりませんでした.
OpenCV(4.5.3) Error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainData, or pass integer responses) in cv::ml::SVMImpl::train, file C:\build\master_winpack-build-win64-vc15\opencv\modules\ml\src\svm.cpp, line 1630 OpenCV: terminate handler is called! The last OpenCV error is: OpenCV(4.5.3) Error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainData, or pass integer responses) in cv::ml::SVMImpl::train, file C:\build\master_winpack-build-win64-vc15\opencv\modules\ml\src\svm.cpp, line 1630
該当のソースコード
Cpp
1#include <iostream> 2#include <fstream> 3#include <opencv2/opencv.hpp> 4#include <opencv2/core/core.hpp> 5#include <opencv2/features2d/features2d.hpp> 6#include <opencv2/highgui/highgui.hpp> 7#include <opencv2/xfeatures2d/nonfree.hpp> 8#include <opencv2/imgcodecs.hpp> 9#include <opencv2/ml/ml.hpp> 10#include <stdio.h> 11#include <stdlib.h> 12#include <fstream> 13#include <iostream> 14 15 16#pragma warning(disable:4996) 17 18using namespace cv; 19using namespace std; 20 21const int WINDOW_HEIGHT = 512; 22const int WINDOW_WIDTH = 512; 23const int TRAINING_DATA_NUM = 200; 24 25inline int labelOf(double x, double y) { 26 // return (x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5) <= 0.1 ? 1 : -1; 27 // return y >= sin(10 * x) ? 1 : -1; 28 return y >= 10 * x * x ? 1 : -1; 29} 30 31int main() { 32 // Data for visual representation 33 Mat image = Mat::zeros(WINDOW_HEIGHT, WINDOW_WIDTH, CV_8UC3); 34 35 // Set up training data 36 Mat trainingData(TRAINING_DATA_NUM, 2, CV_32FC1); 37 Mat labels(TRAINING_DATA_NUM, 1, CV_32FC1); 38 39 for (int i = 0; i < TRAINING_DATA_NUM; i++) { 40 float x = 1. * rand() / RAND_MAX; 41 float y = 1. * rand() / RAND_MAX; 42 43 trainingData.at<float>(i, 0) = x; 44 trainingData.at<float>(i, 1) = y; 45 46 labels.at<float>(i, 0) = labelOf(x, y); 47 } 48 49 50 // Set up SVM's parameters 51 Ptr<ml::SVM> params = ml::SVM::create(); 52 53 54 params->setType(ml::SVM::C_SVC); 55 params->setKernel(ml::SVM::RBF); 56 params->setDegree(3); 57 params->setGamma(3); 58 //params->setCoef0(0); 59 params->setC(0.1); 60 //params->setP(0.1); 61 //params->setNu(0.5); 62 params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); 63 64 // Train the SVM 65 params->train(trainingData, ml::ROW_SAMPLE, labels); 66 67 68 // Show the decision regions given by the SVM 69 Vec3b red(0, 0, 128), blue(128, 0, 0); 70 for (int i = 0; i < image.rows; ++i) { 71 for (int j = 0; j < image.cols; ++j) 72 { 73 Mat sampleMat = 74 (Mat_<float>(1, 2) << 1. * j / WINDOW_HEIGHT, 1. * i / WINDOW_WIDTH); 75 float response = params->predict(sampleMat); 76 if (response == 1) 77 image.at<Vec3b>(i, j) = red; 78 else if (response == -1) 79 image.at<Vec3b>(i, j) = blue; 80 } 81 } 82 83 // Show the training data 84 for (int i = 0; i < TRAINING_DATA_NUM; i++) { 85 86 if (labels.at<float>(i, 0) == 1) 87 circle(image, Point(trainingData.at<float>(i, 0) * WINDOW_HEIGHT, trainingData.at<float>(i, 1) * WINDOW_WIDTH), 3, Scalar(0, 0, 255), -1, 8); 88 else 89 circle(image, Point(trainingData.at<float>(i, 0) * WINDOW_HEIGHT, trainingData.at<float>(i, 1) * WINDOW_WIDTH), 3, Scalar(255, 0, 0), -1, 8); 90 } 91 92 // Show support vectors 93 imshow("Kernel SVM", image); 94 95 waitKey(0); 96}
元のコード
こちらに修正前のものがあります.
http://techtipshoge.blogspot.com/2014/04/opencv8svm.html
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。