Issue 1:
Transferred from http://code.opencv.org/issues/4455

|| Jens Garstka on 2015-07-01 08:32
|| Priority: Normal
|| Affected: branch 'master' (3.0-dev)
|| Category: ml
|| Tracker: Bug
|| Difficulty: Easy
|| PR:
|| Platform: x64 / Linux

SVM write/load problems with kernels other than linear

Within the implementation of the SVMs write and read methods (modules/ml/src/svm.cpp, lines 2022 ff and 2139 ff), the author makes the assumption, that support vector indices are not required in 2-class problems. That is probably correct if a linear kernel is used (i.e., when you have only one support vector). But with other kernels (in my case with an RBF kernel), the support vector indices are definitly required.

I've added a git diff where this questionable conditions are commented out. Without these lines everything works fine.

IMHO the lines should be removed.

History

Hyunjun Kim on 2015-07-03 07:35

Hi, I was able to reproduce the error. I confirmed that cv::Algorithm::load() works well only with SVM::LINEAR kernel.

<pre>
#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**)
{
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);

// Set up training data
int labels[4] = {1, -1, -1, -1};
Mat labelsMat(4, 1, CV_32SC1, labels);

float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

// Set up SVM's parameters
Ptr<ml::SVM> svm = ml::SVM::create();
svm->setType(ml::SVM::C_SVC);
svm->setKernel(SVM::INTER); // Algorithm::load() works well with SVM::LINEAR
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

// Train the SVM
svm->train(ml::TrainData::create(trainingDataMat, ml::ROW_SAMPLE, labelsMat));

// Save and load SVM
svm->save("ex_svm.xml");
svm= cv::Algorithm::load<ml::SVM>("ex_svm.xml"); // something is wrong

Vec3b green(0,255,0), blue (255,0,0);
// Show the decision regions given by the SVM
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1,2) << 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 the training data
int thickness = -1;
int lineType = 8;
circle( image, Point(501, 10), 5, Scalar( 0, 0, 0), thickness, lineType );
circle( image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType );
circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType );
circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness, lineType );

// Show support vectors
thickness = 2;
lineType = 8;

Mat sv = svm->getSupportVectors();

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, lineType);
}

imwrite("result.png", image); // save the image

imshow("SVM Simple Example", image); // show it to the user
waitKey(0);

}
</pre>

Maksim Shabunin on 2015-07-13 08:56

- Assignee set to Maksim Shabunin

Issue 2:
System information (version)

OpenCV => 4.1.1

Operating System / Platform => Windows 10 64bit

Compiler => Visual Studio 2019 16.2.0

Detailed description

I have an original image in green tones:

In legacy code with OpenCV 3.1.0 it was converted to normal colors with:

cv::cvtColor(Mat(size.height, size.width, CV_16UC1, rawRight.data), frameRight, color);	// convert CV_8UC2 to CV_16UC1

And it's work ok.

But when I update OpenCV 4.1.1. And it began to work with problems. Instead of the image with normal colors received:

I tried sorting through all the methods from enum:

https://docs.opencv.org/4.1.1/d8/d01/group__imgproc__color__conversions.html#ga4e0972be5de079fed4e3a10e24ef5ef0

but not one made the colors right.

OpenCV gives the following image information:

[i] channels: 3
[i] pixel depth: 0 bits
[i] elemSize: 3 bytes
[i] elemSize1: 1 bytes
[i] type: CV_8UC3

I would be grateful for any help.