前提・実現したいこと
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
#include <iostream> #include <fstream> #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/xfeatures2d/nonfree.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/ml/ml.hpp> #include <stdio.h> #include <stdlib.h> #include <fstream> #include <iostream> #pragma warning(disable:4996) using namespace cv; using namespace std; const int WINDOW_HEIGHT = 512; const int WINDOW_WIDTH = 512; const int TRAINING_DATA_NUM = 200; inline int labelOf(double x, double y) { // return (x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5) <= 0.1 ? 1 : -1; // return y >= sin(10 * x) ? 1 : -1; return y >= 10 * x * x ? 1 : -1; } int main() { // Data for visual representation Mat image = Mat::zeros(WINDOW_HEIGHT, WINDOW_WIDTH, CV_8UC3); // Set up training data Mat trainingData(TRAINING_DATA_NUM, 2, CV_32FC1); Mat labels(TRAINING_DATA_NUM, 1, CV_32FC1); for (int i = 0; i < TRAINING_DATA_NUM; i++) { float x = 1. * rand() / RAND_MAX; float y = 1. * rand() / RAND_MAX; trainingData.at<float>(i, 0) = x; trainingData.at<float>(i, 1) = y; labels.at<float>(i, 0) = labelOf(x, y); } // Set up SVM's parameters Ptr<ml::SVM> params = ml::SVM::create(); params->setType(ml::SVM::C_SVC); params->setKernel(ml::SVM::RBF); params->setDegree(3); params->setGamma(3); //params->setCoef0(0); params->setC(0.1); //params->setP(0.1); //params->setNu(0.5); params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); // Train the SVM params->train(trainingData, ml::ROW_SAMPLE, labels); // Show the decision regions given by the SVM Vec3b red(0, 0, 128), blue(128, 0, 0); for (int i = 0; i < image.rows; ++i) { for (int j = 0; j < image.cols; ++j) { Mat sampleMat = (Mat_<float>(1, 2) << 1. * j / WINDOW_HEIGHT, 1. * i / WINDOW_WIDTH); float response = params->predict(sampleMat); if (response == 1) image.at<Vec3b>(i, j) = red; else if (response == -1) image.at<Vec3b>(i, j) = blue; } } // Show the training data for (int i = 0; i < TRAINING_DATA_NUM; i++) { if (labels.at<float>(i, 0) == 1) circle(image, Point(trainingData.at<float>(i, 0) * WINDOW_HEIGHT, trainingData.at<float>(i, 1) * WINDOW_WIDTH), 3, Scalar(0, 0, 255), -1, 8); else circle(image, Point(trainingData.at<float>(i, 0) * WINDOW_HEIGHT, trainingData.at<float>(i, 1) * WINDOW_WIDTH), 3, Scalar(255, 0, 0), -1, 8); } // Show support vectors imshow("Kernel SVM", image); waitKey(0); }
元のコード
こちらに修正前のものがあります.
http://techtipshoge.blogspot.com/2014/04/opencv8svm.html
まだ回答がついていません
会員登録して回答してみよう