opencv
assertion_error
ai_generated
true
cv::error: (-215:Assertion failed) centers.cols == data.cols in function 'cv::kmeans'
ID: opencv/kmeans-initial-centers-mismatch
88%Fix Rate
84%Confidence
1Evidence
2023-03-10First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| opencv-4.5.5 | active | — | — | — |
| opencv-4.8.0 | active | — | — | — |
| opencv-4.9.0 | active | — | — | — |
Root Cause
When providing initial cluster centers to kmeans, the number of columns (features) in the centers matrix does not match the number of columns in the data matrix.
generic中文
当向 kmeans 提供初始聚类中心时,中心矩阵的列数(特征数)与数据矩阵的列数不匹配。
Official Documentation
https://docs.opencv.org/4.x/d5/d38/group__core__cluster.htmlWorkarounds
-
90% success Ensure the centers matrix has the same number of columns as the data matrix. For example, if data is a 100x3 matrix (100 samples, 3 features), centers should be Kx3. Initialize centers as: cv::Mat centers(K, data.cols, CV_32FC1); for (int i = 0; i < K; i++) { data.row(rand() % data.rows).copyTo(centers.row(i)); } Then call kmeans(data, K, labels, criteria, attempts, KMEANS_USE_INITIAL_LABELS, centers);
Ensure the centers matrix has the same number of columns as the data matrix. For example, if data is a 100x3 matrix (100 samples, 3 features), centers should be Kx3. Initialize centers as: cv::Mat centers(K, data.cols, CV_32FC1); for (int i = 0; i < K; i++) { data.row(rand() % data.rows).copyTo(centers.row(i)); } Then call kmeans(data, K, labels, criteria, attempts, KMEANS_USE_INITIAL_LABELS, centers); -
80% success Convert data to CV_32F type if it is CV_64F: data.convertTo(data, CV_32F); and ensure centers is also CV_32F.
Convert data to CV_32F type if it is CV_64F: data.convertTo(data, CV_32F); and ensure centers is also CV_32F.
-
95% success Use KMEANS_RANDOM_CENTERS flag instead of providing initial centers: kmeans(data, K, labels, criteria, attempts, KMEANS_RANDOM_CENTERS);
Use KMEANS_RANDOM_CENTERS flag instead of providing initial centers: kmeans(data, K, labels, criteria, attempts, KMEANS_RANDOM_CENTERS);
中文步骤
Ensure the centers matrix has the same number of columns as the data matrix. For example, if data is a 100x3 matrix (100 samples, 3 features), centers should be Kx3. Initialize centers as: cv::Mat centers(K, data.cols, CV_32FC1); for (int i = 0; i < K; i++) { data.row(rand() % data.rows).copyTo(centers.row(i)); } Then call kmeans(data, K, labels, criteria, attempts, KMEANS_USE_INITIAL_LABELS, centers);Convert data to CV_32F type if it is CV_64F: data.convertTo(data, CV_32F); and ensure centers is also CV_32F.
Use KMEANS_RANDOM_CENTERS flag instead of providing initial centers: kmeans(data, K, labels, criteria, attempts, KMEANS_RANDOM_CENTERS);
Dead Ends
Common approaches that don't work:
-
Transpose the data matrix using data.t()
85% fail
kmeans expects data as rows of samples (each row is a sample). Transposing changes the shape incorrectly, leading to centers.cols != data.cols in a different way.
-
Set the number of clusters K to a smaller value
95% fail
The error is about feature dimension mismatch, not the number of clusters. Changing K doesn't affect the column count.
-
Use cv::Mat::reshape to flatten the data to 1 column
90% fail
Flattening to 1 column changes the feature space entirely, causing centers.cols (still original features) to mismatch.