[英]Using OpenCV cv::kmeans() with one-dimensional input
Although the python tutorial uses one-dimensional data, I cannot do the same with the C++ interface: 虽然python教程使用一维数据,但我不能对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);
This fails with an internal assertion since cv::kmeans expects the input to be two-dimensional. 由于cv :: kmeans期望输入是二维的,因此内部断言失败。
CV_Assert(N>=K)
fails since K is 3 and N is 1. What is my mistake? CV_Assert(N>=K)
失败,因为K是3而N是1.我的错误是什么?
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. 麻烦的是当你将一个向量传递给一个接受InputArray的东西时,当在该InputArray上调用getMat()时,会创建一个带有1行的Mat。 But that won't work in this case for the reason Xocoatzin pointed out in the source.
但是由于Xocoatzin在消息来源中指出的原因,在这种情况下这不会起作用。 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.
如果您的输入是矢量,并且您无法更改它,则需要将矢量显式转换为1列Mat,如下所示。
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
. 因此,如果您将数据放在一行中,则需要在输入矩阵中包含多个通道,并且列数多于
K
A quick workaround: reshape your matrix before calling kmeans
快速解决方法:在调用
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: 重塑2行后:
[1234| // a mat 2 x 4
|5678]
You should be able to call kmeans
then. 你应该能够打电话给
kmeans
。 (Don't forget to reshape back) (不要忘记重塑)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.