繁体   English   中英

使用OpenCV cv :: kmeans()和一维输入

[英]Using OpenCV cv::kmeans() with one-dimensional input

虽然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);

由于cv :: kmeans期望输入是二维的,因此内部断言失败。 CV_Assert(N>=K)失败,因为K是3而N是1.我的错误是什么?

麻烦的是当你将一个向量传递给一个接受InputArray的东西时,当在该InputArray上调用getMat()时,会创建一个带有1行的Mat。 但是由于Xocoatzin在消息来源中指出的原因,在这种情况下这不会起作用。 你显然无法重塑一个向量,尽管已经提出过。 如果您的输入是矢量,并且您无法更改它,则需要将矢量显式转换为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);

编辑

我刚检查了一下,它的内容如下:

//...
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 (不要忘记重塑)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM