Although the python tutorial uses one-dimensional data, I cannot do the same with the C++ interface:
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);
This fails with an internal assertion since cv::kmeans expects the input to be two-dimensional. CV_Assert(N>=K)
fails since K is 3 and N is 1. What is my mistake?
The trouble is that when you pass a vector to something that takes an InputArray, when getMat() gets called on that InputArray a Mat with 1 row gets created. But that won't work in this case for the reason Xocoatzin pointed out in the source. You obviously can't reshape a vector, although that has been suggested. If your input is a vector, and you can't change that, you need to explicitly convert the vector into a 1 column Mat, like below.
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);
EDIT :
I've just checked the source, it reads:
//...
bool isrow = data.rows == 1 && data.channels() > 1; // MORE THAN ONE CHANNEL
int N = !isrow ? data.rows : data.cols;
//...
//...
CV_Assert( N >= K );
So, if you have your data in a single row, you need to have more than a single channel in your input matrix and more columns than K
.
A quick workaround: reshape your matrix before calling kmeans
It doesn't copy any data, just changes the dimensions of the matrix. So if you have:
[12345678] // mat 1 x 8
After you reshape with 2 rows:
[1234| // a mat 2 x 4
|5678]
You should be able to call kmeans
then. (Don't forget to reshape back)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.