Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

related sample

"When asked to classify a point at y = 0, the SVM incorrectly returns 1" -- you're actually testing a point at (0,H/2) so the classification is correct.

  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1" --

    you're actually testing a point at (0,H/2)(0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of individual elements). that's also, why the support vector has wrong values.

  • mSVM->getSupportVectors() actually retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]
  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values.

  • mSVM->getSupportVectors() actually retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]
  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values.

  • mSVM->getSupportVectors() actually retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]
  • > (using Cinder as a graphical wrapper). -- that's a bit sad, because it makes your code irreproducable.
  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values.values. if you still want to use this contruct, please use Point2f , not Point

  • mSVM->getSupportVectors() actually retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]
  • >

    (using Cinder as a graphical wrapper). -- that's a bit sad, because it makes your code irreproducable.

  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values. if you still want to use this contruct, please use Point2f , not Point

  • mSVM->getSupportVectors() retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]

(using Cinder as a graphical wrapper). -- that's a bit sad, because it makes your code irreproducable.

here's modified code for reference:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

class exampleClassificationApp {
  public:
    void setup(int w, int h);
    void draw(int w, int h);

    std::vector<cv::Point2f> mPoints;
    std::vector<int> mLabels;
    cv::Ptr<cv::ml::SVM> mSVM;
};

void exampleClassificationApp::setup(int w,int h) {
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(0.0f, float(x));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(-1.0);
    }
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(x, float(h));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(1.0);
    }
    cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data());
    cv::Mat trainingLabels(mLabels.size(), 1, CV_32SC1, mLabels.data());

    mSVM = cv::ml::SVM::create();

    mSVM->setType(cv::ml::SVM::C_SVC);
    mSVM->setKernel(cv::ml::SVM::LINEAR);
    mSVM->setC(1.0);

    mSVM->train(trainingData, cv::ml::ROW_SAMPLE, trainingLabels);

    float data[2] = { 0, float(w) / 2.0f };
    cv::Mat query(1, 2, CV_32F, data);
    int response = mSVM->predict(query);

    std::printf("Asked SVM where to classify %f, %f -- result was %d\n", query.at<float>(0,0), query.at<float>(0, 1), response);
}

void exampleClassificationApp::draw(int w, int h) {
    Mat img(h,w,CV_8UC3,Scalar::all(60));
    for (int i = 0; i < mPoints.size(); i++) {
        Point p = mPoints[i];
        p.y = h - p.y;
        if (mLabels[i] == -1) {
            circle(img, p, 5, Scalar(200, 0, 0), -1);
        }
        else {
            circle(img, p, 5, Scalar(0,0,200), -1);
        }
    }
    imshow("img", img);
    waitKey();
    cv::Mat supports;
    if (mSVM->isTrained()) {
        supports = mSVM->getSupportVectors();
        std::cout << "Support Vectors are " << supports << std::endl;
        supports = mSVM->getUncompressedSupportVectors();
        std::cout << "uncompressed Support Vectors are " << supports << std::endl;

    }   
}

int main() {
    exampleClassificationApp app;
    app.setup(400,400);
    app.draw(400,400);
    return 0;
}
  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values. if you still want to use this contruct, please use Point2f , not Point

  • mSVM->getSupportVectors() retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]

(using Cinder as a graphical wrapper). -- that's a bit sad, because it makes your code irreproducable.

here's modified code for reference:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

class exampleClassificationApp {
  public:
    void setup(int w, int h);
    void draw(int w, int h);

    std::vector<cv::Point2f> mPoints;
    std::vector<int> mLabels;
    cv::Ptr<cv::ml::SVM> mSVM;
};

void exampleClassificationApp::setup(int w,int h) {
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(0.0f, float(x));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(-1.0);
    }
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(x, float(h));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(1.0);
    }
    cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data());
    cv::Mat trainingLabels(mLabels.size(), 1, CV_32SC1, mLabels.data());

    mSVM = cv::ml::SVM::create();

    mSVM->setType(cv::ml::SVM::C_SVC);
    mSVM->setKernel(cv::ml::SVM::LINEAR);
    mSVM->setC(1.0);

    mSVM->train(trainingData, cv::ml::ROW_SAMPLE, trainingLabels);

    float data[2] = { 0, float(w) / 2.0f };
    cv::Mat query(1, 2, CV_32F, data);
    int response = mSVM->predict(query);

    std::printf("Asked SVM where to classify %f, %f -- result was %d\n", query.at<float>(0,0), query.at<float>(0, 1), response);
}

