【问题标题】:openCV k-means call assertion failedopenCV k-means 调用断言失败
【发布时间】:2015-02-07 11:32:17
【问题描述】:

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

OpenCV 错误:断言失败 (labels.isContinuous() && labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == data.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 语言。

【问题讨论】:

  • 很好,我在 26 秒时发布了问题。以前并且已经得到-1。否决投票者请解释一下,我做错了什么?
  • 我没有投反对票。据我所知(至少在过去是这样的)你必须在 C api 中手动分配所有的 openCV 东西(输出图像、缓冲区等)!关于您的错误:改用CvMat* labels = cvCreateMat(1, points->rows, CV_32S);
  • 不确定这个,但看起来有问题:CvMat* points = cvCreateMat(image->width, image->height, CV_32F); 应该类似于:CvMat* points = cvCreateMat(yourNumberOfPoints, yourDimensionOfPoints_probably_2_for_2D, CV_32F);,您将在此处输入 x/y 坐标。
  • points->rows 使断言失败消失。我不明白为什么它不再失败,因为labels->type == CV_32S 仍然是错误的,但看起来我在传递正确格式化的数据时遇到了另一个麻烦。也许阅读 c++ 或 python 函数的源代码来找出它对我来说是个好主意。谢谢@Micka,我认为您已经回答并可以发布您的答案,以便我接受。 @berak:不幸的是,我坚持使用过时的 sht,我很想改用 C# 编写,但是...
  • 你能试试labels->type == CV_32SC1是不是真的吗?

标签: c opencv


【解决方案1】:

断言告诉你:

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

  2. 1234563以将每个点放置在一行中的格式进行聚类,导致 #points 行。因此,您的错误似乎是 CvMat* labels = cvCreateMat(1, points->cols, CV_32S); 而应该是 CvMat* labels = cvCreateMat(1, points->rows, CV_32S);,以使断言消失,但您对 points 的使用似乎在概念上是错误的。

您可能必须在cvMatn rows2 cols of type CV_32FC11 col and type CV_32FC2 中保留您的观点(您想聚集)(也许两个版本都有效,也许只有一个,或者我错了完全)。

编辑:我写了一个适合我的短代码 sn-p:

// 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 为您提供了返回它们的选项,但没有检查它是如何工作的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-10
    • 2016-07-21
    • 2012-11-26
    • 2014-11-24
    • 2014-05-28
    • 2020-12-31
    • 2015-09-12
    • 2015-04-25
    相关资源
    最近更新 更多