You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenCV对CSV时序数据执行k-means时遇访问冲突问题求助

解决OpenCV K-Means崩溃及Centers为空的问题

嘿,我仔细看了你的代码,马上就找到了导致kmeans崩溃、centers无法正常生成的核心问题——Mat的类型与元素访问方式不匹配,这直接引发了内存访问越界,让kmeans函数内部出错。

核心错误点

你创建Mat的时候指定了CV_32F(单精度浮点型,每个元素占4字节):

cv::Mat data_mat = cv::Mat::zeros((int)all_data.size(), (int)all_data[0].size(), CV_32F);

但赋值时却用了at<double>(双精度浮点型,每个元素占8字节)去读写:

data_mat.at<double>(rows, cols) = all_data[rows][cols];

这种类型不匹配会直接破坏Mat的内存结构,后续调用kmeans时自然会触发内存访问异常,连centers都没法正常初始化,所以你看到它的属性全是空的。

修复方案(二选一即可)

方案1:保持Mat为CV_32F,用float类型访问

把赋值时的at<double>改成at<float>,同时把double类型的数据转成float:

cv::Mat data_mat = cv::Mat::zeros((int)all_data.size(), (int)all_data[0].size(), CV_32F);
for (int rows = 0; rows < (int)all_data.size(); rows++) { 
    for (int cols = 0; cols < (int)all_data[0].size(); cols++) { 
        data_mat.at<float>(rows, cols) = static_cast<float>(all_data[rows][cols]); 
    } 
}

方案2:将Mat改为CV_64F,用double类型访问

如果想保留双精度的精度,直接把Mat的类型改成CV_64F,这样用at<double>就没问题了:

cv::Mat data_mat = cv::Mat::zeros((int)all_data.size(), (int)all_data[0].size(), CV_64F);
for (int rows = 0; rows < (int)all_data.size(); rows++) { 
    for (int cols = 0; cols < (int)all_data[0].size(); cols++) { 
        data_mat.at<double>(rows, cols) = all_data[rows][cols]; 
    } 
}

后续验证与优化建议

  1. 验证Mat正确性:修复后可以先打印Mat的类型,确认和你使用的访问类型匹配:
    std::cout << "Mat type code: " << data_mat.type() << std::endl;
    // CV_32F对应5,CV_64F对应6
    
  2. 高效批量赋值:你的数据量很大(5万多行),嵌套循环赋值效率偏低,可以用memcpy直接拷贝数据:
    比如CV_64F的情况:
    cv::Mat data_mat(all_data.size(), all_data[0].size(), CV_64F);
    for (int i = 0; i < all_data.size(); ++i) {
        memcpy(data_mat.ptr<double>(i), all_data[i].data(), all_data[i].size() * sizeof(double));
    }
    
  3. 异常捕获:给kmeans加异常捕获,方便后续定位问题:
    try {
        cv::kmeans(data_mat, k, labels, criteria, attempts, cv::KMEANS_PP_CENTERS, centers);
        std::cout << "Finished k-means" << std::endl;
        std::cout << "Centers rows: " << centers.rows << std::endl;
        std::cout << "Centers cols: " << centers.cols << std::endl;
    } catch (const cv::Exception& e) {
        std::cerr << "Kmeans error: " << e.what() << std::endl;
    }
    

按照上面的步骤修复后,kmeans应该能正常运行,centers也会生成你预期的256×256矩阵啦!

内容的提问来源于stack exchange,提问作者Timo Nörnberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:39:17