x軸は時間で、y軸に実験で得られたデータ(温度など)を用いる予定です。
とりあえず時間と温度を持ったスカラー量をSVMに使おうとネットで資料を探したところ、4クラスのSVMが見つかりました。
80行目のfor文がクラスの数にかかわっていると思うのですが、思うように3クラスの分類になりません。
どのように変更するとよいでしょうか?
また、実験で得られたデータのみを使いたい場合は49行目でランダムに発生させているものの代わりにcvPointで座標指定すればよろしいのでしょうか?
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
const int WINDOW_HEIGHT = 512;
const int WINDOW_WIDTH = 512;
const int TRAINING_DATA_NUM = 200;
const Vec3b REGION_COLOR[] = {
Vec3b(0, 0, 128),
Vec3b(0, 128, 0),
Vec3b(128, 0, 0),
Vec3b(0, 64, 128)
};
const Scalar DATA_COLOR[] = {
Scalar(0, 0, 255),
Scalar(0, 255, 0),
Scalar(255, 0, 0),
Scalar(0, 128, 255)
};
inline int labelOf(double x, double y) {
// concentric circle
/*
double d = (x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5);
if (d < 0.075) return 0;
if (d < 0.15) return 1;
if (d < 0.22) return 2;
return 3;
*/
// quadrant
x -= 0.5, y -= 0.5;
return (x >= 0) * 2 + (y >= 0);
}
/**
* マルチクラス非線形SVMのデモ.
*/
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
CvSVMParams params = CvSVMParams();
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::RBF;
params.degree = 0;
params.gamma = 20;
params.coef0 = 0;
params.C = 10;
params.nu = 0.0;
params.p = 0.0;
params.class_weights = NULL;
params.term_crit.type = CV_TERMCRIT_ITER + CV_TERMCRIT_EPS;
params.term_crit.max_iter = 1000;
params.term_crit.epsilon = 1e-6;
// Train the SVM
CvSVM SVM;
SVM.train(trainingData, labels, Mat(), Mat(), params);
// Show the decision regions given by the SVM
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);
int response = SVM.predict(sampleMat);
image.at<Vec3b>(i,j) = REGION_COLOR[response];
}
}
// Show the training data
for (int i = 0; i < TRAINING_DATA_NUM; i++) {
double x = trainingData.at<float>(i, 0) * WINDOW_HEIGHT;
double y = trainingData.at<float>(i, 1) * WINDOW_WIDTH;
int label = labels.at<float>(i, 0);
circle(image, Point(x, y), 3, DATA_COLOR[label], -1, 8);
}
// Show support vectors
int c = SVM.get_support_vector_count();
for (int i = 0; i < c; ++i) {
const float* v = SVM.get_support_vector(i);
circle(image, Point(v[0] * WINDOW_WIDTH, v[1] * WINDOW_HEIGHT),
6, Scalar(128, 128, 128), 2, 8);
}
imshow("Kernel SVM", image);
waitKey(0);
}