vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
+368
View File
@@ -0,0 +1,368 @@
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/geometry.hpp"
#include "opencv2/ml.hpp"
#include <algorithm>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
const int SZ = 20; // size of each digit is SZ x SZ
const int CLASS_N = 10;
const char* DIGITS_FN = "digits.png";
static void help(char** argv)
{
cout <<
"\n"
"SVM and KNearest digit recognition.\n"
"\n"
"Sample loads a dataset of handwritten digits from 'digits.png'.\n"
"Then it trains a SVM and KNearest classifiers on it and evaluates\n"
"their accuracy.\n"
"\n"
"Following preprocessing is applied to the dataset:\n"
" - Moment-based image deskew (see deskew())\n"
" - Digit images are split into 4 10x10 cells and 16-bin\n"
" histogram of oriented gradients is computed for each\n"
" cell\n"
" - Transform histograms to space with Hellinger metric (see [1] (RootSIFT))\n"
"\n"
"\n"
"[1] R. Arandjelovic, A. Zisserman\n"
" \"Three things everyone should know to improve object retrieval\"\n"
" http://www.robots.ox.ac.uk/~vgg/publications/2012/Arandjelovic12/arandjelovic12.pdf\n"
"\n"
"Usage:\n"
<< argv[0] << endl;
}
static void split2d(const Mat& image, const Size cell_size, vector<Mat>& cells)
{
int height = image.rows;
int width = image.cols;
int sx = cell_size.width;
int sy = cell_size.height;
cells.clear();
for (int i = 0; i < height; i += sy)
{
for (int j = 0; j < width; j += sx)
{
cells.push_back(image(Rect(j, i, sx, sy)));
}
}
}
static void load_digits(const char* fn, vector<Mat>& digits, vector<int>& labels)
{
digits.clear();
labels.clear();
String filename = samples::findFile(fn);
cout << "Loading " << filename << " ..." << endl;
Mat digits_img = imread(filename, IMREAD_GRAYSCALE);
split2d(digits_img, Size(SZ, SZ), digits);
for (int i = 0; i < CLASS_N; i++)
{
for (size_t j = 0; j < digits.size() / CLASS_N; j++)
{
labels.push_back(i);
}
}
}
static void deskew(const Mat& img, Mat& deskewed_img)
{
Moments m = moments(img);
if (abs(m.mu02) < 0.01)
{
deskewed_img = img.clone();
return;
}
float skew = (float)(m.mu11 / m.mu02);
float M_vals[2][3] = {{1, skew, -0.5f * SZ * skew}, {0, 1, 0}};
Mat M(Size(3, 2), CV_32F, &M_vals[0][0]);
warpAffine(img, deskewed_img, M, Size(SZ, SZ), WARP_INVERSE_MAP | INTER_LINEAR);
}
static void mosaic(const int width, const vector<Mat>& images, Mat& grid)
{
int mat_width = SZ * width;
int mat_height = SZ * (int)ceil((double)images.size() / width);
if (!images.empty())
{
grid = Mat(Size(mat_width, mat_height), images[0].type());
for (size_t i = 0; i < images.size(); i++)
{
Mat location_on_grid = grid(Rect(SZ * ((int)i % width), SZ * ((int)i / width), SZ, SZ));
images[i].copyTo(location_on_grid);
}
}
}
static void evaluate_model(const vector<float>& predictions, const vector<Mat>& digits, const vector<int>& labels, Mat& mos)
{
double err = 0;
for (size_t i = 0; i < predictions.size(); i++)
{
if ((int)predictions[i] != labels[i])
{
err++;
}
}
err /= predictions.size();
cout << cv::format("error: %.2f %%", err * 100) << endl;
int confusion[10][10] = {};
for (size_t i = 0; i < labels.size(); i++)
{
confusion[labels[i]][(int)predictions[i]]++;
}
cout << "confusion matrix:" << endl;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
cout << cv::format("%2d ", confusion[i][j]);
}
cout << endl;
}
cout << endl;
vector<Mat> vis;
for (size_t i = 0; i < digits.size(); i++)
{
Mat img;
cvtColor(digits[i], img, COLOR_GRAY2BGR);
if ((int)predictions[i] != labels[i])
{
for (int j = 0; j < img.rows; j++)
{
for (int k = 0; k < img.cols; k++)
{
img.at<Vec3b>(j, k)[0] = 0;
img.at<Vec3b>(j, k)[1] = 0;
}
}
}
vis.push_back(img);
}
mosaic(25, vis, mos);
}
static void bincount(const Mat& x, const Mat& weights, const int min_length, vector<double>& bins)
{
double max_x_val = 0;
minMaxLoc(x, NULL, &max_x_val);
bins = vector<double>(max((int)max_x_val, min_length));
for (int i = 0; i < x.rows; i++)
{
for (int j = 0; j < x.cols; j++)
{
bins[x.at<int>(i, j)] += weights.at<float>(i, j);
}
}
}
static void preprocess_hog(const vector<Mat>& digits, Mat& hog)
{
int bin_n = 16;
int half_cell = SZ / 2;
double eps = 1e-7;
hog = Mat(Size(4 * bin_n, (int)digits.size()), CV_32F);
for (size_t img_index = 0; img_index < digits.size(); img_index++)
{
Mat gx;
Sobel(digits[img_index], gx, CV_32F, 1, 0);
Mat gy;
Sobel(digits[img_index], gy, CV_32F, 0, 1);
Mat mag;
Mat ang;
cartToPolar(gx, gy, mag, ang);
Mat bin(ang.size(), CV_32S);
for (int i = 0; i < ang.rows; i++)
{
for (int j = 0; j < ang.cols; j++)
{
bin.at<int>(i, j) = (int)(bin_n * ang.at<float>(i, j) / (2 * CV_PI));
}
}
Mat bin_cells[] = {
bin(Rect(0, 0, half_cell, half_cell)),
bin(Rect(half_cell, 0, half_cell, half_cell)),
bin(Rect(0, half_cell, half_cell, half_cell)),
bin(Rect(half_cell, half_cell, half_cell, half_cell))
};
Mat mag_cells[] = {
mag(Rect(0, 0, half_cell, half_cell)),
mag(Rect(half_cell, 0, half_cell, half_cell)),
mag(Rect(0, half_cell, half_cell, half_cell)),
mag(Rect(half_cell, half_cell, half_cell, half_cell))
};
vector<double> hist;
hist.reserve(4 * bin_n);
for (int i = 0; i < 4; i++)
{
vector<double> partial_hist;
bincount(bin_cells[i], mag_cells[i], bin_n, partial_hist);
hist.insert(hist.end(), partial_hist.begin(), partial_hist.end());
}
// transform to Hellinger kernel
double sum = 0;
for (size_t i = 0; i < hist.size(); i++)
{
sum += hist[i];
}
for (size_t i = 0; i < hist.size(); i++)
{
hist[i] /= sum + eps;
hist[i] = sqrt(hist[i]);
}
double hist_norm = norm(hist);
for (size_t i = 0; i < hist.size(); i++)
{
hog.at<float>((int)img_index, (int)i) = (float)(hist[i] / (hist_norm + eps));
}
}
}
static void shuffle(vector<Mat>& digits, vector<int>& labels)
{
vector<int> shuffled_indexes(digits.size());
for (size_t i = 0; i < digits.size(); i++)
{
shuffled_indexes[i] = (int)i;
}
randShuffle(shuffled_indexes);
vector<Mat> shuffled_digits(digits.size());
vector<int> shuffled_labels(labels.size());
for (size_t i = 0; i < shuffled_indexes.size(); i++)
{
shuffled_digits[shuffled_indexes[i]] = digits[i];
shuffled_labels[shuffled_indexes[i]] = labels[i];
}
digits = shuffled_digits;
labels = shuffled_labels;
}
int main(int /* argc */, char* argv[])
{
help(argv);
vector<Mat> digits;
vector<int> labels;
load_digits(DIGITS_FN, digits, labels);
cout << "preprocessing..." << endl;
// shuffle digits
shuffle(digits, labels);
vector<Mat> digits2;
for (size_t i = 0; i < digits.size(); i++)
{
Mat deskewed_digit;
deskew(digits[i], deskewed_digit);
digits2.push_back(deskewed_digit);
}
Mat samples;
preprocess_hog(digits2, samples);
int train_n = (int)(0.9 * samples.rows);
Mat test_set;
vector<Mat> digits_test(digits2.begin() + train_n, digits2.end());
mosaic(25, digits_test, test_set);
imshow("test set", test_set);
Mat samples_train = samples(Rect(0, 0, samples.cols, train_n));
Mat samples_test = samples(Rect(0, train_n, samples.cols, samples.rows - train_n));
vector<int> labels_train(labels.begin(), labels.begin() + train_n);
vector<int> labels_test(labels.begin() + train_n, labels.end());
Ptr<ml::KNearest> k_nearest;
Ptr<ml::SVM> svm;
vector<float> predictions;
Mat vis;
cout << "training KNearest..." << endl;
k_nearest = ml::KNearest::create();
k_nearest->train(samples_train, ml::ROW_SAMPLE, labels_train);
// predict digits with KNearest
k_nearest->findNearest(samples_test, 4, predictions);
evaluate_model(predictions, digits_test, labels_test, vis);
imshow("KNearest test", vis);
k_nearest.release();
cout << "training SVM..." << endl;
svm = ml::SVM::create();
svm->setGamma(5.383);
svm->setC(2.67);
svm->setKernel(ml::SVM::RBF);
svm->setType(ml::SVM::C_SVC);
svm->train(samples_train, ml::ROW_SAMPLE, labels_train);
// predict digits with SVM
svm->predict(samples_test, predictions);
evaluate_model(predictions, digits_test, labels_test, vis);
imshow("SVM test", vis);
cout << "Saving SVM as \"digits_svm.yml\"..." << endl;
svm->save("digits_svm.yml");
svm.release();
waitKey();
return 0;
}
+70
View File
@@ -0,0 +1,70 @@
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/ml.hpp"
using namespace cv;
using namespace cv::ml;
int main( int /*argc*/, char** /*argv*/ )
{
const int N = 4;
const int N1 = (int)sqrt((double)N);
const Scalar colors[] =
{
Scalar(0,0,255), Scalar(0,255,0),
Scalar(0,255,255),Scalar(255,255,0)
};
int i, j;
int nsamples = 100;
Mat samples( nsamples, 2, CV_32FC1 );
Mat labels;
Mat img = Mat::zeros( Size( 500, 500 ), CV_8UC3 );
Mat sample( 1, 2, CV_32FC1 );
samples = samples.reshape(2, 0);
for( i = 0; i < N; i++ )
{
// form the training samples
Mat samples_part = samples.rowRange(i*nsamples/N, (i+1)*nsamples/N );
Scalar mean(((i%N1)+1)*img.rows/(N1+1),
((i/N1)+1)*img.rows/(N1+1));
Scalar sigma(30,30);
randn( samples_part, mean, sigma );
}
samples = samples.reshape(1, 0);
// cluster the data
Ptr<EM> em_model = EM::create();
em_model->setClustersNumber(N);
em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 300, 0.1));
em_model->trainEM( samples, noArray(), labels, noArray() );
// classify every image pixel
for( i = 0; i < img.rows; i++ )
{
for( j = 0; j < img.cols; j++ )
{
sample.at<float>(0) = (float)j;
sample.at<float>(1) = (float)i;
int response = cvRound(em_model->predict2( sample, noArray() )[1]);
Scalar c = colors[response];
circle( img, Point(j, i), 1, c*0.75, FILLED );
}
}
//draw the clustered samples
for( i = 0; i < nsamples; i++ )
{
Point pt(cvRound(samples.at<float>(i, 0)), cvRound(samples.at<float>(i, 1)));
circle( img, pt, 1, colors[labels.at<int>(i)], FILLED );
}
imshow( "EM-clustering result", img );
waitKey(0);
return 0;
}
@@ -0,0 +1,81 @@
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main(int, char**)
{
// Set up training data
//! [setup1]
int labels[4] = {1, -1, -1, -1};
float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
//! [setup1]
//! [setup2]
Mat trainingDataMat(4, 2, CV_32F, trainingData);
Mat labelsMat(4, 1, CV_32SC1, labels);
//! [setup2]
// Train the SVM
//! [init]
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
//! [init]
//! [train]
svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);
//! [train]
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
// Show the decision regions given by the SVM
//! [show]
Vec3b green(0,255,0), blue(255,0,0);
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
Mat sampleMat = (Mat_<float>(1,2) << j,i);
float response = svm->predict(sampleMat);
if (response == 1)
image.at<Vec3b>(i,j) = green;
else if (response == -1)
image.at<Vec3b>(i,j) = blue;
}
}
//! [show]
// Show the training data
//! [show_data]
int thickness = -1;
circle( image, Point(501, 10), 5, Scalar( 0, 0, 0), thickness );
circle( image, Point(255, 10), 5, Scalar(255, 255, 255), thickness );
circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness );
circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness );
//! [show_data]
// Show support vectors
//! [show_vectors]
thickness = 2;
Mat sv = svm->getUncompressedSupportVectors();
for (int i = 0; i < sv.rows; i++)
{
const float* v = sv.ptr<float>(i);
circle(image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness);
}
//! [show_vectors]
imwrite("result.png", image); // save the image
imshow("SVM Simple Example", image); // show it to the user
waitKey();
return 0;
}
@@ -0,0 +1,99 @@
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.TermCriteria;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.ml.Ml;
import org.opencv.ml.SVM;
public class IntroductionToSVMDemo {
public static void main(String[] args) {
// Load the native OpenCV library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Set up training data
//! [setup1]
int[] labels = { 1, -1, -1, -1 };
float[] trainingData = { 501, 10, 255, 10, 501, 255, 10, 501 };
//! [setup1]
//! [setup2]
Mat trainingDataMat = new Mat(4, 2, CvType.CV_32FC1);
trainingDataMat.put(0, 0, trainingData);
Mat labelsMat = new Mat(4, 1, CvType.CV_32SC1);
labelsMat.put(0, 0, labels);
//! [setup2]
// Train the SVM
//! [init]
SVM svm = SVM.create();
svm.setType(SVM.C_SVC);
svm.setKernel(SVM.LINEAR);
svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 100, 1e-6));
//! [init]
//! [train]
svm.train(trainingDataMat, Ml.ROW_SAMPLE, labelsMat);
//! [train]
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat.zeros(height, width, CvType.CV_8UC3);
// Show the decision regions given by the SVM
//! [show]
byte[] imageData = new byte[(int) (image.total() * image.channels())];
Mat sampleMat = new Mat(1, 2, CvType.CV_32F);
float[] sampleMatData = new float[(int) (sampleMat.total() * sampleMat.channels())];
for (int i = 0; i < image.rows(); i++) {
for (int j = 0; j < image.cols(); j++) {
sampleMatData[0] = j;
sampleMatData[1] = i;
sampleMat.put(0, 0, sampleMatData);
float response = svm.predict(sampleMat);
if (response == 1) {
imageData[(i * image.cols() + j) * image.channels()] = 0;
imageData[(i * image.cols() + j) * image.channels() + 1] = (byte) 255;
imageData[(i * image.cols() + j) * image.channels() + 2] = 0;
} else if (response == -1) {
imageData[(i * image.cols() + j) * image.channels()] = (byte) 255;
imageData[(i * image.cols() + j) * image.channels() + 1] = 0;
imageData[(i * image.cols() + j) * image.channels() + 2] = 0;
}
}
}
image.put(0, 0, imageData);
//! [show]
// Show the training data
//! [show_data]
int thickness = -1;
int lineType = Imgproc.LINE_8;
Imgproc.circle(image, new Point(501, 10), 5, new Scalar(0, 0, 0), thickness, lineType, 0);
Imgproc.circle(image, new Point(255, 10), 5, new Scalar(255, 255, 255), thickness, lineType, 0);
Imgproc.circle(image, new Point(501, 255), 5, new Scalar(255, 255, 255), thickness, lineType, 0);
Imgproc.circle(image, new Point(10, 501), 5, new Scalar(255, 255, 255), thickness, lineType, 0);
//! [show_data]
// Show support vectors
//! [show_vectors]
thickness = 2;
Mat sv = svm.getUncompressedSupportVectors();
float[] svData = new float[(int) (sv.total() * sv.channels())];
sv.get(0, 0, svData);
for (int i = 0; i < sv.rows(); ++i) {
Imgproc.circle(image, new Point(svData[i * sv.cols()], svData[i * sv.cols() + 1]), 6,
new Scalar(128, 128, 128), thickness, lineType, 0);
}
//! [show_vectors]
Imgcodecs.imwrite("result.png", image); // save the image
HighGui.imshow("SVM Simple Example", image); // show it to the user
HighGui.waitKey();
System.exit(0);
}
}
@@ -0,0 +1,186 @@
import java.util.Random;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.TermCriteria;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.ml.Ml;
import org.opencv.ml.SVM;
public class NonLinearSVMsDemo {
public static final int NTRAINING_SAMPLES = 100;
public static final float FRAC_LINEAR_SEP = 0.9f;
public static void main(String[] args) {
// Load the native OpenCV library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("\n--------------------------------------------------------------------------");
System.out.println("This program shows Support Vector Machines for Non-Linearly Separable Data. ");
System.out.println("--------------------------------------------------------------------------\n");
// Data for visual representation
int width = 512, height = 512;
Mat I = Mat.zeros(height, width, CvType.CV_8UC3);
// --------------------- 1. Set up training data randomly---------------------------------------
Mat trainData = new Mat(2 * NTRAINING_SAMPLES, 2, CvType.CV_32F);
Mat labels = new Mat(2 * NTRAINING_SAMPLES, 1, CvType.CV_32S);
Random rng = new Random(100); // Random value generation class
// Set up the linearly separable part of the training data
int nLinearSamples = (int) (FRAC_LINEAR_SEP * NTRAINING_SAMPLES);
//! [setup1]
// Generate random points for the class 1
Mat trainClass = trainData.rowRange(0, nLinearSamples);
// The x coordinate of the points is in [0, 0.4)
Mat c = trainClass.colRange(0, 1);
float[] cData = new float[(int) (c.total() * c.channels())];
double[] cDataDbl = rng.doubles(cData.length, 0, 0.4f * width).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1, 2);
cData = new float[(int) (c.total() * c.channels())];
cDataDbl = rng.doubles(cData.length, 0, height).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
// Generate random points for the class 2
trainClass = trainData.rowRange(2 * NTRAINING_SAMPLES - nLinearSamples, 2 * NTRAINING_SAMPLES);
// The x coordinate of the points is in [0.6, 1]
c = trainClass.colRange(0, 1);
cData = new float[(int) (c.total() * c.channels())];
cDataDbl = rng.doubles(cData.length, 0.6 * width, width).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1, 2);
cData = new float[(int) (c.total() * c.channels())];
cDataDbl = rng.doubles(cData.length, 0, height).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
//! [setup1]
// ------------------ Set up the non-linearly separable part of the training data ---------------
//! [setup2]
// Generate random points for the classes 1 and 2
trainClass = trainData.rowRange(nLinearSamples, 2 * NTRAINING_SAMPLES - nLinearSamples);
// The x coordinate of the points is in [0.4, 0.6)
c = trainClass.colRange(0, 1);
cData = new float[(int) (c.total() * c.channels())];
cDataDbl = rng.doubles(cData.length, 0.4 * width, 0.6 * width).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1, 2);
cData = new float[(int) (c.total() * c.channels())];
cDataDbl = rng.doubles(cData.length, 0, height).toArray();
for (int i = 0; i < cData.length; i++) {
cData[i] = (float) cDataDbl[i];
}
c.put(0, 0, cData);
//! [setup2]
// ------------------------- Set up the labels for the classes---------------------------------
labels.rowRange(0, NTRAINING_SAMPLES).setTo(new Scalar(1)); // Class 1
labels.rowRange(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES).setTo(new Scalar(2)); // Class 2
// ------------------------ 2. Set up the support vector machines parameters--------------------
System.out.println("Starting training process");
//! [init]
SVM svm = SVM.create();
svm.setType(SVM.C_SVC);
svm.setC(0.1);
svm.setKernel(SVM.LINEAR);
svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, (int) 1e7, 1e-6));
//! [init]
// ------------------------ 3. Train the svm----------------------------------------------------
//! [train]
svm.train(trainData, Ml.ROW_SAMPLE, labels);
//! [train]
System.out.println("Finished training process");
// ------------------------ 4. Show the decision regions----------------------------------------
//! [show]
byte[] IData = new byte[(int) (I.total() * I.channels())];
Mat sampleMat = new Mat(1, 2, CvType.CV_32F);
float[] sampleMatData = new float[(int) (sampleMat.total() * sampleMat.channels())];
for (int i = 0; i < I.rows(); i++) {
for (int j = 0; j < I.cols(); j++) {
sampleMatData[0] = j;
sampleMatData[1] = i;
sampleMat.put(0, 0, sampleMatData);
float response = svm.predict(sampleMat);
if (response == 1) {
IData[(i * I.cols() + j) * I.channels()] = 0;
IData[(i * I.cols() + j) * I.channels() + 1] = 100;
IData[(i * I.cols() + j) * I.channels() + 2] = 0;
} else if (response == 2) {
IData[(i * I.cols() + j) * I.channels()] = 100;
IData[(i * I.cols() + j) * I.channels() + 1] = 0;
IData[(i * I.cols() + j) * I.channels() + 2] = 0;
}
}
}
I.put(0, 0, IData);
//! [show]
// ----------------------- 5. Show the training data--------------------------------------------
//! [show_data]
int thick = -1;
int lineType = Imgproc.LINE_8;
float px, py;
// Class 1
float[] trainDataData = new float[(int) (trainData.total() * trainData.channels())];
trainData.get(0, 0, trainDataData);
for (int i = 0; i < NTRAINING_SAMPLES; i++) {
px = trainDataData[i * trainData.cols()];
py = trainDataData[i * trainData.cols() + 1];
Imgproc.circle(I, new Point(px, py), 3, new Scalar(0, 255, 0), thick, lineType, 0);
}
// Class 2
for (int i = NTRAINING_SAMPLES; i < 2 * NTRAINING_SAMPLES; ++i) {
px = trainDataData[i * trainData.cols()];
py = trainDataData[i * trainData.cols() + 1];
Imgproc.circle(I, new Point(px, py), 3, new Scalar(255, 0, 0), thick, lineType, 0);
}
//! [show_data]
// ------------------------- 6. Show support vectors--------------------------------------------
//! [show_vectors]
thick = 2;
Mat sv = svm.getUncompressedSupportVectors();
float[] svData = new float[(int) (sv.total() * sv.channels())];
sv.get(0, 0, svData);
for (int i = 0; i < sv.rows(); i++) {
Imgproc.circle(I, new Point(svData[i * sv.cols()], svData[i * sv.cols() + 1]), 6, new Scalar(128, 128, 128),
thick, lineType, 0);
}
//! [show_vectors]
Imgcodecs.imwrite("result.png", I); // save the Image
HighGui.imshow("SVM for Non-Linear Training Data", I); // show it to the user
HighGui.waitKey();
System.exit(0);
}
}
+558
View File
@@ -0,0 +1,558 @@
#include "opencv2/core.hpp"
#include "opencv2/ml.hpp"
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;
static void help(char** argv)
{
printf("\nThe sample demonstrates how to train Random Trees classifier\n"
"(or Boosting classifier, or MLP, or Knearest, or Nbayes, or Support Vector Machines - see main()) using the provided dataset.\n"
"\n"
"We use the sample database letter-recognition.data\n"
"from UCI Repository, here is the link:\n"
"\n"
"Newman, D.J. & Hettich, S. & Blake, C.L. & Merz, C.J. (1998).\n"
"UCI Repository of machine learning databases\n"
"[http://www.ics.uci.edu/~mlearn/MLRepository.html].\n"
"Irvine, CA: University of California, Department of Information and Computer Science.\n"
"\n"
"The dataset consists of 20000 feature vectors along with the\n"
"responses - capital latin letters A..Z.\n"
"The first 16000 (10000 for boosting)) samples are used for training\n"
"and the remaining 4000 (10000 for boosting) - to test the classifier.\n"
"======================================================\n");
printf("\nThis is letter recognition sample.\n"
"The usage: %s [-data=<path to letter-recognition.data>] \\\n"
" [-save=<output XML file for the classifier>] \\\n"
" [-load=<XML file with the pre-trained classifier>] \\\n"
" [-boost|-mlp|-knearest|-nbayes|-svm] # to use boost/mlp/knearest/SVM classifier instead of default Random Trees\n", argv[0] );
}
// This function reads data and responses from the file <filename>
static bool
read_num_class_data( const string& filename, int var_count,
Mat* _data, Mat* _responses )
{
const int M = 1024;
char buf[M+2];
Mat el_ptr(1, var_count, CV_32F);
int i;
vector<int> responses;
_data->release();
_responses->release();
FILE* f = fopen( filename.c_str(), "rt" );
if( !f )
{
cout << "Could not read the database " << filename << endl;
return false;
}
for(;;)
{
char* ptr;
if( !fgets( buf, M, f ) || !strchr( buf, ',' ) )
break;
responses.push_back((int)buf[0]);
ptr = buf+2;
for( i = 0; i < var_count; i++ )
{
int n = 0;
sscanf( ptr, "%f%n", &el_ptr.at<float>(i), &n );
ptr += n + 1;
}
if( i < var_count )
break;
_data->push_back(el_ptr);
}
fclose(f);
Mat(responses).copyTo(*_responses);
cout << "The database " << filename << " is loaded.\n";
return true;
}
template<typename T>
static Ptr<T> load_classifier(const string& filename_to_load)
{
// load classifier from the specified file
Ptr<T> model = StatModel::load<T>( filename_to_load );
if( model.empty() )
cout << "Could not read the classifier " << filename_to_load << endl;
else
cout << "The classifier " << filename_to_load << " is loaded.\n";
return model;
}
static Ptr<TrainData>
prepare_train_data(const Mat& data, const Mat& responses, int ntrain_samples)
{
Mat sample_idx = Mat::zeros( 1, data.rows, CV_8U );
Mat train_samples = sample_idx.colRange(0, ntrain_samples);
train_samples.setTo(Scalar::all(1));
int nvars = data.cols;
Mat var_type( nvars + 1, 1, CV_8U );
var_type.setTo(Scalar::all(VAR_ORDERED));
var_type.at<uchar>(nvars) = VAR_CATEGORICAL;
return TrainData::create(data, ROW_SAMPLE, responses,
noArray(), sample_idx, noArray(), var_type);
}
inline TermCriteria TC(int iters, double eps)
{
return TermCriteria(TermCriteria::MAX_ITER + (eps > 0 ? TermCriteria::EPS : 0), iters, eps);
}
static void test_and_save_classifier(const Ptr<StatModel>& model,
const Mat& data, const Mat& responses,
int ntrain_samples, int rdelta,
const string& filename_to_save)
{
int i, nsamples_all = data.rows;
double train_hr = 0, test_hr = 0;
// compute prediction error on train and test data
for( i = 0; i < nsamples_all; i++ )
{
Mat sample = data.row(i);
float r = model->predict( sample );
r = std::abs(r + rdelta - responses.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;
if( i < ntrain_samples )
train_hr += r;
else
test_hr += r;
}
test_hr /= nsamples_all - ntrain_samples;
train_hr = ntrain_samples > 0 ? train_hr/ntrain_samples : 1.;
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. );
if( !filename_to_save.empty() )
{
model->save( filename_to_save );
}
}
static bool
build_rtrees_classifier( const string& data_filename,
const string& filename_to_save,
const string& filename_to_load )
{
Mat data;
Mat responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
Ptr<RTrees> model;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.8);
// Create or load Random Trees classifier
if( !filename_to_load.empty() )
{
model = load_classifier<RTrees>(filename_to_load);
if( model.empty() )
return false;
ntrain_samples = 0;
}
else
{
// create classifier by using <data> and <responses>
cout << "Training the classifier ...\n";
// Params( int maxDepth, int minSampleCount,
// double regressionAccuracy, bool useSurrogates,
// int maxCategories, const Mat& priors,
// bool calcVarImportance, int nactiveVars,
// TermCriteria termCrit );
Ptr<TrainData> tdata = prepare_train_data(data, responses, ntrain_samples);
model = RTrees::create();
model->setMaxDepth(10);
model->setMinSampleCount(10);
model->setRegressionAccuracy(0);
model->setUseSurrogates(false);
model->setMaxCategories(15);
model->setPriors(Mat());
model->setCalculateVarImportance(true);
model->setActiveVarCount(4);
model->setTermCriteria(TC(100,0.01f));
model->train(tdata);
cout << endl;
}
test_and_save_classifier(model, data, responses, ntrain_samples, 0, filename_to_save);
cout << "Number of trees: " << model->getRoots().size() << endl;
// Print variable importance
Mat var_importance = model->getVarImportance();
if( !var_importance.empty() )
{
double rt_imp_sum = sum( var_importance )[0];
printf("var#\timportance (in %%):\n");
int i, n = (int)var_importance.total();
for( i = 0; i < n; i++ )
printf( "%-2d\t%-4.1f\n", i, 100.f*var_importance.at<float>(i)/rt_imp_sum);
}
return true;
}
static bool
build_boost_classifier( const string& data_filename,
const string& filename_to_save,
const string& filename_to_load )
{
const int class_count = 26;
Mat data;
Mat responses;
Mat weak_responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
int i, j, k;
Ptr<Boost> model;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.5);
int var_count = data.cols;
// Create or load Boosted Tree classifier
if( !filename_to_load.empty() )
{
model = load_classifier<Boost>(filename_to_load);
if( model.empty() )
return false;
ntrain_samples = 0;
}
else
{
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// As currently boosted tree classifier in MLL can only be trained
// for 2-class problems, we transform the training database by
// "unrolling" each training sample as many times as the number of
// classes (26) that we have.
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Mat new_data( ntrain_samples*class_count, var_count + 1, CV_32F );
Mat new_responses( ntrain_samples*class_count, 1, CV_32S );
// 1. unroll the database type mask
printf( "Unrolling the database...\n");
for( i = 0; i < ntrain_samples; i++ )
{
const float* data_row = data.ptr<float>(i);
for( j = 0; j < class_count; j++ )
{
float* new_data_row = (float*)new_data.ptr<float>(i*class_count+j);
memcpy(new_data_row, data_row, var_count*sizeof(data_row[0]));
new_data_row[var_count] = (float)j;
new_responses.at<int>(i*class_count + j) = responses.at<int>(i) == j+'A';
}
}
Mat var_type( 1, var_count + 2, CV_8U );
var_type.setTo(Scalar::all(VAR_ORDERED));
var_type.at<uchar>(var_count) = var_type.at<uchar>(var_count+1) = VAR_CATEGORICAL;
Ptr<TrainData> tdata = TrainData::create(new_data, ROW_SAMPLE, new_responses,
noArray(), noArray(), noArray(), var_type);
vector<double> priors(2);
priors[0] = 1;
priors[1] = 26;
cout << "Training the classifier (may take a few minutes)...\n";
model = Boost::create();
model->setBoostType(Boost::GENTLE);
model->setWeakCount(100);
model->setWeightTrimRate(0.95);
model->setMaxDepth(5);
model->setUseSurrogates(false);
model->setPriors(Mat(priors));
model->train(tdata);
cout << endl;
}
Mat temp_sample( 1, var_count + 1, CV_32F );
float* tptr = temp_sample.ptr<float>();
// compute prediction error on train and test data
double train_hr = 0, test_hr = 0;
for( i = 0; i < nsamples_all; i++ )
{
int best_class = 0;
double max_sum = -DBL_MAX;
const float* ptr = data.ptr<float>(i);
for( k = 0; k < var_count; k++ )
tptr[k] = ptr[k];
for( j = 0; j < class_count; j++ )
{
tptr[var_count] = (float)j;
float s = model->predict( temp_sample, noArray(), StatModel::RAW_OUTPUT );
if( max_sum < s )
{
max_sum = s;
best_class = j + 'A';
}
}
double r = std::abs(best_class - responses.at<int>(i)) < FLT_EPSILON ? 1 : 0;
if( i < ntrain_samples )
train_hr += r;
else
test_hr += r;
}
test_hr /= nsamples_all-ntrain_samples;
train_hr = ntrain_samples > 0 ? train_hr/ntrain_samples : 1.;
printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
train_hr*100., test_hr*100. );
cout << "Number of trees: " << model->getRoots().size() << endl;
// Save classifier to file if needed
if( !filename_to_save.empty() )
model->save( filename_to_save );
return true;
}
static bool
build_mlp_classifier( const string& data_filename,
const string& filename_to_save,
const string& filename_to_load )
{
const int class_count = 26;
Mat data;
Mat responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
Ptr<ANN_MLP> model;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.8);
// Create or load MLP classifier
if( !filename_to_load.empty() )
{
model = load_classifier<ANN_MLP>(filename_to_load);
if( model.empty() )
return false;
ntrain_samples = 0;
}
else
{
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// MLP does not support categorical variables by explicitly.
// So, instead of the output class label, we will use
// a binary vector of <class_count> components for training and,
// therefore, MLP will give us a vector of "probabilities" at the
// prediction stage
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Mat train_data = data.rowRange(0, ntrain_samples);
Mat train_responses = Mat::zeros( ntrain_samples, class_count, CV_32F );
// 1. unroll the responses
cout << "Unrolling the responses...\n";
for( int i = 0; i < ntrain_samples; i++ )
{
int cls_label = responses.at<int>(i) - 'A';
train_responses.at<float>(i, cls_label) = 1.f;
}
// 2. train classifier
int layer_sz[] = { data.cols, 100, 100, class_count };
int nlayers = (int)(sizeof(layer_sz)/sizeof(layer_sz[0]));
Mat layer_sizes( 1, nlayers, CV_32S, layer_sz );
#if 1
int method = ANN_MLP::BACKPROP;
double method_param = 0.001;
int max_iter = 300;
#else
int method = ANN_MLP::RPROP;
double method_param = 0.1;
int max_iter = 1000;
#endif
Ptr<TrainData> tdata = TrainData::create(train_data, ROW_SAMPLE, train_responses);
cout << "Training the classifier (may take a few minutes)...\n";
model = ANN_MLP::create();
model->setLayerSizes(layer_sizes);
model->setActivationFunction(ANN_MLP::SIGMOID_SYM, 0, 0);
model->setTermCriteria(TC(max_iter,0));
model->setTrainMethod(method, method_param);
model->train(tdata);
cout << endl;
}
test_and_save_classifier(model, data, responses, ntrain_samples, 'A', filename_to_save);
return true;
}
static bool
build_knearest_classifier( const string& data_filename, int K )
{
Mat data;
Mat responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.8);
// create classifier by using <data> and <responses>
cout << "Training the classifier ...\n";
Ptr<TrainData> tdata = prepare_train_data(data, responses, ntrain_samples);
Ptr<KNearest> model = KNearest::create();
model->setDefaultK(K);
model->setIsClassifier(true);
model->train(tdata);
cout << endl;
test_and_save_classifier(model, data, responses, ntrain_samples, 0, string());
return true;
}
static bool
build_nbayes_classifier( const string& data_filename )
{
Mat data;
Mat responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
Ptr<NormalBayesClassifier> model;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.8);
// create classifier by using <data> and <responses>
cout << "Training the classifier ...\n";
Ptr<TrainData> tdata = prepare_train_data(data, responses, ntrain_samples);
model = NormalBayesClassifier::create();
model->train(tdata);
cout << endl;
test_and_save_classifier(model, data, responses, ntrain_samples, 0, string());
return true;
}
static bool
build_svm_classifier( const string& data_filename,
const string& filename_to_save,
const string& filename_to_load )
{
Mat data;
Mat responses;
bool ok = read_num_class_data( data_filename, 16, &data, &responses );
if( !ok )
return ok;
Ptr<SVM> model;
int nsamples_all = data.rows;
int ntrain_samples = (int)(nsamples_all*0.8);
// Create or load Random Trees classifier
if( !filename_to_load.empty() )
{
model = load_classifier<SVM>(filename_to_load);
if( model.empty() )
return false;
ntrain_samples = 0;
}
else
{
// create classifier by using <data> and <responses>
cout << "Training the classifier ...\n";
Ptr<TrainData> tdata = prepare_train_data(data, responses, ntrain_samples);
model = SVM::create();
model->setType(SVM::C_SVC);
model->setKernel(SVM::LINEAR);
model->setC(1);
model->train(tdata);
cout << endl;
}
test_and_save_classifier(model, data, responses, ntrain_samples, 0, filename_to_save);
return true;
}
int main( int argc, char *argv[] )
{
string filename_to_save = "";
string filename_to_load = "";
string data_filename;
int method = 0;
cv::CommandLineParser parser(argc, argv, "{data|letter-recognition.data|}{save||}{load||}{boost||}"
"{mlp||}{knn knearest||}{nbayes||}{svm||}");
data_filename = samples::findFile(parser.get<string>("data"));
if (parser.has("save"))
filename_to_save = parser.get<string>("save");
if (parser.has("load"))
filename_to_load = samples::findFile(parser.get<string>("load"));
if (parser.has("boost"))
method = 1;
else if (parser.has("mlp"))
method = 2;
else if (parser.has("knearest"))
method = 3;
else if (parser.has("nbayes"))
method = 4;
else if (parser.has("svm"))
method = 5;
help(argv);
if( (method == 0 ?
build_rtrees_classifier( data_filename, filename_to_save, filename_to_load ) :
method == 1 ?
build_boost_classifier( data_filename, filename_to_save, filename_to_load ) :
method == 2 ?
build_mlp_classifier( data_filename, filename_to_save, filename_to_load ) :
method == 3 ?
build_knearest_classifier( data_filename, 10 ) :
method == 4 ?
build_nbayes_classifier( data_filename) :
method == 5 ?
build_svm_classifier( data_filename, filename_to_save, filename_to_load ):
-1) < 0)
return 0;
}
+127
View File
@@ -0,0 +1,127 @@
// Logistic Regression sample
// AUTHOR: Rahul Kavi rahulkavi[at]live[at]com
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/ml.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
using namespace cv::ml;
static void showImage(const Mat &data, int columns, const String &name)
{
Mat bigImage;
for(int i = 0; i < data.rows; ++i)
{
bigImage.push_back(data.row(i).reshape(0, columns));
}
imshow(name, bigImage.t());
}
static float calculateAccuracyPercent(const Mat &original, const Mat &predicted)
{
return 100 * (float)countNonZero(original == predicted) / predicted.rows;
}
int main()
{
const String filename = samples::findFile("data01.xml");
cout << "**********************************************************************" << endl;
cout << filename
<< " contains digits 0 and 1 of 20 samples each, collected on an Android device" << endl;
cout << "Each of the collected images are of size 28 x 28 re-arranged to 1 x 784 matrix"
<< endl;
cout << "**********************************************************************" << endl;
Mat data, labels;
{
cout << "loading the dataset...";
FileStorage f;
if(f.open(filename, FileStorage::READ))
{
f["datamat"] >> data;
f["labelsmat"] >> labels;
f.release();
}
else
{
cerr << "file can not be opened: " << filename << endl;
return 1;
}
data.convertTo(data, CV_32F);
labels.convertTo(labels, CV_32F);
cout << "read " << data.rows << " rows of data" << endl;
}
Mat data_train, data_test;
Mat labels_train, labels_test;
for(int i = 0; i < data.rows; i++)
{
if(i % 2 == 0)
{
data_train.push_back(data.row(i));
labels_train.push_back(labels.row(i));
}
else
{
data_test.push_back(data.row(i));
labels_test.push_back(labels.row(i));
}
}
cout << "training/testing samples count: " << data_train.rows << "/" << data_test.rows << endl;
// display sample image
showImage(data_train, 28, "train data");
showImage(data_test, 28, "test data");
// simple case with batch gradient
cout << "training...";
//! [init]
Ptr<LogisticRegression> lr1 = LogisticRegression::create();
lr1->setLearningRate(0.001);
lr1->setIterations(10);
lr1->setRegularization(LogisticRegression::REG_L2);
lr1->setTrainMethod(LogisticRegression::BATCH);
lr1->setMiniBatchSize(1);
//! [init]
lr1->train(data_train, ROW_SAMPLE, labels_train);
cout << "done!" << endl;
cout << "predicting...";
Mat responses;
lr1->predict(data_test, responses);
cout << "done!" << endl;
// show prediction report
cout << "original vs predicted:" << endl;
labels_test.convertTo(labels_test, CV_32S);
cout << labels_test.t() << endl;
cout << responses.t() << endl;
cout << "accuracy: " << calculateAccuracyPercent(labels_test, responses) << "%" << endl;
// save the classifier
const String saveFilename = "NewLR_Trained.xml";
cout << "saving the classifier to " << saveFilename << endl;
lr1->save(saveFilename);
// load the classifier onto new object
cout << "loading a new classifier from " << saveFilename << endl;
Ptr<LogisticRegression> lr2 = StatModel::load<LogisticRegression>(saveFilename);
// predict using loaded classifier
cout << "predicting the dataset using the loaded classifier...";
Mat responses2;
lr2->predict(data_test, responses2);
cout << "done!" << endl;
// calculate accuracy
cout << labels_test.t() << endl;
cout << responses2.t() << endl;
cout << "accuracy: " << calculateAccuracyPercent(labels_test, responses2) << "%" << endl;
waitKey(0);
return 0;
}
+66
View File
@@ -0,0 +1,66 @@
//#include <opencv2/ml/ml.hpp>
#include <opencv2/ml.hpp>
using namespace std;
using namespace cv;
using namespace cv::ml;
int main()
{
//create random training data
Mat_<float> data(100, 100);
randn(data, Mat::zeros(1, 1, data.type()), Mat::ones(1, 1, data.type()));
//half of the samples for each class
Mat_<float> responses(data.rows, 2);
for (int i = 0; i<data.rows; ++i)
{
if (i < data.rows/2)
{
responses(i, 0) = 1;
responses(i, 1) = 0;
}
else
{
responses(i, 0) = 0;
responses(i, 1) = 1;
}
}
/*
//example code for just a single response (regression)
Mat_<float> responses(data.rows, 1);
for (int i=0; i<responses.rows; ++i)
responses(i, 0) = i < responses.rows / 2 ? 0 : 1;
*/
//create the neural network
Mat_<int> layerSizes(1, 3);
layerSizes(0, 0) = data.cols;
layerSizes(0, 1) = 20;
layerSizes(0, 2) = responses.cols;
Ptr<ANN_MLP> network = ANN_MLP::create();
network->setLayerSizes(layerSizes);
network->setActivationFunction(ANN_MLP::SIGMOID_SYM, 0.1, 0.1);
network->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
Ptr<TrainData> trainData = TrainData::create(data, ROW_SAMPLE, responses);
network->train(trainData);
if (network->isTrained())
{
printf("Predict one-vector:\n");
Mat result;
network->predict(Mat::ones(1, data.cols, data.type()), result);
cout << result << endl;
printf("Predict training data:\n");
for (int i=0; i<data.rows; ++i)
{
network->predict(data.row(i), result);
cout << result << endl;
}
}
return 0;
}
+144
View File
@@ -0,0 +1,144 @@
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
using namespace std;
static void help()
{
cout<< "\n--------------------------------------------------------------------------" << endl
<< "This program shows Support Vector Machines for Non-Linearly Separable Data. " << endl
<< "--------------------------------------------------------------------------" << endl
<< endl;
}
int main()
{
help();
const int NTRAINING_SAMPLES = 100; // Number of training samples per class
const float FRAC_LINEAR_SEP = 0.9f; // Fraction of samples which compose the linear separable part
// Data for visual representation
const int WIDTH = 512, HEIGHT = 512;
Mat I = Mat::zeros(HEIGHT, WIDTH, CV_8UC3);
//--------------------- 1. Set up training data randomly ---------------------------------------
Mat trainData(2*NTRAINING_SAMPLES, 2, CV_32F);
Mat labels (2*NTRAINING_SAMPLES, 1, CV_32S);
RNG rng(100); // Random value generation class
// Set up the linearly separable part of the training data
int nLinearSamples = (int) (FRAC_LINEAR_SEP * NTRAINING_SAMPLES);
//! [setup1]
// Generate random points for the class 1
Mat trainClass = trainData.rowRange(0, nLinearSamples);
// The x coordinate of the points is in [0, 0.4)
Mat c = trainClass.colRange(0, 1);
rng.fill(c, RNG::UNIFORM, Scalar(0), Scalar(0.4 * WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(0), Scalar(HEIGHT));
// Generate random points for the class 2
trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES);
// The x coordinate of the points is in [0.6, 1]
c = trainClass.colRange(0 , 1);
rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(0), Scalar(HEIGHT));
//! [setup1]
//------------------ Set up the non-linearly separable part of the training data ---------------
//! [setup2]
// Generate random points for the classes 1 and 2
trainClass = trainData.rowRange(nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples);
// The x coordinate of the points is in [0.4, 0.6)
c = trainClass.colRange(0,1);
rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));
// The y coordinate of the points is in [0, 1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(0), Scalar(HEIGHT));
//! [setup2]
//------------------------- Set up the labels for the classes ---------------------------------
labels.rowRange( 0, NTRAINING_SAMPLES).setTo(1); // Class 1
labels.rowRange(NTRAINING_SAMPLES, 2*NTRAINING_SAMPLES).setTo(2); // Class 2
//------------------------ 2. Set up the support vector machines parameters --------------------
cout << "Starting training process" << endl;
//! [init]
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setC(0.1);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
//! [init]
//------------------------ 3. Train the svm ----------------------------------------------------
//! [train]
svm->train(trainData, ROW_SAMPLE, labels);
//! [train]
cout << "Finished training process" << endl;
//------------------------ 4. Show the decision regions ----------------------------------------
//! [show]
Vec3b green(0,100,0), blue(100,0,0);
for (int i = 0; i < I.rows; i++)
{
for (int j = 0; j < I.cols; j++)
{
Mat sampleMat = (Mat_<float>(1,2) << j, i);
float response = svm->predict(sampleMat);
if (response == 1) I.at<Vec3b>(i,j) = green;
else if (response == 2) I.at<Vec3b>(i,j) = blue;
}
}
//! [show]
//----------------------- 5. Show the training data --------------------------------------------
//! [show_data]
int thick = -1;
float px, py;
// Class 1
for (int i = 0; i < NTRAINING_SAMPLES; i++)
{
px = trainData.at<float>(i,0);
py = trainData.at<float>(i,1);
circle(I, Point( (int) px, (int) py ), 3, Scalar(0, 255, 0), thick);
}
// Class 2
for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; i++)
{
px = trainData.at<float>(i,0);
py = trainData.at<float>(i,1);
circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick);
}
//! [show_data]
//------------------------- 6. Show support vectors --------------------------------------------
//! [show_vectors]
thick = 2;
Mat sv = svm->getUncompressedSupportVectors();
for (int i = 0; i < sv.rows; i++)
{
const float* v = sv.ptr<float>(i);
circle(I, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick);
}
//! [show_vectors]
imwrite("result.png", I); // save the Image
imshow("SVM for Non-Linear Training Data", I); // show it to the user
waitKey();
return 0;
}
+399
View File
@@ -0,0 +1,399 @@
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/ml.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
using namespace std;
using namespace cv;
using namespace cv::ml;
const Scalar WHITE_COLOR = Scalar(255,255,255);
const string winName = "points";
const int testStep = 5;
Mat img, imgDst;
RNG rng;
vector<Point> trainedPoints;
vector<int> trainedPointsMarkers;
const int MAX_CLASSES = 2;
vector<Vec3b> classColors(MAX_CLASSES);
int currentClass = 0;
vector<int> classCounters(MAX_CLASSES);
#define _NBC_ 1 // normal Bayessian classifier
#define _KNN_ 1 // k nearest neighbors classifier
#define _SVM_ 1 // support vectors machine
#define _DT_ 1 // decision tree
#define _BT_ 1 // ADA Boost
#define _GBT_ 0 // gradient boosted trees
#define _RF_ 1 // random forest
#define _ANN_ 1 // artificial neural networks
#define _EM_ 1 // expectation-maximization
static void on_mouse( int event, int x, int y, int /*flags*/, void* )
{
if( img.empty() )
return;
int updateFlag = 0;
if( event == EVENT_LBUTTONUP )
{
trainedPoints.push_back( Point(x,y) );
trainedPointsMarkers.push_back( currentClass );
classCounters[currentClass]++;
updateFlag = true;
}
//draw
if( updateFlag )
{
img = Scalar::all(0);
// draw points
for( size_t i = 0; i < trainedPoints.size(); i++ )
{
Vec3b c = classColors[trainedPointsMarkers[i]];
circle( img, trainedPoints[i], 5, Scalar(c), -1 );
}
imshow( winName, img );
}
}
static Mat prepare_train_samples(const vector<Point>& pts)
{
Mat samples;
Mat(pts).reshape(1, (int)pts.size()).convertTo(samples, CV_32F);
return samples;
}
static Ptr<TrainData> prepare_train_data()
{
Mat samples = prepare_train_samples(trainedPoints);
return TrainData::create(samples, ROW_SAMPLE, Mat(trainedPointsMarkers));
}
static void predict_and_paint(const Ptr<StatModel>& model, Mat& dst)
{
Mat testSample( 1, 2, CV_32FC1 );
for( int y = 0; y < img.rows; y += testStep )
{
for( int x = 0; x < img.cols; x += testStep )
{
testSample.at<float>(0) = (float)x;
testSample.at<float>(1) = (float)y;
int response = (int)model->predict( testSample );
dst.at<Vec3b>(y, x) = classColors[response];
}
}
}
#if _NBC_
static void find_decision_boundary_NBC()
{
// learn classifier
Ptr<NormalBayesClassifier> normalBayesClassifier = StatModel::train<NormalBayesClassifier>(prepare_train_data());
predict_and_paint(normalBayesClassifier, imgDst);
}
#endif
#if _KNN_
static void find_decision_boundary_KNN( int K )
{
Ptr<KNearest> knn = KNearest::create();
knn->setDefaultK(K);
knn->setIsClassifier(true);
knn->train(prepare_train_data());
predict_and_paint(knn, imgDst);
}
#endif
#if _SVM_
static void find_decision_boundary_SVM( double C )
{
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::POLY); //SVM::LINEAR;
svm->setDegree(0.5);
svm->setGamma(1);
svm->setCoef0(1);
svm->setNu(0.5);
svm->setP(0);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 1000, 0.01));
svm->setC(C);
svm->train(prepare_train_data());
predict_and_paint(svm, imgDst);
Mat sv = svm->getSupportVectors();
for( int i = 0; i < sv.rows; i++ )
{
const float* supportVector = sv.ptr<float>(i);
circle( imgDst, Point(saturate_cast<int>(supportVector[0]),saturate_cast<int>(supportVector[1])), 5, Scalar(255,255,255), -1 );
}
}
#endif
#if _DT_
static void find_decision_boundary_DT()
{
Ptr<DTrees> dtree = DTrees::create();
dtree->setMaxDepth(8);
dtree->setMinSampleCount(2);
dtree->setUseSurrogates(false);
dtree->setCVFolds(0); // the number of cross-validation folds
dtree->setUse1SERule(false);
dtree->setTruncatePrunedTree(false);
dtree->train(prepare_train_data());
predict_and_paint(dtree, imgDst);
}
#endif
#if _BT_
static void find_decision_boundary_BT()
{
Ptr<Boost> boost = Boost::create();
boost->setBoostType(Boost::DISCRETE);
boost->setWeakCount(100);
boost->setWeightTrimRate(0.95);
boost->setMaxDepth(2);
boost->setUseSurrogates(false);
boost->setPriors(Mat());
boost->train(prepare_train_data());
predict_and_paint(boost, imgDst);
}
#endif
#if _GBT_
static void find_decision_boundary_GBT()
{
GBTrees::Params params( GBTrees::DEVIANCE_LOSS, // loss_function_type
100, // weak_count
0.1f, // shrinkage
1.0f, // subsample_portion
2, // max_depth
false // use_surrogates )
);
Ptr<GBTrees> gbtrees = StatModel::train<GBTrees>(prepare_train_data(), params);
predict_and_paint(gbtrees, imgDst);
}
#endif
#if _RF_
static void find_decision_boundary_RF()
{
Ptr<RTrees> rtrees = RTrees::create();
rtrees->setMaxDepth(4);
rtrees->setMinSampleCount(2);
rtrees->setRegressionAccuracy(0.f);
rtrees->setUseSurrogates(false);
rtrees->setMaxCategories(16);
rtrees->setPriors(Mat());
rtrees->setCalculateVarImportance(false);
rtrees->setActiveVarCount(1);
rtrees->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 5, 0));
rtrees->train(prepare_train_data());
predict_and_paint(rtrees, imgDst);
}
#endif
#if _ANN_
static void find_decision_boundary_ANN( const Mat& layer_sizes )
{
Mat trainClasses = Mat::zeros( (int)trainedPoints.size(), (int)classColors.size(), CV_32FC1 );
for( int i = 0; i < trainClasses.rows; i++ )
{
trainClasses.at<float>(i, trainedPointsMarkers[i]) = 1.f;
}
Mat samples = prepare_train_samples(trainedPoints);
Ptr<TrainData> tdata = TrainData::create(samples, ROW_SAMPLE, trainClasses);
Ptr<ANN_MLP> ann = ANN_MLP::create();
ann->setLayerSizes(layer_sizes);
ann->setActivationFunction(ANN_MLP::SIGMOID_SYM, 1, 1);
ann->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 300, FLT_EPSILON));
ann->setTrainMethod(ANN_MLP::BACKPROP, 0.001);
ann->train(tdata);
predict_and_paint(ann, imgDst);
}
#endif
#if _EM_
static void find_decision_boundary_EM()
{
img.copyTo( imgDst );
Mat samples = prepare_train_samples(trainedPoints);
int i, j, nmodels = (int)classColors.size();
vector<Ptr<EM> > em_models(nmodels);
Mat modelSamples;
for( i = 0; i < nmodels; i++ )
{
const int componentCount = 3;
modelSamples.release();
for( j = 0; j < samples.rows; j++ )
{
if( trainedPointsMarkers[j] == i )
modelSamples.push_back(samples.row(j));
}
// learn models
if( !modelSamples.empty() )
{
Ptr<EM> em = EM::create();
em->setClustersNumber(componentCount);
em->setCovarianceMatrixType(EM::COV_MAT_DIAGONAL);
em->trainEM(modelSamples, noArray(), noArray(), noArray());
em_models[i] = em;
}
}
// classify coordinate plane points using the bayes classifier, i.e.
// y(x) = arg max_i=1_modelsCount likelihoods_i(x)
Mat testSample(1, 2, CV_32FC1 );
Mat logLikelihoods(1, nmodels, CV_64FC1, Scalar(-DBL_MAX));
for( int y = 0; y < img.rows; y += testStep )
{
for( int x = 0; x < img.cols; x += testStep )
{
testSample.at<float>(0) = (float)x;
testSample.at<float>(1) = (float)y;
for( i = 0; i < nmodels; i++ )
{
if( !em_models[i].empty() )
logLikelihoods.at<double>(i) = em_models[i]->predict2(testSample, noArray())[0];
}
Point maxLoc;
minMaxLoc(logLikelihoods, 0, 0, 0, &maxLoc);
imgDst.at<Vec3b>(y, x) = classColors[maxLoc.x];
}
}
}
#endif
int main()
{
cout << "Use:" << endl
<< " key '0' .. '1' - switch to class #n" << endl
<< " left mouse button - to add new point;" << endl
<< " key 'r' - to run the ML model;" << endl
<< " key 'i' - to init (clear) the data." << endl << endl;
cv::namedWindow( "points", 1 );
img.create( 480, 640, CV_8UC3 );
imgDst.create( 480, 640, CV_8UC3 );
imshow( "points", img );
setMouseCallback( "points", on_mouse );
classColors[0] = Vec3b(0, 255, 0);
classColors[1] = Vec3b(0, 0, 255);
for(;;)
{
char key = (char)waitKey();
if( key == 27 ) break;
if( key == 'i' ) // init
{
img = Scalar::all(0);
trainedPoints.clear();
trainedPointsMarkers.clear();
classCounters.assign(MAX_CLASSES, 0);
imshow( winName, img );
}
if( key == '0' || key == '1' )
{
currentClass = key - '0';
}
if( key == 'r' ) // run
{
double minVal = 0;
minMaxLoc(classCounters, &minVal, 0, 0, 0);
if( minVal == 0 )
{
printf("each class should have at least 1 point\n");
continue;
}
img.copyTo( imgDst );
#if _NBC_
find_decision_boundary_NBC();
imshow( "NormalBayesClassifier", imgDst );
#endif
#if _KNN_
find_decision_boundary_KNN( 3 );
imshow( "kNN", imgDst );
find_decision_boundary_KNN( 15 );
imshow( "kNN2", imgDst );
#endif
#if _SVM_
//(1)-(2)separable and not sets
find_decision_boundary_SVM( 1 );
imshow( "classificationSVM1", imgDst );
find_decision_boundary_SVM( 10 );
imshow( "classificationSVM2", imgDst );
#endif
#if _DT_
find_decision_boundary_DT();
imshow( "DT", imgDst );
#endif
#if _BT_
find_decision_boundary_BT();
imshow( "BT", imgDst);
#endif
#if _GBT_
find_decision_boundary_GBT();
imshow( "GBT", imgDst);
#endif
#if _RF_
find_decision_boundary_RF();
imshow( "RF", imgDst);
#endif
#if _ANN_
Mat layer_sizes1( 1, 3, CV_32SC1 );
layer_sizes1.at<int>(0) = 2;
layer_sizes1.at<int>(1) = 5;
layer_sizes1.at<int>(2) = (int)classColors.size();
find_decision_boundary_ANN( layer_sizes1 );
imshow( "ANN", imgDst );
#endif
#if _EM_
find_decision_boundary_EM();
imshow( "EM", imgDst );
#endif
}
}
return 0;
}
+224
View File
@@ -0,0 +1,224 @@
#!/usr/bin/env python
'''
This module contains some common routines used by other samples.
'''
from functools import reduce
import numpy as np
import cv2 as cv
# built-in modules
import os
import itertools as it
from contextlib import contextmanager
image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tif', '.tiff', '.pbm', '.pgm', '.ppm']
class Bunch(object):
def __init__(self, **kw):
self.__dict__.update(kw)
def __str__(self):
return str(self.__dict__)
def splitfn(fn):
path, fn = os.path.split(fn)
name, ext = os.path.splitext(fn)
return path, name, ext
def anorm2(a):
return (a*a).sum(-1)
def anorm(a):
return np.sqrt( anorm2(a) )
def homotrans(H, x, y):
xs = H[0, 0]*x + H[0, 1]*y + H[0, 2]
ys = H[1, 0]*x + H[1, 1]*y + H[1, 2]
s = H[2, 0]*x + H[2, 1]*y + H[2, 2]
return xs/s, ys/s
def to_rect(a):
a = np.ravel(a)
if len(a) == 2:
a = (0, 0, a[0], a[1])
return np.array(a, np.float64).reshape(2, 2)
def rect2rect_mtx(src, dst):
src, dst = to_rect(src), to_rect(dst)
cx, cy = (dst[1] - dst[0]) / (src[1] - src[0])
tx, ty = dst[0] - src[0] * (cx, cy)
M = np.float64([[ cx, 0, tx],
[ 0, cy, ty],
[ 0, 0, 1]])
return M
def lookat(eye, target, up = (0, 0, 1)):
fwd = np.asarray(target, np.float64) - eye
fwd /= anorm(fwd)
right = np.cross(fwd, up)
right /= anorm(right)
down = np.cross(fwd, right)
R = np.float64([right, down, fwd])
tvec = -np.dot(R, eye)
return R, tvec
def mtx2rvec(R):
w, u, vt = cv.SVDecomp(R - np.eye(3))
p = vt[0] + u[:,0]*w[0] # same as np.dot(R, vt[0])
c = np.dot(vt[0], p)
s = np.dot(vt[1], p)
axis = np.cross(vt[0], vt[1])
return axis * np.arctan2(s, c)
def draw_str(dst, target, s):
x, y = target
cv.putText(dst, s, (x+1, y+1), cv.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv.LINE_AA)
cv.putText(dst, s, (x, y), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv.LINE_AA)
class Sketcher:
def __init__(self, windowname, dests, colors_func):
self.prev_pt = None
self.windowname = windowname
self.dests = dests
self.colors_func = colors_func
self.dirty = False
self.show()
cv.setMouseCallback(self.windowname, self.on_mouse)
def show(self):
cv.imshow(self.windowname, self.dests[0])
def on_mouse(self, event, x, y, flags, param):
pt = (x, y)
if event == cv.EVENT_LBUTTONDOWN:
self.prev_pt = pt
elif event == cv.EVENT_LBUTTONUP:
self.prev_pt = None
if self.prev_pt and flags & cv.EVENT_FLAG_LBUTTON:
for dst, color in zip(self.dests, self.colors_func()):
cv.line(dst, self.prev_pt, pt, color, 5)
self.dirty = True
self.prev_pt = pt
self.show()
# palette data from matplotlib/_cm.py
_jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89,1, 1),
(1, 0.5, 0.5)),
'green': ((0., 0, 0), (0.125,0, 0), (0.375,1, 1), (0.64,1, 1),
(0.91,0,0), (1, 0, 0)),
'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65,0, 0),
(1, 0, 0))}
cmap_data = { 'jet' : _jet_data }
def make_cmap(name, n=256):
data = cmap_data[name]
xs = np.linspace(0.0, 1.0, n)
channels = []
eps = 1e-6
for ch_name in ['blue', 'green', 'red']:
ch_data = data[ch_name]
xp, yp = [], []
for x, y1, y2 in ch_data:
xp += [x, x+eps]
yp += [y1, y2]
ch = np.interp(xs, xp, yp)
channels.append(ch)
return np.uint8(np.array(channels).T*255)
def nothing(*arg, **kw):
pass
def clock():
return cv.getTickCount() / cv.getTickFrequency()
@contextmanager
def Timer(msg):
print(msg, '...',)
start = clock()
try:
yield
finally:
print("%.2f ms" % ((clock()-start)*1000))
class StatValue:
def __init__(self, smooth_coef = 0.5):
self.value = None
self.smooth_coef = smooth_coef
def update(self, v):
if self.value is None:
self.value = v
else:
c = self.smooth_coef
self.value = c * self.value + (1.0-c) * v
class RectSelector:
def __init__(self, win, callback):
self.win = win
self.callback = callback
cv.setMouseCallback(win, self.onmouse)
self.drag_start = None
self.drag_rect = None
def onmouse(self, event, x, y, flags, param):
x, y = np.int16([x, y]) # BUG
if event == cv.EVENT_LBUTTONDOWN:
self.drag_start = (x, y)
return
if self.drag_start:
if flags & cv.EVENT_FLAG_LBUTTON:
xo, yo = self.drag_start
x0, y0 = np.minimum([xo, yo], [x, y])
x1, y1 = np.maximum([xo, yo], [x, y])
self.drag_rect = None
if x1-x0 > 0 and y1-y0 > 0:
self.drag_rect = (x0, y0, x1, y1)
else:
rect = self.drag_rect
self.drag_start = None
self.drag_rect = None
if rect:
self.callback(rect)
def draw(self, vis):
if not self.drag_rect:
return False
x0, y0, x1, y1 = self.drag_rect
cv.rectangle(vis, (x0, y0), (x1, y1), (0, 255, 0), 2)
return True
@property
def dragging(self):
return self.drag_rect is not None
def grouper(n, iterable, fillvalue=None):
'''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx'''
args = [iter(iterable)] * n
output = it.zip_longest(fillvalue=fillvalue, *args)
return output
def mosaic(w, imgs):
'''Make a grid from images.
w -- number of grid columns
imgs -- images (must have same size and format)
'''
imgs = iter(imgs)
img0 = next(imgs)
pad = np.zeros_like(img0)
imgs = it.chain([img0], imgs)
rows = grouper(w, imgs, pad)
return np.vstack(list(map(np.hstack, rows)))
def getsize(img):
h, w = img.shape[:2]
return w, h
def mdot(*args):
return reduce(np.dot, args)
def draw_keypoints(vis, keypoints, color = (0, 255, 255)):
for kp in keypoints:
x, y = kp.pt
cv.circle(vis, (int(x), int(y)), 2, color)
+194
View File
@@ -0,0 +1,194 @@
#!/usr/bin/env python
'''
SVM and KNearest digit recognition.
Sample loads a dataset of handwritten digits from 'digits.png'.
Then it trains a SVM and KNearest classifiers on it and evaluates
their accuracy.
Following preprocessing is applied to the dataset:
- Moment-based image deskew (see deskew())
- Digit images are split into 4 10x10 cells and 16-bin
histogram of oriented gradients is computed for each
cell
- Transform histograms to space with Hellinger metric (see [1] (RootSIFT))
[1] R. Arandjelovic, A. Zisserman
"Three things everyone should know to improve object retrieval"
http://www.robots.ox.ac.uk/~vgg/publications/2012/Arandjelovic12/arandjelovic12.pdf
Usage:
digits.py
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# built-in modules
from multiprocessing.pool import ThreadPool
from numpy.linalg import norm
# local modules
from common import clock, mosaic
SZ = 20 # size of each digit is SZ x SZ
CLASS_N = 10
DIGITS_FN = 'digits.png'
def split2d(img, cell_size, flatten=True):
h, w = img.shape[:2]
sx, sy = cell_size
cells = [np.hsplit(row, w//sx) for row in np.vsplit(img, h//sy)]
cells = np.array(cells)
if flatten:
cells = cells.reshape(-1, sy, sx)
return cells
def load_digits(fn):
fn = cv.samples.findFile(fn)
print('loading "%s" ...' % fn)
digits_img = cv.imread(fn, cv.IMREAD_GRAYSCALE)
digits = split2d(digits_img, (SZ, SZ))
labels = np.repeat(np.arange(CLASS_N), len(digits)/CLASS_N)
return digits, labels
def deskew(img):
m = cv.moments(img)
if abs(m['mu02']) < 1e-2:
return img.copy()
skew = m['mu11']/m['mu02']
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
img = cv.warpAffine(img, M, (SZ, SZ), flags=cv.WARP_INVERSE_MAP | cv.INTER_LINEAR)
return img
class KNearest(object):
def __init__(self, k = 3):
self.k = k
self.model = cv.ml.KNearest_create()
def train(self, samples, responses):
self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
def predict(self, samples):
_retval, results, _neigh_resp, _dists = self.model.findNearest(samples, self.k)
return results.ravel()
def load(self, fn):
self.model = cv.ml.KNearest_load(fn)
def save(self, fn):
self.model.save(fn)
class SVM(object):
def __init__(self, C = 1, gamma = 0.5):
self.model = cv.ml.SVM_create()
self.model.setGamma(gamma)
self.model.setC(C)
self.model.setKernel(cv.ml.SVM_RBF)
self.model.setType(cv.ml.SVM_C_SVC)
def train(self, samples, responses):
self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
def predict(self, samples):
return self.model.predict(samples)[1].ravel()
def load(self, fn):
self.model = cv.ml.SVM_load(fn)
def save(self, fn):
self.model.save(fn)
def evaluate_model(model, digits, samples, labels):
resp = model.predict(samples)
err = (labels != resp).mean()
print('error: %.2f %%' % (err*100))
confusion = np.zeros((10, 10), np.int32)
for i, j in zip(labels, resp):
confusion[i, int(j)] += 1
print('confusion matrix:')
print(confusion)
print()
vis = []
for img, flag in zip(digits, resp == labels):
img = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
if not flag:
img[...,:2] = 0
vis.append(img)
return mosaic(25, vis)
def preprocess_simple(digits):
return np.float32(digits).reshape(-1, SZ*SZ) / 255.0
def preprocess_hog(digits):
samples = []
for img in digits:
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.cartToPolar(gx, gy)
bin_n = 16
bin = np.int32(bin_n*ang/(2*np.pi))
bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists)
# transform to Hellinger kernel
eps = 1e-7
hist /= hist.sum() + eps
hist = np.sqrt(hist)
hist /= norm(hist) + eps
samples.append(hist)
return np.float32(samples)
if __name__ == '__main__':
print(__doc__)
digits, labels = load_digits(DIGITS_FN)
print('preprocessing...')
# shuffle digits
rand = np.random.RandomState(321)
shuffle = rand.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]
digits2 = list(map(deskew, digits))
samples = preprocess_hog(digits2)
train_n = int(0.9*len(samples))
cv.imshow('test set', mosaic(25, digits[train_n:]))
digits_train, digits_test = np.split(digits2, [train_n])
samples_train, samples_test = np.split(samples, [train_n])
labels_train, labels_test = np.split(labels, [train_n])
print('training KNearest...')
model = KNearest(k=4)
model.train(samples_train, labels_train)
vis = evaluate_model(model, digits_test, samples_test, labels_test)
cv.imshow('KNearest test', vis)
print('training SVM...')
model = SVM(C=2.67, gamma=5.383)
model.train(samples_train, labels_train)
vis = evaluate_model(model, digits_test, samples_test, labels_test)
cv.imshow('SVM test', vis)
print('saving SVM as "digits_svm.dat"...')
model.save('digits_svm.dat')
cv.waitKey(0)
cv.destroyAllWindows()
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env python
'''
Digit recognition adjustment.
Grid search is used to find the best parameters for SVM and KNearest classifiers.
SVM adjustment follows the guidelines given in
http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf
Usage:
digits_adjust.py [--model {svm|knearest}]
--model {svm|knearest} - select the classifier (SVM is the default)
'''
import numpy as np
import cv2 as cv
from multiprocessing.pool import ThreadPool
from digits import *
def cross_validate(model_class, params, samples, labels, kfold = 3, pool = None):
n = len(samples)
folds = np.array_split(np.arange(n), kfold)
def f(i):
model = model_class(**params)
test_idx = folds[i]
train_idx = list(folds)
train_idx.pop(i)
train_idx = np.hstack(train_idx)
train_samples, train_labels = samples[train_idx], labels[train_idx]
test_samples, test_labels = samples[test_idx], labels[test_idx]
model.train(train_samples, train_labels)
resp = model.predict(test_samples)
score = (resp != test_labels).mean()
print(".", end='')
return score
if pool is None:
scores = list(map(f, range(kfold)))
else:
scores = pool.map(f, range(kfold))
return np.mean(scores)
class App(object):
def __init__(self):
self._samples, self._labels = self.preprocess()
def preprocess(self):
digits, labels = load_digits(DIGITS_FN)
shuffle = np.random.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]
digits2 = list(map(deskew, digits))
samples = preprocess_hog(digits2)
return samples, labels
def get_dataset(self):
return self._samples, self._labels
def run_jobs(self, f, jobs):
pool = ThreadPool(processes=cv.getNumberOfCPUs())
ires = pool.imap_unordered(f, jobs)
return ires
def adjust_SVM(self):
Cs = np.logspace(0, 10, 15, base=2)
gammas = np.logspace(-7, 4, 15, base=2)
scores = np.zeros((len(Cs), len(gammas)))
scores[:] = np.nan
print('adjusting SVM (may take a long time) ...')
def f(job):
i, j = job
samples, labels = self.get_dataset()
params = dict(C = Cs[i], gamma=gammas[j])
score = cross_validate(SVM, params, samples, labels)
return i, j, score
ires = self.run_jobs(f, np.ndindex(*scores.shape))
for count, (i, j, score) in enumerate(ires):
scores[i, j] = score
print('%d / %d (best error: %.2f %%, last: %.2f %%)' %
(count+1, scores.size, np.nanmin(scores)*100, score*100))
print(scores)
print('writing score table to "svm_scores.npz"')
np.savez('svm_scores.npz', scores=scores, Cs=Cs, gammas=gammas)
i, j = np.unravel_index(scores.argmin(), scores.shape)
best_params = dict(C = Cs[i], gamma=gammas[j])
print('best params:', best_params)
print('best error: %.2f %%' % (scores.min()*100))
return best_params
def adjust_KNearest(self):
print('adjusting KNearest ...')
def f(k):
samples, labels = self.get_dataset()
err = cross_validate(KNearest, dict(k=k), samples, labels)
return k, err
best_err, best_k = np.inf, -1
for k, err in self.run_jobs(f, range(1, 9)):
if err < best_err:
best_err, best_k = err, k
print('k = %d, error: %.2f %%' % (k, err*100))
best_params = dict(k=best_k)
print('best params:', best_params, 'err: %.2f' % (best_err*100))
return best_params
if __name__ == '__main__':
import getopt
import sys
print(__doc__)
args, _ = getopt.getopt(sys.argv[1:], '', ['model='])
args = dict(args)
args.setdefault('--model', 'svm')
args.setdefault('--env', '')
if args['--model'] not in ['svm', 'knearest']:
print('unknown model "%s"' % args['--model'])
sys.exit(1)
t = clock()
app = App()
if args['--model'] == 'knearest':
app.adjust_KNearest()
else:
app.adjust_SVM()
print('work time: %f s' % (clock() - t))
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env python
'''
Digit recognition from video.
Run digits.py before, to train and save the SVM.
Usage:
digits_video.py [{camera_id|video_file}]
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
# built-in modules
import os
import sys
# local modules
import video
from common import mosaic
from digits import *
def main():
try:
src = sys.argv[1]
except:
src = 0
cap = video.create_capture(src, fallback='synth:bg={}:noise=0.05'.format(cv.samples.findFile('sudoku.png')))
classifier_fn = 'digits_svm.dat'
if not os.path.exists(classifier_fn):
print('"%s" not found, run digits.py first' % classifier_fn)
return
model = cv.ml.SVM_load(classifier_fn)
while True:
_ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
bin = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 31, 10)
bin = cv.medianBlur(bin, 3)
contours, heirs = cv.findContours( bin.copy(), cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
try:
heirs = heirs[0]
except:
heirs = []
for cnt, heir in zip(contours, heirs):
_, _, _, outer_i = heir
if outer_i >= 0:
continue
x, y, w, h = cv.boundingRect(cnt)
if not (16 <= h <= 64 and w <= 1.2*h):
continue
pad = max(h-w, 0)
x, w = x - (pad // 2), w + pad
cv.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0))
bin_roi = bin[y:,x:][:h,:w]
m = bin_roi != 0
if not 0.1 < m.mean() < 0.4:
continue
'''
gray_roi = gray[y:,x:][:h,:w]
v_in, v_out = gray_roi[m], gray_roi[~m]
if v_out.std() > 10.0:
continue
s = "%f, %f" % (abs(v_in.mean() - v_out.mean()), v_out.std())
cv.putText(frame, s, (x, y), cv.FONT_HERSHEY_PLAIN, 1.0, (200, 0, 0), thickness = 1)
'''
s = 1.5*float(h)/SZ
m = cv.moments(bin_roi)
c1 = np.float32([m['m10'], m['m01']]) / m['m00']
c0 = np.float32([SZ/2, SZ/2])
t = c1 - s*c0
A = np.zeros((2, 3), np.float32)
A[:,:2] = np.eye(2)*s
A[:,2] = t
bin_norm = cv.warpAffine(bin_roi, A, (SZ, SZ), flags=cv.WARP_INVERSE_MAP | cv.INTER_LINEAR)
bin_norm = deskew(bin_norm)
if x+w+SZ < frame.shape[1] and y+SZ < frame.shape[0]:
frame[y:,x+w:][:SZ, :SZ] = bin_norm[...,np.newaxis]
sample = preprocess_hog([bin_norm])
digit = model.predict(sample)[1].ravel()
cv.putText(frame, '%d'%digit, (x, y), cv.FONT_HERSHEY_PLAIN, 1.0, (200, 0, 0), thickness = 1)
cv.imshow('frame', frame)
cv.imshow('bin', bin)
ch = cv.waitKey(1)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python
import numpy as np
import cv2 as cv
from numpy import random
def make_gaussians(cluster_n, img_size):
points = []
ref_distrs = []
for _i in range(cluster_n):
mean = (0.1 + 0.8*random.rand(2)) * img_size
a = (random.rand(2, 2)-0.5)*img_size*0.1
cov = np.dot(a.T, a) + img_size*0.05*np.eye(2)
n = 100 + random.randint(900)
pts = random.multivariate_normal(mean, cov, n)
points.append( pts )
ref_distrs.append( (mean, cov) )
points = np.float32( np.vstack(points) )
return points, ref_distrs
def draw_gaussain(img, mean, cov, color):
x, y = mean
w, u, _vt = cv.SVDecomp(cov)
ang = np.arctan2(u[1, 0], u[0, 0])*(180/np.pi)
s1, s2 = np.sqrt(w)*3.0
cv.ellipse(img, (int(x), int(y)), (int(s1), int(s2)), ang, 0, 360, color, 1, cv.LINE_AA)
def main():
cluster_n = 5
img_size = 512
print('press any key to update distributions, ESC - exit\n')
while True:
print('sampling distributions...')
points, ref_distrs = make_gaussians(cluster_n, img_size)
print('EM (opencv) ...')
em = cv.ml.EM_create()
em.setClustersNumber(cluster_n)
em.setCovarianceMatrixType(cv.ml.EM_COV_MAT_GENERIC)
em.trainEM(points)
means = em.getMeans()
covs = em.getCovs() # Known bug: https://github.com/opencv/opencv/pull/4232
found_distrs = zip(means, covs)
print('ready!\n')
img = np.zeros((img_size, img_size, 3), np.uint8)
for x, y in np.int32(points):
cv.circle(img, (x, y), 1, (255, 255, 255), -1)
for m, cov in ref_distrs:
draw_gaussain(img, m, cov, (0, 255, 0))
for m, cov in found_distrs:
draw_gaussain(img, m, cov, (0, 0, 255))
cv.imshow('gaussian mixture', img)
ch = cv.waitKey(0)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
+194
View File
@@ -0,0 +1,194 @@
#!/usr/bin/env python
'''
The sample demonstrates how to train Random Trees classifier
(or Boosting classifier, or MLP, or Knearest, or Support Vector Machines) using the provided dataset.
We use the sample database letter-recognition.data
from UCI Repository, here is the link:
Newman, D.J. & Hettich, S. & Blake, C.L. & Merz, C.J. (1998).
UCI Repository of machine learning databases
[http://www.ics.uci.edu/~mlearn/MLRepository.html].
Irvine, CA: University of California, Department of Information and Computer Science.
The dataset consists of 20000 feature vectors along with the
responses - capital latin letters A..Z.
The first 10000 samples are used for training
and the remaining 10000 - to test the classifier.
======================================================
USAGE:
letter_recog.py [--model <model>]
[--data <data fn>]
[--load <model fn>] [--save <model fn>]
Models: RTrees, KNearest, Boost, SVM, MLP
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
def load_base(fn):
a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') })
samples, responses = a[:,1:], a[:,0]
return samples, responses
class LetterStatModel(object):
class_n = 26
train_ratio = 0.5
def load(self, fn):
self.model = self.model.load(fn)
def save(self, fn):
self.model.save(fn)
def unroll_samples(self, samples):
sample_n, var_n = samples.shape
new_samples = np.zeros((sample_n * self.class_n, var_n+1), np.float32)
new_samples[:,:-1] = np.repeat(samples, self.class_n, axis=0)
new_samples[:,-1] = np.tile(np.arange(self.class_n), sample_n)
return new_samples
def unroll_responses(self, responses):
sample_n = len(responses)
new_responses = np.zeros(sample_n*self.class_n, np.int32)
resp_idx = np.int32( responses + np.arange(sample_n)*self.class_n )
new_responses[resp_idx] = 1
return new_responses
class RTrees(LetterStatModel):
def __init__(self):
self.model = cv.ml.RTrees_create()
def train(self, samples, responses):
self.model.setMaxDepth(20)
self.model.train(samples, cv.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
_ret, resp = self.model.predict(samples)
return resp.ravel()
class KNearest(LetterStatModel):
def __init__(self):
self.model = cv.ml.KNearest_create()
def train(self, samples, responses):
self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
def predict(self, samples):
_retval, results, _neigh_resp, _dists = self.model.findNearest(samples, k = 10)
return results.ravel()
class Boost(LetterStatModel):
def __init__(self):
self.model = cv.ml.Boost_create()
def train(self, samples, responses):
_sample_n, var_n = samples.shape
new_samples = self.unroll_samples(samples)
new_responses = self.unroll_responses(responses)
var_types = np.array([cv.ml.VAR_NUMERICAL] * var_n + [cv.ml.VAR_CATEGORICAL, cv.ml.VAR_CATEGORICAL], np.uint8)
self.model.setWeakCount(15)
self.model.setMaxDepth(10)
self.model.train(cv.ml.TrainData_create(new_samples, cv.ml.ROW_SAMPLE, new_responses.astype(int), varType = var_types))
def predict(self, samples):
new_samples = self.unroll_samples(samples)
_ret, resp = self.model.predict(new_samples)
return resp.ravel().reshape(-1, self.class_n).argmax(1)
class SVM(LetterStatModel):
def __init__(self):
self.model = cv.ml.SVM_create()
def train(self, samples, responses):
self.model.setType(cv.ml.SVM_C_SVC)
self.model.setC(1)
self.model.setKernel(cv.ml.SVM_RBF)
self.model.setGamma(.1)
self.model.train(samples, cv.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
_ret, resp = self.model.predict(samples)
return resp.ravel()
class MLP(LetterStatModel):
def __init__(self):
self.model = cv.ml.ANN_MLP_create()
def train(self, samples, responses):
_sample_n, var_n = samples.shape
new_responses = self.unroll_responses(responses).reshape(-1, self.class_n)
layer_sizes = np.int32([var_n, 100, 100, self.class_n])
self.model.setLayerSizes(layer_sizes)
self.model.setTrainMethod(cv.ml.ANN_MLP_BACKPROP)
self.model.setBackpropMomentumScale(0.0)
self.model.setBackpropWeightScale(0.001)
self.model.setTermCriteria((cv.TERM_CRITERIA_COUNT, 20, 0.01))
self.model.setActivationFunction(cv.ml.ANN_MLP_SIGMOID_SYM, 2, 1)
self.model.train(samples, cv.ml.ROW_SAMPLE, np.float32(new_responses))
def predict(self, samples):
_ret, resp = self.model.predict(samples)
return resp.argmax(-1)
def main():
import getopt
import sys
models = [RTrees, KNearest, Boost, SVM, MLP] # NBayes
models = dict( [(cls.__name__.lower(), cls) for cls in models] )
args, dummy = getopt.getopt(sys.argv[1:], '', ['model=', 'data=', 'load=', 'save='])
args = dict(args)
args.setdefault('--model', 'svm')
args.setdefault('--data', 'letter-recognition.data')
datafile = cv.samples.findFile(args['--data'])
print('loading data %s ...' % datafile)
samples, responses = load_base(datafile)
Model = models[args['--model']]
model = Model()
train_n = int(len(samples)*model.train_ratio)
if '--load' in args:
fn = args['--load']
print('loading model from %s ...' % fn)
model.load(fn)
else:
print('training %s ...' % Model.__name__)
model.train(samples[:train_n], responses[:train_n])
print('testing...')
train_rate = np.mean(model.predict(samples[:train_n]) == responses[:train_n].astype(int))
test_rate = np.mean(model.predict(samples[train_n:]) == responses[train_n:].astype(int))
print('train rate: %f test rate: %f' % (train_rate*100, test_rate*100))
if '--save' in args:
fn = args['--save']
print('saving model to %s ...' % fn)
model.save(fn)
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
@@ -0,0 +1,121 @@
#!/usr/bin/env python
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
from numpy import pi, sin, cos
defaultSize = 512
class TestSceneRender():
def __init__(self, bgImg = None, fgImg = None,
deformation = False, speed = 0.25, **params):
self.time = 0.0
self.timeStep = 1.0 / 30.0
self.foreground = fgImg
self.deformation = deformation
self.speed = speed
if bgImg is not None:
self.sceneBg = bgImg.copy()
else:
self.sceneBg = np.zeros((defaultSize, defaultSize,3), np.uint8)
self.w = self.sceneBg.shape[0]
self.h = self.sceneBg.shape[1]
if fgImg is not None:
self.foreground = fgImg.copy()
self.center = self.currentCenter = (int(self.w/2 - fgImg.shape[0]/2), int(self.h/2 - fgImg.shape[1]/2))
self.xAmpl = self.sceneBg.shape[0] - (self.center[0] + fgImg.shape[0])
self.yAmpl = self.sceneBg.shape[1] - (self.center[1] + fgImg.shape[1])
self.initialRect = np.array([ (self.h/2, self.w/2), (self.h/2, self.w/2 + self.w/10),
(self.h/2 + self.h/10, self.w/2 + self.w/10), (self.h/2 + self.h/10, self.w/2)]).astype(int)
self.currentRect = self.initialRect
def getXOffset(self, time):
return int( self.xAmpl*cos(time*self.speed))
def getYOffset(self, time):
return int(self.yAmpl*sin(time*self.speed))
def setInitialRect(self, rect):
self.initialRect = rect
def getRectInTime(self, time):
if self.foreground is not None:
tmp = np.array(self.center) + np.array((self.getXOffset(time), self.getYOffset(time)))
x0, y0 = tmp
x1, y1 = tmp + self.foreground.shape[0:2]
return np.array([y0, x0, y1, x1])
else:
x0, y0 = self.initialRect[0] + np.array((self.getXOffset(time), self.getYOffset(time)))
x1, y1 = self.initialRect[2] + np.array((self.getXOffset(time), self.getYOffset(time)))
return np.array([y0, x0, y1, x1])
def getCurrentRect(self):
if self.foreground is not None:
x0 = self.currentCenter[0]
y0 = self.currentCenter[1]
x1 = self.currentCenter[0] + self.foreground.shape[0]
y1 = self.currentCenter[1] + self.foreground.shape[1]
return np.array([y0, x0, y1, x1])
else:
x0, y0 = self.currentRect[0]
x1, y1 = self.currentRect[2]
return np.array([x0, y0, x1, y1])
def getNextFrame(self):
img = self.sceneBg.copy()
if self.foreground is not None:
self.currentCenter = (self.center[0] + self.getXOffset(self.time), self.center[1] + self.getYOffset(self.time))
img[self.currentCenter[0]:self.currentCenter[0]+self.foreground.shape[0],
self.currentCenter[1]:self.currentCenter[1]+self.foreground.shape[1]] = self.foreground
else:
self.currentRect = self.initialRect + int( 30*cos(self.time*self.speed) + 50*sin(self.time*self.speed))
if self.deformation:
self.currentRect[1:3] += int(self.h/20*cos(self.time))
cv.fillConvexPoly(img, self.currentRect, (0, 0, 255))
self.time += self.timeStep
return img
def resetTime(self):
self.time = 0.0
def main():
backGr = cv.imread(cv.samples.findFile('graf1.png'))
fgr = cv.imread(cv.samples.findFile('box.png'))
render = TestSceneRender(backGr, fgr)
while True:
img = render.getNextFrame()
cv.imshow('img', img)
ch = cv.waitKey(3)
if ch == 27:
break
print('Done')
if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
@@ -0,0 +1,62 @@
import cv2 as cv
import numpy as np
# Set up training data
## [setup1]
labels = np.array([1, -1, -1, -1])
trainingData = np.matrix([[501, 10], [255, 10], [501, 255], [10, 501]], dtype=np.float32)
## [setup1]
# Train the SVM
## [init]
svm = cv.ml.SVM_create()
svm.setType(cv.ml.SVM_C_SVC)
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setTermCriteria((cv.TERM_CRITERIA_MAX_ITER, 100, 1e-6))
## [init]
## [train]
svm.train(trainingData, cv.ml.ROW_SAMPLE, labels)
## [train]
# Data for visual representation
width = 512
height = 512
image = np.zeros((height, width, 3), dtype=np.uint8)
# Show the decision regions given by the SVM
## [show]
green = (0,255,0)
blue = (255,0,0)
for i in range(image.shape[0]):
for j in range(image.shape[1]):
sampleMat = np.matrix([[j,i]], dtype=np.float32)
response = svm.predict(sampleMat)[1]
if response == 1:
image[i,j] = green
elif response == -1:
image[i,j] = blue
## [show]
# Show the training data
## [show_data]
thickness = -1
cv.circle(image, (501, 10), 5, ( 0, 0, 0), thickness)
cv.circle(image, (255, 10), 5, (255, 255, 255), thickness)
cv.circle(image, (501, 255), 5, (255, 255, 255), thickness)
cv.circle(image, ( 10, 501), 5, (255, 255, 255), thickness)
## [show_data]
# Show support vectors
## [show_vectors]
thickness = 2
sv = svm.getUncompressedSupportVectors()
for i in range(sv.shape[0]):
cv.circle(image, (int(sv[i,0]), int(sv[i,1])), 6, (128, 128, 128), thickness)
## [show_vectors]
cv.imwrite('result.png', image) # save the image
cv.imshow('SVM Simple Example', image) # show it to the user
cv.waitKey()
@@ -0,0 +1,117 @@
from __future__ import print_function
import cv2 as cv
import numpy as np
import random as rng
NTRAINING_SAMPLES = 100 # Number of training samples per class
FRAC_LINEAR_SEP = 0.9 # Fraction of samples which compose the linear separable part
# Data for visual representation
WIDTH = 512
HEIGHT = 512
I = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)
# --------------------- 1. Set up training data randomly ---------------------------------------
trainData = np.empty((2*NTRAINING_SAMPLES, 2), dtype=np.float32)
labels = np.empty((2*NTRAINING_SAMPLES, 1), dtype=np.int32)
rng.seed(100) # Random value generation class
# Set up the linearly separable part of the training data
nLinearSamples = int(FRAC_LINEAR_SEP * NTRAINING_SAMPLES)
## [setup1]
# Generate random points for the class 1
trainClass = trainData[0:nLinearSamples,:]
# The x coordinate of the points is in [0, 0.4)
c = trainClass[:,0:1]
c[:] = np.random.uniform(0.0, 0.4 * WIDTH, c.shape)
# The y coordinate of the points is in [0, 1)
c = trainClass[:,1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)
# Generate random points for the class 2
trainClass = trainData[2*NTRAINING_SAMPLES-nLinearSamples:2*NTRAINING_SAMPLES,:]
# The x coordinate of the points is in [0.6, 1]
c = trainClass[:,0:1]
c[:] = np.random.uniform(0.6*WIDTH, WIDTH, c.shape)
# The y coordinate of the points is in [0, 1)
c = trainClass[:,1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)
## [setup1]
#------------------ Set up the non-linearly separable part of the training data ---------------
## [setup2]
# Generate random points for the classes 1 and 2
trainClass = trainData[nLinearSamples:2*NTRAINING_SAMPLES-nLinearSamples,:]
# The x coordinate of the points is in [0.4, 0.6)
c = trainClass[:,0:1]
c[:] = np.random.uniform(0.4*WIDTH, 0.6*WIDTH, c.shape)
# The y coordinate of the points is in [0, 1)
c = trainClass[:,1:2]
c[:] = np.random.uniform(0.0, HEIGHT, c.shape)
## [setup2]
#------------------------- Set up the labels for the classes ---------------------------------
labels[0:NTRAINING_SAMPLES,:] = 1 # Class 1
labels[NTRAINING_SAMPLES:2*NTRAINING_SAMPLES,:] = 2 # Class 2
#------------------------ 2. Set up the support vector machines parameters --------------------
print('Starting training process')
## [init]
svm = cv.ml.SVM_create()
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(0.1)
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setTermCriteria((cv.TERM_CRITERIA_MAX_ITER, int(1e7), 1e-6))
## [init]
#------------------------ 3. Train the svm ----------------------------------------------------
## [train]
svm.train(trainData, cv.ml.ROW_SAMPLE, labels)
## [train]
print('Finished training process')
#------------------------ 4. Show the decision regions ----------------------------------------
## [show]
green = (0,100,0)
blue = (100,0,0)
for i in range(I.shape[0]):
for j in range(I.shape[1]):
sampleMat = np.matrix([[j,i]], dtype=np.float32)
response = svm.predict(sampleMat)[1]
if response == 1:
I[i,j] = green
elif response == 2:
I[i,j] = blue
## [show]
#----------------------- 5. Show the training data --------------------------------------------
## [show_data]
thick = -1
# Class 1
for i in range(NTRAINING_SAMPLES):
px = trainData[i,0]
py = trainData[i,1]
cv.circle(I, (int(px), int(py)), 3, (0, 255, 0), thick)
# Class 2
for i in range(NTRAINING_SAMPLES, 2*NTRAINING_SAMPLES):
px = trainData[i,0]
py = trainData[i,1]
cv.circle(I, (int(px), int(py)), 3, (255, 0, 0), thick)
## [show_data]
#------------------------- 6. Show support vectors --------------------------------------------
## [show_vectors]
thick = 2
sv = svm.getUncompressedSupportVectors()
for i in range(sv.shape[0]):
cv.circle(I, (int(sv[i,0]), int(sv[i,1])), 6, (128, 128, 128), thick)
## [show_vectors]
cv.imwrite('result.png', I) # save the Image
cv.imshow('SVM for Non-Linear Training Data', I) # show it to the user
cv.waitKey()
@@ -0,0 +1,73 @@
#!/usr/bin/env python
import cv2 as cv
import numpy as np
SZ=20
bin_n = 16 # Number of bins
affine_flags = cv.WARP_INVERSE_MAP|cv.INTER_LINEAR
## [deskew]
def deskew(img):
m = cv.moments(img)
if abs(m['mu02']) < 1e-2:
return img.copy()
skew = m['mu11']/m['mu02']
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
img = cv.warpAffine(img,M,(SZ, SZ),flags=affine_flags)
return img
## [deskew]
## [hog]
def hog(img):
gx = cv.Sobel(img, cv.CV_32F, 1, 0)
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
mag, ang = cv.cartToPolar(gx, gy)
bins = np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)
bin_cells = bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists) # hist is a 64 bit vector
return hist
## [hog]
img = cv.imread(cv.samples.findFile('digits.png'),0)
if img is None:
raise Exception("we need the digits.png image from samples/data here !")
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# First half is trainData, remaining is testData
train_cells = [ i[:50] for i in cells ]
test_cells = [ i[50:] for i in cells]
###### Now training ########################
deskewed = [list(map(deskew,row)) for row in train_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
trainData = np.float32(hogdata).reshape(-1,64)
responses = np.repeat(np.arange(10),250)[:,np.newaxis]
svm = cv.ml.SVM_create()
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
###### Now testing ########################
deskewed = [list(map(deskew,row)) for row in test_cells]
hogdata = [list(map(hog,row)) for row in deskewed]
testData = np.float32(hogdata).reshape(-1,bin_n*4)
result = svm.predict(testData)[1]
####### Check Accuracy ########################
mask = result==responses
correct = np.count_nonzero(mask)
print(correct*100.0/result.size)
+228
View File
@@ -0,0 +1,228 @@
#!/usr/bin/env python
'''
Video capture sample.
Sample shows how VideoCapture class can be used to acquire video
frames from a camera of a movie file. Also the sample provides
an example of procedural video generation by an object, mimicking
the VideoCapture interface (see Chess class).
'create_capture' is a convenience function for capture creation,
falling back to procedural video in case of error.
Usage:
video.py [--shotdir <shot path>] [source0] [source1] ...'
sourceN is an
- integer number for camera capture
- name of video file
- synth:<params> for procedural video
Synth examples:
synth:bg=lena.jpg:noise=0.1
synth:class=chess:bg=lena.jpg:noise=0.1:size=640x480
Keys:
ESC - exit
SPACE - save current frame to <shot path> directory
'''
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2 as cv
import re
from numpy import pi, sin, cos
# local modules
from tst_scene_render import TestSceneRender
import common
class VideoSynthBase(object):
def __init__(self, size=None, noise=0.0, bg = None, **params):
self.bg = None
self.frame_size = (640, 480)
if bg is not None:
self.bg = cv.imread(cv.samples.findFile(bg))
h, w = self.bg.shape[:2]
self.frame_size = (w, h)
if size is not None:
w, h = map(int, size.split('x'))
self.frame_size = (w, h)
self.bg = cv.resize(self.bg, self.frame_size)
self.noise = float(noise)
def render(self, dst):
pass
def read(self, dst=None):
w, h = self.frame_size
if self.bg is None:
buf = np.zeros((h, w, 3), np.uint8)
else:
buf = self.bg.copy()
self.render(buf)
if self.noise > 0.0:
noise = np.zeros((h, w, 3), np.int8)
cv.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
buf = cv.add(buf, noise, dtype=cv.CV_8UC3)
return True, buf
def isOpened(self):
return True
class Book(VideoSynthBase):
def __init__(self, **kw):
super(Book, self).__init__(**kw)
backGr = cv.imread(cv.samples.findFile('graf1.png'))
fgr = cv.imread(cv.samples.findFile('box.png'))
self.render = TestSceneRender(backGr, fgr, speed = 1)
def read(self, dst=None):
noise = np.zeros(self.render.sceneBg.shape, np.int8)
cv.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
return True, cv.add(self.render.getNextFrame(), noise, dtype=cv.CV_8UC3)
class Cube(VideoSynthBase):
def __init__(self, **kw):
super(Cube, self).__init__(**kw)
self.render = TestSceneRender(cv.imread(cv.samples.findFile('pca_test1.jpg')), deformation = True, speed = 1)
def read(self, dst=None):
noise = np.zeros(self.render.sceneBg.shape, np.int8)
cv.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
return True, cv.add(self.render.getNextFrame(), noise, dtype=cv.CV_8UC3)
class Chess(VideoSynthBase):
def __init__(self, **kw):
super(Chess, self).__init__(**kw)
w, h = self.frame_size
self.grid_size = sx, sy = 10, 7
white_quads = []
black_quads = []
for i, j in np.ndindex(sy, sx):
q = [[j, i, 0], [j+1, i, 0], [j+1, i+1, 0], [j, i+1, 0]]
[white_quads, black_quads][(i + j) % 2].append(q)
self.white_quads = np.float32(white_quads)
self.black_quads = np.float32(black_quads)
fx = 0.9
self.K = np.float64([[fx*w, 0, 0.5*(w-1)],
[0, fx*w, 0.5*(h-1)],
[0.0,0.0, 1.0]])
self.dist_coef = np.float64([-0.2, 0.1, 0, 0])
self.t = 0
def draw_quads(self, img, quads, color = (0, 255, 0)):
img_quads = cv.projectPoints(quads.reshape(-1, 3), self.rvec, self.tvec, self.K, self.dist_coef) [0]
img_quads.shape = quads.shape[:2] + (2,)
for q in img_quads:
cv.fillConvexPoly(img, np.int32(q*4), color, cv.LINE_AA, shift=2)
def render(self, dst):
t = self.t
self.t += 1.0/30.0
sx, sy = self.grid_size
center = np.array([0.5*sx, 0.5*sy, 0.0])
phi = pi/3 + sin(t*3)*pi/8
c, s = cos(phi), sin(phi)
ofs = np.array([sin(1.2*t), cos(1.8*t), 0]) * sx * 0.2
eye_pos = center + np.array([cos(t)*c, sin(t)*c, s]) * 15.0 + ofs
target_pos = center + ofs
R, self.tvec = common.lookat(eye_pos, target_pos)
self.rvec = common.mtx2rvec(R)
self.draw_quads(dst, self.white_quads, (245, 245, 245))
self.draw_quads(dst, self.black_quads, (10, 10, 10))
classes = dict(chess=Chess, book=Book, cube=Cube)
presets = dict(
empty = 'synth:',
lena = 'synth:bg=lena.jpg:noise=0.1',
chess = 'synth:class=chess:bg=lena.jpg:noise=0.1:size=640x480',
book = 'synth:class=book:bg=graf1.png:noise=0.1:size=640x480',
cube = 'synth:class=cube:bg=pca_test1.jpg:noise=0.0:size=640x480'
)
def create_capture(source = 0, fallback = presets['chess']):
'''source: <int> or '<int>|<filename>|synth [:<param_name>=<value> [:...]]'
'''
source = str(source).strip()
# Win32: handle drive letter ('c:', ...)
source = re.sub(r'(^|=)([a-zA-Z]):([/\\a-zA-Z0-9])', r'\1?disk\2?\3', source)
chunks = source.split(':')
chunks = [re.sub(r'\?disk([a-zA-Z])\?', r'\1:', s) for s in chunks]
source = chunks[0]
try: source = int(source)
except ValueError: pass
params = dict( s.split('=') for s in chunks[1:] )
cap = None
if source == 'synth':
Class = classes.get(params.get('class', None), VideoSynthBase)
try: cap = Class(**params)
except: pass
else:
cap = cv.VideoCapture(source)
if 'size' in params:
w, h = map(int, params['size'].split('x'))
cap.set(cv.CAP_PROP_FRAME_WIDTH, w)
cap.set(cv.CAP_PROP_FRAME_HEIGHT, h)
if cap is None or not cap.isOpened():
print('Warning: unable to open video source: ', source)
if fallback is not None:
return create_capture(fallback, None)
return cap
if __name__ == '__main__':
import sys
import getopt
print(__doc__)
args, sources = getopt.getopt(sys.argv[1:], '', 'shotdir=')
args = dict(args)
shotdir = args.get('--shotdir', '.')
if len(sources) == 0:
sources = [ 0 ]
caps = list(map(create_capture, sources))
shot_idx = 0
while True:
imgs = []
for i, cap in enumerate(caps):
ret, img = cap.read()
imgs.append(img)
cv.imshow('capture %d' % i, img)
ch = cv.waitKey(1)
if ch == 27:
break
if ch == ord(' '):
for i, img in enumerate(imgs):
fn = '%s/shot_%d_%03d.bmp' % (shotdir, i, shot_idx)
cv.imwrite(fn, img)
print(fn, 'saved')
shot_idx += 1
cv.destroyAllWindows()
+211
View File
@@ -0,0 +1,211 @@
#include "opencv2/core.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"
using namespace cv;
using namespace cv::ml;
struct Data
{
Mat img;
Mat samples; //Set of train samples. Contains points on image
Mat responses; //Set of responses for train samples
Data()
{
const int WIDTH = 841;
const int HEIGHT = 594;
img = Mat::zeros(HEIGHT, WIDTH, CV_8UC3);
imshow("Train svmsgd", img);
}
};
//Train with SVMSGD algorithm
//(samples, responses) is a train set
//weights is a required vector for decision function of SVMSGD algorithm
bool doTrain(const Mat samples, const Mat responses, Mat &weights, float &shift);
//function finds two points for drawing line (wx = 0)
bool findPointsForLine(const Mat &weights, float shift, Point points[2], int width, int height);
// function finds cross point of line (wx = 0) and segment ( (y = HEIGHT, 0 <= x <= WIDTH) or (x = WIDTH, 0 <= y <= HEIGHT) )
bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair<Point,Point> &segment, Point &crossPoint);
//segments' initialization ( (y = HEIGHT, 0 <= x <= WIDTH) and (x = WIDTH, 0 <= y <= HEIGHT) )
void fillSegments(std::vector<std::pair<Point,Point> > &segments, int width, int height);
//redraw points' set and line (wx = 0)
void redraw(Data data, const Point points[2]);
//add point in train set, train SVMSGD algorithm and draw results on image
void addPointRetrainAndRedraw(Data &data, int x, int y, int response);
bool doTrain( const Mat samples, const Mat responses, Mat &weights, float &shift)
{
cv::Ptr<SVMSGD> svmsgd = SVMSGD::create();
cv::Ptr<TrainData> trainData = TrainData::create(samples, cv::ml::ROW_SAMPLE, responses);
svmsgd->train( trainData );
if (svmsgd->isTrained())
{
weights = svmsgd->getWeights();
shift = svmsgd->getShift();
return true;
}
return false;
}
void fillSegments(std::vector<std::pair<Point,Point> > &segments, int width, int height)
{
std::pair<Point,Point> currentSegment;
currentSegment.first = Point(width, 0);
currentSegment.second = Point(width, height);
segments.push_back(currentSegment);
currentSegment.first = Point(0, height);
currentSegment.second = Point(width, height);
segments.push_back(currentSegment);
currentSegment.first = Point(0, 0);
currentSegment.second = Point(width, 0);
segments.push_back(currentSegment);
currentSegment.first = Point(0, 0);
currentSegment.second = Point(0, height);
segments.push_back(currentSegment);
}
bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair<Point,Point> &segment, Point &crossPoint)
{
int x = 0;
int y = 0;
int xMin = std::min(segment.first.x, segment.second.x);
int xMax = std::max(segment.first.x, segment.second.x);
int yMin = std::min(segment.first.y, segment.second.y);
int yMax = std::max(segment.first.y, segment.second.y);
CV_Assert(weights.type() == CV_32FC1);
CV_Assert(xMin == xMax || yMin == yMax);
if (xMin == xMax && weights.at<float>(1) != 0)
{
x = xMin;
y = static_cast<int>(std::floor( - (weights.at<float>(0) * x + shift) / weights.at<float>(1)));
if (y >= yMin && y <= yMax)
{
crossPoint.x = x;
crossPoint.y = y;
return true;
}
}
else if (yMin == yMax && weights.at<float>(0) != 0)
{
y = yMin;
x = static_cast<int>(std::floor( - (weights.at<float>(1) * y + shift) / weights.at<float>(0)));
if (x >= xMin && x <= xMax)
{
crossPoint.x = x;
crossPoint.y = y;
return true;
}
}
return false;
}
bool findPointsForLine(const Mat &weights, float shift, Point points[2], int width, int height)
{
if (weights.empty())
{
return false;
}
int foundPointsCount = 0;
std::vector<std::pair<Point,Point> > segments;
fillSegments(segments, width, height);
for (uint i = 0; i < segments.size(); i++)
{
if (findCrossPointWithBorders(weights, shift, segments[i], points[foundPointsCount]))
foundPointsCount++;
if (foundPointsCount >= 2)
break;
}
return true;
}
void redraw(Data data, const Point points[2])
{
data.img.setTo(0);
Point center;
int radius = 3;
Scalar color;
CV_Assert((data.samples.type() == CV_32FC1) && (data.responses.type() == CV_32FC1));
for (int i = 0; i < data.samples.rows; i++)
{
center.x = static_cast<int>(data.samples.at<float>(i,0));
center.y = static_cast<int>(data.samples.at<float>(i,1));
color = (data.responses.at<float>(i) > 0) ? Scalar(128,128,0) : Scalar(0,128,128);
circle(data.img, center, radius, color, 5);
}
line(data.img, points[0], points[1],cv::Scalar(1,255,1));
imshow("Train svmsgd", data.img);
}
void addPointRetrainAndRedraw(Data &data, int x, int y, int response)
{
Mat currentSample(1, 2, CV_32FC1);
currentSample.at<float>(0,0) = (float)x;
currentSample.at<float>(0,1) = (float)y;
data.samples.push_back(currentSample);
data.responses.push_back(static_cast<float>(response));
Mat weights(1, 2, CV_32FC1);
float shift = 0;
if (doTrain(data.samples, data.responses, weights, shift))
{
Point points[2];
findPointsForLine(weights, shift, points, data.img.cols, data.img.rows);
redraw(data, points);
}
}
static void onMouse( int event, int x, int y, int, void* pData)
{
Data &data = *(Data*)pData;
switch( event )
{
case EVENT_LBUTTONUP:
addPointRetrainAndRedraw(data, x, y, 1);
break;
case EVENT_RBUTTONDOWN:
addPointRetrainAndRedraw(data, x, y, -1);
break;
}
}
int main()
{
Data data;
setMouseCallback( "Train svmsgd", onMouse, &data );
waitKey();
return 0;
}
+109
View File
@@ -0,0 +1,109 @@
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
class TravelSalesman
{
private :
const std::vector<Point>& posCity;
std::vector<int>& next;
RNG rng;
int d0,d1,d2,d3;
public:
TravelSalesman(std::vector<Point> &p, std::vector<int> &n) :
posCity(p), next(n)
{
rng = theRNG();
}
/** Give energy value for a state of system.*/
double energy() const;
/** Function which change the state of system (random perturbation).*/
void changeState();
/** Function to reverse to the previous state.*/
void reverseState();
};
void TravelSalesman::changeState()
{
d0 = rng.uniform(0,static_cast<int>(posCity.size()));
d1 = next[d0];
d2 = next[d1];
d3 = next[d2];
next[d0] = d2;
next[d2] = d1;
next[d1] = d3;
}
void TravelSalesman::reverseState()
{
next[d0] = d1;
next[d1] = d2;
next[d2] = d3;
}
double TravelSalesman::energy() const
{
double e = 0;
for (size_t i = 0; i < next.size(); i++)
{
e += norm(posCity[i]-posCity[next[i]]);
}
return e;
}
static void DrawTravelMap(Mat &img, std::vector<Point> &p, std::vector<int> &n)
{
for (size_t i = 0; i < n.size(); i++)
{
circle(img,p[i],5,Scalar(0,0,255),2);
line(img,p[i],p[n[i]],Scalar(0,255,0),2);
}
}
int main(void)
{
int nbCity=40;
Mat img(500,500,CV_8UC3,Scalar::all(0));
RNG rng(123456);
int radius=static_cast<int>(img.cols*0.45);
Point center(img.cols/2,img.rows/2);
std::vector<Point> posCity(nbCity);
std::vector<int> next(nbCity);
for (size_t i = 0; i < posCity.size(); i++)
{
double theta = rng.uniform(0., 2 * CV_PI);
posCity[i].x = static_cast<int>(radius*cos(theta)) + center.x;
posCity[i].y = static_cast<int>(radius*sin(theta)) + center.y;
next[i]=(i+1)%nbCity;
}
TravelSalesman ts_system(posCity, next);
DrawTravelMap(img,posCity,next);
imshow("Map",img);
waitKey(10);
double currentTemperature = 100.0;
for (int i = 0, zeroChanges = 0; zeroChanges < 10; i++)
{
int changesApplied = ml::simulatedAnnealingSolver(ts_system, currentTemperature, currentTemperature*0.97, 0.99, 10000*nbCity, &currentTemperature, rng);
img.setTo(Scalar::all(0));
DrawTravelMap(img, posCity, next);
imshow("Map", img);
int k = waitKey(10);
std::cout << "i=" << i << " changesApplied=" << changesApplied << " temp=" << currentTemperature << " result=" << ts_system.energy() << std::endl;
if (k == 27 || k == 'q' || k == 'Q')
return 0;
if (changesApplied == 0)
zeroChanges++;
}
std::cout << "Done" << std::endl;
waitKey(0);
return 0;
}
+116
View File
@@ -0,0 +1,116 @@
#include "opencv2/ml.hpp"
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include <stdio.h>
#include <string>
#include <map>
using namespace cv;
using namespace cv::ml;
static void help(char** argv)
{
printf(
"\nThis sample demonstrates how to use different decision trees and forests including boosting and random trees.\n"
"Usage:\n\t%s [-r=<response_column>] [-ts=type_spec] <csv filename>\n"
"where -r=<response_column> specified the 0-based index of the response (0 by default)\n"
"-ts= specifies the var type spec in the form ord[n1,n2-n3,n4-n5,...]cat[m1-m2,m3,m4-m5,...]\n"
"<csv filename> is the name of training data file in comma-separated value format\n\n", argv[0]);
}
static void train_and_print_errs(Ptr<StatModel> model, const Ptr<TrainData>& data)
{
bool ok = model->train(data);
if( !ok )
{
printf("Training failed\n");
}
else
{
printf( "train error: %f\n", model->calcError(data, false, noArray()) );
printf( "test error: %f\n\n", model->calcError(data, true, noArray()) );
}
}
int main(int argc, char** argv)
{
cv::CommandLineParser parser(argc, argv, "{ help h | | }{r | 0 | }{ts | | }{@input | | }");
if (parser.has("help"))
{
help(argv);
return 0;
}
std::string filename = parser.get<std::string>("@input");
int response_idx;
std::string typespec;
response_idx = parser.get<int>("r");
typespec = parser.get<std::string>("ts");
if( filename.empty() || !parser.check() )
{
parser.printErrors();
help(argv);
return 0;
}
printf("\nReading in %s...\n\n",filename.c_str());
const double train_test_split_ratio = 0.5;
Ptr<TrainData> data = TrainData::loadFromCSV(filename, 0, response_idx, response_idx+1, typespec);
if( data.empty() )
{
printf("ERROR: File %s can not be read\n", filename.c_str());
return 0;
}
data->setTrainTestSplitRatio(train_test_split_ratio);
std::cout << "Test/Train: " << data->getNTestSamples() << "/" << data->getNTrainSamples();
printf("======DTREE=====\n");
Ptr<DTrees> dtree = DTrees::create();
dtree->setMaxDepth(10);
dtree->setMinSampleCount(2);
dtree->setRegressionAccuracy(0);
dtree->setUseSurrogates(false);
dtree->setMaxCategories(16);
dtree->setCVFolds(0);
dtree->setUse1SERule(false);
dtree->setTruncatePrunedTree(false);
dtree->setPriors(Mat());
train_and_print_errs(dtree, data);
if( (int)data->getClassLabels().total() <= 2 ) // regression or 2-class classification problem
{
printf("======BOOST=====\n");
Ptr<Boost> boost = Boost::create();
boost->setBoostType(Boost::GENTLE);
boost->setWeakCount(100);
boost->setWeightTrimRate(0.95);
boost->setMaxDepth(2);
boost->setUseSurrogates(false);
boost->setPriors(Mat());
train_and_print_errs(boost, data);
}
printf("======RTREES=====\n");
Ptr<RTrees> rtrees = RTrees::create();
rtrees->setMaxDepth(10);
rtrees->setMinSampleCount(2);
rtrees->setRegressionAccuracy(0);
rtrees->setUseSurrogates(false);
rtrees->setMaxCategories(16);
rtrees->setPriors(Mat());
rtrees->setCalculateVarImportance(true);
rtrees->setActiveVarCount(0);
rtrees->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 0));
train_and_print_errs(rtrees, data);
cv::Mat ref_labels = data->getClassLabels();
cv::Mat test_data = data->getTestSampleIdx();
cv::Mat predict_labels;
rtrees->predict(data->getSamples(), predict_labels);
cv::Mat variable_importance = rtrees->getVarImportance();
std::cout << "Estimated variable importance" << std::endl;
for (int i = 0; i < variable_importance.rows; i++) {
std::cout << "Variable " << i << ": " << variable_importance.at<float>(i, 0) << std::endl;
}
return 0;
}