openCV k-means调用断言失败

时间:2014-12-09 14:25:23

标签: c opencv

我已经从openCV源代码分发的samples文件夹中读取了c ++示例,如果省略随机图片生成,kmeans调用看起来很简单 - 作者甚至不分配中心/标签数组(你可以找到它{{3 }})。但是,我不能在C中做同样的事。如果我没有分配标签,我会得到断言错误:

  

OpenCV错误:断言失败(labels.isContinuous()&& labels.type()   == CV_32S&& (labels.cols == 1 || labels.rows == 1)&& cvKMeans2文件中的labels.cols + labels.rows - 1 == data.rows)   /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 个答案:

答案 0 :(得分:2)

断言告诉你:

  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的使用似乎在概念上是错误的。

  3. 您可能必须在cvMat n rows2 cols of type CV_32FC11 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);
    }
    

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

    enter image description here

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