对来自 csv 文件的数据执行 OpenCV k-means
Performing OpenCV k-means on data from csv-file
我正在尝试从 csv 文件中读取时间序列。
每行包含 256 个(将来可能会有所不同)我想作为 256 维中的一个点处理的元素 space.
然后我想对其执行 k 均值聚类以找到描述数据的最重要的 k 个时间序列。
我目前正在读取 csv 文件,将每一行存储在
std::vector<double> temprow
然后得到一个
std::vector<std::vector<double>> data_vect
然后我将转换为
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<double>(rows, cols) = all_data[rows][cols];
}
}
return data_mat;
这让我得到具有以下属性的 cv::Mat:
std::cout << "Rows: " << data.rows << std::endl; //Rows: 52178
std::cout << "Cols: " << data.cols << std::endl; //Cols: 256
std::cout << "Dims: " << data.dims << std::endl; //Dims: 2
然后我按如下方式执行 k 均值聚类:
cv::Mat labels,centers;
int k = 256;
int attempts = 10;
cv::TermCriteria criteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 1.0);
cv::kmeans(data_mat, k, labels, criteria, attempts, cv::KMEANS_PP_CENTERS, centers);
根据我的理解,应该用每个簇的中心值填充 centers,留下 k*n 矩阵(在本例中为 256*256)。
然而,当我打电话时
std::cout << "Rows: " << centers.rows << std::endl; //Hopefully 256
std::cout << "Cols: " << centers.cols << std::endl; //Hopefully 256
我收到这条一般性错误消息:
Exception thrown at 0x00007FF806C86020 (opencv_world341.dll) in Project1.exe: 0xC0000005: Access violation reading location 0x0000024B9ECAFC80.
程序此时centers的属性是:
flags 1124007936 int
dims 0 int
rows 0 int
cols 0 int
+ data 0x0000000000000000 <NULL> unsigned char *
+ datastart 0x0000000000000000 <NULL> const unsigned char *
+ dataend 0x0000000000000000 <NULL> const unsigned char *
+ datalimit 0x0000000000000000 <NULL> const unsigned char *
+ allocator 0x0000000000000000 <NULL> cv::MatAllocator *
+ u 0x0000000000000000 <NULL> cv::UMatData *
+ size {p=0x000000bdfc93f9e8 {0} } cv::MatSize
+ step {p=0x000000bdfc93fa30 {0} buf=0x000000bdfc93fa30 {0, 0} } cv::MatStep
所以中心似乎是 NULL。所以也许输入 data_mat 的形状不对,所以 kmeans() 没有输出任何东西到中心,但又一次我没有收到 kmeans()
的任何错误消息
非常感谢您的努力和帮助,
蒂莫
编辑 1:错误发生在 kmeans() 内部,因为
cv::kmeans(data_mat, k, labels, criteria, attempts, cv::KMEANS_PP_CENTERS, centers);
std::cout << "Finished k-means" << std::endl;
cout 未打印到控制台。然而,错误的行号是 kmeans()+1,所以我只是通过在那里放置一个通用 cout 来发现它。
所以我找到了答案:
因为我正在使用 Type CV32_F 我必须将其作为 float Mat.
访问
如此变化data_mat.at<double>(rows, cols) = all_data[rows][cols];
data_mat.at<float>(rows, cols) = all_data[rows][cols];
为我完成了工作。
最初我想使用 CV64_F,所以我到处都是 double,但我发现,OpenCV-k-means 只能工作到CV32_F。然后我也忘了更改它,这导致执行了第一个聚类步骤,但在第二个步骤之后它崩溃了。
我正在尝试从 csv 文件中读取时间序列。
每行包含 256 个(将来可能会有所不同)我想作为 256 维中的一个点处理的元素 space.
然后我想对其执行 k 均值聚类以找到描述数据的最重要的 k 个时间序列。
我目前正在读取 csv 文件,将每一行存储在
std::vector<double> temprow
然后得到一个
std::vector<std::vector<double>> data_vect
然后我将转换为
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<double>(rows, cols) = all_data[rows][cols];
}
}
return data_mat;
这让我得到具有以下属性的 cv::Mat:
std::cout << "Rows: " << data.rows << std::endl; //Rows: 52178
std::cout << "Cols: " << data.cols << std::endl; //Cols: 256
std::cout << "Dims: " << data.dims << std::endl; //Dims: 2
然后我按如下方式执行 k 均值聚类:
cv::Mat labels,centers;
int k = 256;
int attempts = 10;
cv::TermCriteria criteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 1.0);
cv::kmeans(data_mat, k, labels, criteria, attempts, cv::KMEANS_PP_CENTERS, centers);
根据我的理解,应该用每个簇的中心值填充 centers,留下 k*n 矩阵(在本例中为 256*256)。
然而,当我打电话时
std::cout << "Rows: " << centers.rows << std::endl; //Hopefully 256
std::cout << "Cols: " << centers.cols << std::endl; //Hopefully 256
我收到这条一般性错误消息:
Exception thrown at 0x00007FF806C86020 (opencv_world341.dll) in Project1.exe: 0xC0000005: Access violation reading location 0x0000024B9ECAFC80.
程序此时centers的属性是:
flags 1124007936 int
dims 0 int
rows 0 int
cols 0 int
+ data 0x0000000000000000 <NULL> unsigned char *
+ datastart 0x0000000000000000 <NULL> const unsigned char *
+ dataend 0x0000000000000000 <NULL> const unsigned char *
+ datalimit 0x0000000000000000 <NULL> const unsigned char *
+ allocator 0x0000000000000000 <NULL> cv::MatAllocator *
+ u 0x0000000000000000 <NULL> cv::UMatData *
+ size {p=0x000000bdfc93f9e8 {0} } cv::MatSize
+ step {p=0x000000bdfc93fa30 {0} buf=0x000000bdfc93fa30 {0, 0} } cv::MatStep
所以中心似乎是 NULL。所以也许输入 data_mat 的形状不对,所以 kmeans() 没有输出任何东西到中心,但又一次我没有收到 kmeans()
的任何错误消息非常感谢您的努力和帮助,
蒂莫
编辑 1:错误发生在 kmeans() 内部,因为
cv::kmeans(data_mat, k, labels, criteria, attempts, cv::KMEANS_PP_CENTERS, centers);
std::cout << "Finished k-means" << std::endl;
cout 未打印到控制台。然而,错误的行号是 kmeans()+1,所以我只是通过在那里放置一个通用 cout 来发现它。
所以我找到了答案:
因为我正在使用 Type CV32_F 我必须将其作为 float Mat.
访问如此变化data_mat.at<double>(rows, cols) = all_data[rows][cols];
data_mat.at<float>(rows, cols) = all_data[rows][cols];
为我完成了工作。
最初我想使用 CV64_F,所以我到处都是 double,但我发现,OpenCV-k-means 只能工作到CV32_F。然后我也忘了更改它,这导致执行了第一个聚类步骤,但在第二个步骤之后它崩溃了。