openCV k-means调用断言失败

汤美

我已经从openCV源代码发布的samples文件夹中读取了c ++ sample,并且,如果省略了随机图片生成,kmeans调用看起来非常简单-作者甚至不分配center / labels数组(您可以在这里找到它)。但是,我无法在C中执行相同的操作。如果不分配标签,则会出现断言错误:

OpenCV错误:断言失败(labels.isContinuous()&& labels.type()== CV_32S &&(labels.cols == 1 || labels.rows == 1)&& labels.cols + labels.rows-1 ==数据.rows)在cvKMeans2中,文件/tmp/opencv-xiht/opencv-2.4.9/modules/core/src/matrix.cpp,第3094行

好的,我试图创建一个空labels矩阵,但是断言消息根本没有改变。

IplImage* image = cvLoadImage("test.jpg", -1);
IplImage* normal = cvCreateImage(cvGetSize(image), IPL_DEPTH_32F, image->nChannels);
cvConvertScale(image, normal, 1/255.0, 0);
CvMat* points = cvCreateMat(image->width, image->height, CV_32F);
points->data.fl = normal->imageData;

CvMat* labels = cvCreateMat(1, points->cols, CV_32S);
CvMat* centers = NULL;

CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);

// KMEANS_PP_CENTERS is undefined
int KMEANS_PP_CENTERS = 2;
cvKMeans2(points, 4, labels, criteria, 3, NULL, KMEANS_PP_CENTERS, centers, 0);

让我发疯的事情是:

CvMat* labels = cvCreateMat(1, points->cols, CV_32S);
int good = labels->type == CV_32S; // FALSE here

显然,这是一个导致断言失败的问题(不确定是否唯一)。这应该如何工作?我不能使用С++ API,因为整个应用程序都使用纯C语言。

米卡

该断言告诉您:

  1. 类型必须CV_32S在您的代码中似乎是这种情况,也许您的if语句为false,因为类型已自动更改为CV_32SC1?不知道...

  2. 您可以将每个点放置在一行或一列中,因此is set to 1必须将行/列和另一维设置为data.rows,以指示data您要聚类的点以将每个点放置在行中的格式保存,从而导致#points行。因此,使该断言消失的错误似乎CvMat* labels = cvCreateMat(1, points->cols, CV_32S);应该CvMat* labels = cvCreateMat(1, points->rows, CV_32S);改为,但从points概念上来说,您的使用似乎是错误的。

您可能必须将您的观点(您想聚类)放在cvMatwithn rows2 cols of type CV_32FC1or中1 col and type CV_32FC2(也许两个版本都可以使用,也许只有一个版本,或者在那儿我完全错了)。

编辑:我写了一个对我有用的简短代码段:

// here create the data array where your input points will be hold:
CvMat* points = cvCreateMat( numberOfPoints , 2 /* 2D points*/ , CV_32F);

// this is a float array of the 
float* pointsDataPtr = points->data.fl;
// fill the mat:
for(unsigned int r=0; r<samples.size(); ++r)
{
    pointsDataPtr[2*r] = samples.at(r).x; // this is the x coordinate of your r-th point
    pointsDataPtr[2*r+1] = samples.at(r).y; // this is the y coordinate of your r-th point
}


// this is the data array for the labels, which will be the output of the method.
CvMat* labels = cvCreateMat(1, points->rows, CV_32S);
// this is the quit criteria, which I did neither check nor modify, just used your version here.
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);

// call the method for 2 cluster
cvKMeans2(points, 2, labels, criteria);

// now labels holds numberOfPoints labels which have either value 0 or 1 since we searched for 2 cluster

int* labelData = labels->data.i; // array to the labels
for(unsigned int r=0; r<samples.size(); ++r)
{
    int labelOfPointR = labelData[r]; // this is the value of the label of point number r

    // here I use c++ API to draw the points, do whatever else you want to do with the label information (in C API). I choose different color for different labels.
    cv::Scalar outputColor;
    switch(labelOfPointR)
    {
        case 0: outputColor = cv::Scalar(0,255,0); break;
        case 1: outputColor = cv::Scalar(0,0,255); break;
        default: outputColor = cv::Scalar(255,0,255); break;    // this should never happen for 2 clusters...
    }
    cv::circle(outputMat, samples.at(r), 2, outputColor);
}

给我一些生成的点数据的结果:

在此处输入图片说明

也许您也需要这些中心,C API为您提供了返回它们的选项,但没有检查它的工作方式。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章