如何在OpenCV的KMeans算法中使用KMEANS_USE_INITIAL_LABELS参数设置初始标签

3
我正在使用OpenCV KMeans对从ConvexHull返回的点进行聚类。
在我的情况下,我将得到3个点。在下一次循环中,我想用这些最后找到的3个点提供给KMeans。我读到我需要设置KMEANS_USE_INITIAL_LABELS。
但我怎样设置初始标签/点呢?
这是我目前拥有的,但它会返回错误:
//get all convexhull points and average them in 3 groups
                    int dimensions = 2;
                    float pointsdata[sampleCount*2]; //[] = {1,1, 2,2, 6,6, 5,5, 10,10};

                    int cnt = 0;
                    for(int a=0; a<sampleCount; a++){
                        pointsdata[cnt] = convexHull[a].x;
                        cnt++;
                        pointsdata[cnt] = convexHull[a].y;
                        cnt++;
                    }

                    cv::Mat points;
                    points = cv::Mat(sampleCount,dimensions, CV_32F,pointsdata);

                    int clusterCount = 3; //i want 3 averaged points back

                    cv::Mat labels;
                    labels = cv::Mat(3,1,points.type());
                    labels.at<float>(0,0) = pointA.x;
                    labels.at<float>(0,1) = pointA.y;

                    labels.at<float>(0,2) = pointB.x;
                    labels.at<float>(0,3) = pointB.y;

                    labels.at<float>(0,4) = pointC.x;
                    labels.at<float>(0,5) = pointC.y;

                    cv::Mat centers;
                    centers = cv::Mat(clusterCount, 1, points.type());



                    kmeans(points, 3, labels, cv::TermCriteria(), 2,cv::KMEANS_USE_INITIAL_LABELS, &centers);

更新: 好的,我现在知道标签指的是输入聚类中点的索引,而不是实际坐标。 所以应该更像这样,但仍然是错误的。
cv::Mat labels;
                    labels = cv::Mat(3,1,points.type());
                    labels.at<int>(0,0) = labelA;
                    labels.at<int>(0,1) = labelB;
                    labels.at<int>(0,2) = labelC;
3个回答

1
初始聚类分配需要为 CV_32S 类型,而非 CV_32F。您可以在 matrix.cpp 中查看其他条件。
CV_Assert( (best_labels.cols == 1 || best_labels.rows == 1) &&
              best_labels.cols*best_labels.rows == N &&
              best_labels.type() == CV_32S &&
              best_labels.isContinuous());

你的标签值应该在范围[0,N)内,其中N是行数。

0
cv::Mat labels;
labels = cv::Mat(3,1,points.type());
labels.at<int>(0,0) = labelA;
labels.at<int>(1,0) = labelB;
labels.at<int>(2,0) = labelC;

顺便提一下:您在上面的编辑中的代码是错误的。您已经分配了三行并正在写入三列。


0
cv::Mat labels;
labels = cv::Mat(sampleCount,1,CV_32S);
for(int i = 0; i < sampleCount; i++)
    labels.at<int>(i,0) = 0;
labels.at<int>(position1, 0) = 0;
labels.at<int>(position2, 0) = 1;
labels.at<int>(position3, 0) = 2;

labels是一个1*N或N*1的整数数组,用于存储样本中每个点的聚类ID。因此,请确保:

  1. labels的大小:1*N或N*1(不是1*K或K*1)
  2. labels的类型:CV_32S,因为它存储聚类ID,所以应该是整数
  3. labels的范围:labels中的每个元素都在[0,K)之间

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接