【问题标题】:Creating a clustered image from kmeans data in OpenCV从 OpenCV 中的 kmeans 数据创建聚类图像
【发布时间】:2011-10-24 23:01:39
【问题描述】:

我正在尝试根据从 kmeans 函数返回的数据创建一个聚类图像。我尝试以类似的方式从 OpenCV 示例中提取数据,但这似乎让我崩溃了。经过进一步的研究,我发现有人使用中心提取了数据,但没有对这些数据做任何事情,所以我的追踪就到此为止了。

我在下面包含了我的代码的 sn-p 和我正在做的事情。任何帮助将不胜感激。

编辑 我已经将我的代码恢复到原始状态,没有任何测试变量。上述错误仍然存​​在。我还在下面添加了一些关于我的图像的调试信息:

图片信息:

  • 尺寸:2
  • 图像数据:
  • 尺寸0:256
  • 尺寸 1:256
  • 元素尺寸 1:12
  • 元素大小 2:4

虽然数据为 NULL,但如果我在其上调用 cv::imshow,我仍然可以查看数据。

// mImage is a cv::Mat that was created from a 256 x 256 image with the depth of
// CV_32F and 3 channels
// labels is a cv::Mat that was created by converting the image into a 256 x 256
// CV_8UC1 IplImage
kmeans(mImage, 6, labels, termcrit, 3, cv::KMEANS_PP_CENTERS, centers);
float* c = new float[6];
memcpy(c, centers.ptr<float>(0), sizeof(float)*6);

// Block of code that crashes when I do "mImage.at<cv::Point2f>(i)" with the error:
/* OpenCV Error: Assertion failed (dims <= 2 && data && (size.p[0] == 1 || 
       size.p[1] == 1) && (unsigned)i0 < (unsigned)(size.p[0] + size.p[1] - 1) && 
       elemSize() == (((((DataType<_Tp>::type) & ((512 - 1) << 3)) >> 3) + 1) << 
       ((((sizeof(size_t)/ 4+1)*16384|0x3a50) >> ((DataType<_Tp>::type) & 
       ((1 << 3) - 1))*2) & 3))) in unknown function, file 
       c:\opencv-2.3.0\modules\core\include\opencv2\core\mat.hpp, line 583 */

for(int i = 0; i < list.rows; i++)
{
    int clusterIdx = list.at<int>(i);
    cv::Point ipt = mImage.at<cv::Point2f>(i);
    circle( miplImage, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA );
}

【问题讨论】:

    标签: c image-processing opencv k-means


    【解决方案1】:

    您在调用 mRegion.at() 时遇到断言错误。 mRegion 是在哪里定义的?

    这是来自kmeans.cpp 示例代码的等效 sn-p:

        kmeans(points, clusterCount, labels, 
               TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
               3, KMEANS_PP_CENTERS, centers);
    
        img = Scalar::all(0);
    
        for( i = 0; i < sampleCount; i++ )
        {
            int clusterIdx = labels.at<int>(i);
            Point ipt = points.at<Point2f>(i);
            circle( img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA );
        }
    

    它对kmeans 的第一个参数和for 循环中ipt 的源使用相同的变量points。我想你可能想在for 循环中使用mImage,而不是mRegion。

    编辑 现在您已经更改了代码以在for 循环中使用 mImage,您需要了解为什么会出现断言错误。断言消息被模板代码弄得很乱,所以这里来自 mat.hpp:

    dims <= 2 && data && (size.p[0] == 1 || size.p[1] == 1) &&
                 (unsigned)i0 < (unsigned)(size.p[0] + size.p[1] - 1) &&
                 elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type)
    

    其中一项或多项测试失败。如果您使用的是空的 mImage,那将是失败的,因为 data 将为零。您不能在空矩阵上调用 at。无论如何,请检查 mImage 的属性以查看导致断言错误的原因。

    【讨论】:

    • 很抱歉省略了一些变量,因为我只是在测试不同的技术,看看是否能得到一些东西。 mRegion 只是一个空矩阵,其维度和类型为 mImage。我尝试使用 mImage 并通过该错误尝试,所以我尝试使用空矩阵并得到相同的错误。
    • 那么在这种情况下我是否必须将我的 256x256 图像转换为 65536x1 的数组?
    • 不,256x256 没问题。这就是dims &lt;= 2 测试。您可能失败了,因为data 为零或i 大于点数。尝试在for 循环之前添加cout &lt;&lt; "data: " &lt;&lt; mImage.data &lt;&lt; endl;
    • 我在尝试转换矩阵时似乎丢失了数据。现在我必须找出如何保存数据。感谢您的帮助。
    • 事实证明你不能直接在图像上运行 kmeans。它需要在包含坐标的 n 行 1 列矩阵上运行。在这种情况下,它们是二维坐标。我自己没有这样做,但也许你可以在输入图像上运行一个阈值,然后用高于阈值的像素尺寸填充一个矩阵。
    猜你喜欢
    • 1970-01-01
    • 2016-05-11
    • 2013-03-24
    • 2016-02-03
    • 2012-06-30
    • 2020-11-18
    • 2012-05-01
    • 2018-08-13
    相关资源
    最近更新 更多