Хотя учебник по питону использует одномерные данные, я не могу сделать то же самое с интерфейсом C ++:
int size=100;
std::vector<float> data(size);
for (size_t i = 0; i < size ; i++)
{
data[i] = (float)i; //placeholder
}
std::vector<int> labels;
std::vector<float> centers;
cv::kmeans(data, 3, labels,
cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 10, 0.1),
3, cv::KMEANS_PP_CENTERS, centers);
Это терпит неудачу с внутренним утверждением, поскольку cv :: kmeans ожидает, что ввод будет двумерным. CV_Assert(N>=K)
терпит неудачу, так как K — 3, а N — 1. В чем моя ошибка?
РЕДАКТИРОВАТЬ:
Я только что проверил источник, он читает:
//...
bool isrow = data.rows == 1 && data.channels() > 1; // MORE THAN ONE CHANNEL
int N = !isrow ? data.rows : data.cols;
//...
//...
CV_Assert( N >= K );
Итак, если у вас есть данные в одной строке, вам нужно иметь более одного канала в матрице ввода и больше столбцов, чем K
,
Быстрый обходной путь: перекроить Ваша матрица перед звонком kmeans
Он не копирует какие-либо данные, просто меняет размеры матрицы. Так что если у вас есть:
[12345678] // mat 1 x 8
После того, как вы измените форму с 2 рядами:
[1234| // a mat 2 x 4
|5678]
Вы должны быть в состоянии позвонить kmeans
затем. (Не забудьте изменить форму обратно)
Проблема в том, что когда вы передаете вектор чему-то, что принимает InputArray, когда getMat () вызывается для этого InputArray, создается Mat с 1 строкой. Но это не сработает в этом случае по причине, указанной Ксокоацин в источнике. Вы, очевидно, не можете изменить вектор, хотя это было предложено. Если ваш ввод является вектором, и вы не можете это изменить, вам нужно явно преобразовать вектор в Mat из 1 столбца, как показано ниже.
int size=100;
std::vector<float> data(size);
for (size_t i = 0; i < size ; i++)
{
data[i] = (float)i; //placeholder
}
cv::Mat data_mat(data.size(), 1, CV32FC1, &data[0]); // ** Make 1 column Mat from vector
std::vector<int> labels;
std::vector<float> centers;
cv::kmeans(data_mat, 3, labels, // ** Pass 1 column Mat from Mat to kmeans
cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 10, 0.1),
3, cv::KMEANS_PP_CENTERS, centers);