void exampleClassificationApp::draw(int w, int h) {
    Mat img(h,w,CV_8UC3,Scalar::all(60));
    for (int i = 0; i < mPoints.size(); i++) {
        Point p = mPoints[i];
        p.y = h - p.y;
p.y; // y-axis points down in opencv
        if (mLabels[i] == -1) {
            circle(img, p, 5, Scalar(200, 0, 0), -1);
        }
        else {
            circle(img, p, 5, Scalar(0,0,200), -1);
        }
    }
    imshow("img", img);
    waitKey();
    cv::Mat supports;
    if (mSVM->isTrained()) {
        supports = mSVM->getSupportVectors();
        std::cout << "Support Vectors are " << supports << std::endl;
        supports = mSVM->getUncompressedSupportVectors();
        std::cout << "uncompressed Support Vectors are " << supports << std::endl;

    }   
}

int main() {
    exampleClassificationApp app;
    app.setup(400,400);
    app.draw(400,400);
    return 0;
}
  • please have a look at a related sample

  • "When asked to classify a point at y = 0, the SVM incorrectly returns 1"

    you're actually testing a point at (0,W/2), not (W/2,0) so the classification is correct.

  • cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data()); <-- you cannot put a vector of integer points into a float Mat (which just casts the pointer instead of converting individual elements). that's also, why the support vector has wrong values. if you still want to use this contruct, please use Point2f , not Point

  • mSVM->getSupportVectors() retrieves the single compressed support vector for a linear SVM, if you check mSVM->getUncompressedSupportVectors() you'll get a nice diagonal:


[174.18019, 168.38301;
 228.93629, 216.20596;
 10.42392, 10.316812;
 342.7677, 342.85413;
 21.18305, 32.687538;
 93.60273, 96.210686;
 399.43951, 399.63388]

(using Cinder as a graphical wrapper). -- that's a bit sad, because it makes your code irreproducable.

here's modified code for reference:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

class exampleClassificationApp {
  public:
    void setup(int w, int h);
    void draw(int w, int h);

    std::vector<cv::Point2f> mPoints;
    std::vector<int> mLabels;
    cv::Ptr<cv::ml::SVM> mSVM;
};

void exampleClassificationApp::setup(int w,int h) {
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(0.0f, float(x));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(-1.0);
mLabels.push_back(-1);
    }
    for (int i = 0; i < 100; i++) {
        float x = cv::theRNG().uniform(0.0f, float(w));
        float y = cv::theRNG().uniform(x, float(h));
        mPoints.push_back(cv::Point2f(x, y));
        mLabels.push_back(1.0);
mLabels.push_back(1);
    }
    cv::Mat trainingData(mPoints.size(), 2, CV_32FC1, mPoints.data());
    cv::Mat trainingLabels(mLabels.size(), 1, CV_32SC1, mLabels.data());

    mSVM = cv::ml::SVM::create();

    mSVM->setType(cv::ml::SVM::C_SVC);
    mSVM->setKernel(cv::ml::SVM::LINEAR);
    mSVM->setC(1.0);

    mSVM->train(trainingData, cv::ml::ROW_SAMPLE, trainingLabels);

    float data[2] = { 0, float(w) / 2.0f };
    cv::Mat query(1, 2, CV_32F, data);
    int response = mSVM->predict(query);

    std::printf("Asked SVM where to classify %f, %f -- result was %d\n", query.at<float>(0,0), query.at<float>(0, 1), response);
}

void exampleClassificationApp::draw(int w, int h) {
    Mat img(h,w,CV_8UC3,Scalar::all(60));
    for (int i = 0; i < mPoints.size(); i++) {
        Point p = mPoints[i];
        p.y = h - p.y; // y-axis points down in opencv
        if (mLabels[i] == -1) {
            circle(img, p, 5, Scalar(200, 0, 0), -1);
        }
        else {
            circle(img, p, 5, Scalar(0,0,200), -1);
        }
    }
    imshow("img", img);
    waitKey();
    cv::Mat supports;
    if (mSVM->isTrained()) {
        supports = mSVM->getSupportVectors();
        std::cout << "Support Vectors are " << supports << std::endl;
        supports = mSVM->getUncompressedSupportVectors();
        std::cout << "uncompressed Support Vectors are " << supports << std::endl;

    }   
}

int main() {
    exampleClassificationApp app;
    app.setup(400,400);
    app.draw(400,400);
    return 0;
}