Merge pull request #2744 from jet47:kmeans-fix

pull/2738/merge
Vadim Pisarevsky 11 years ago committed by OpenCV Buildbot
commit 118b27f5b4
  1. 14
      modules/core/src/matrix.cpp
  2. 79
      modules/core/test/test_math.cpp
  3. 2
      samples/cpp/kmeans.cpp

@ -2691,16 +2691,18 @@ double cv::kmeans( InputArray _data, int K,
int flags, OutputArray _centers ) int flags, OutputArray _centers )
{ {
const int SPP_TRIALS = 3; const int SPP_TRIALS = 3;
Mat data = _data.getMat(); Mat data0 = _data.getMat();
bool isrow = data.rows == 1 && data.channels() > 1; bool isrow = data0.rows == 1 && data0.channels() > 1;
int N = !isrow ? data.rows : data.cols; int N = !isrow ? data0.rows : data0.cols;
int dims = (!isrow ? data.cols : 1)*data.channels(); int dims = (!isrow ? data0.cols : 1)*data0.channels();
int type = data.depth(); int type = data0.depth();
attempts = std::max(attempts, 1); attempts = std::max(attempts, 1);
CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 ); CV_Assert( data0.dims <= 2 && type == CV_32F && K > 0 );
CV_Assert( N >= K ); CV_Assert( N >= K );
Mat data(N, dims, CV_32F, data0.data, isrow ? dims * sizeof(float) : static_cast<size_t>(data0.step));
_bestLabels.create(N, 1, CV_32S, -1, true); _bestLabels.create(N, 1, CV_32S, -1, true);
Mat _labels, best_labels = _bestLabels.getMat(); Mat _labels, best_labels = _bestLabels.getMat();

@ -2512,6 +2512,15 @@ TEST(Core_SVD, flt)
// TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)), // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),
enum
{
MAT_N_DIM_C1,
MAT_N_1_CDIM,
MAT_1_N_CDIM,
MAT_N_DIM_C1_NONCONT,
MAT_N_1_CDIM_NONCONT,
VECTOR
};
class CV_KMeansSingularTest : public cvtest::BaseTest class CV_KMeansSingularTest : public cvtest::BaseTest
{ {
@ -2519,7 +2528,7 @@ public:
CV_KMeansSingularTest() {} CV_KMeansSingularTest() {}
~CV_KMeansSingularTest() {} ~CV_KMeansSingularTest() {}
protected: protected:
void run(int) void run(int inVariant)
{ {
int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0; int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0;
Mat labels; Mat labels;
@ -2531,20 +2540,70 @@ protected:
for( iter = 0; iter < maxIter; iter++ ) for( iter = 0; iter < maxIter; iter++ )
{ {
ts->update_context(this, iter, true); ts->update_context(this, iter, true);
dims = rng.uniform(1, MAX_DIM+1); dims = rng.uniform(inVariant == MAT_1_N_CDIM ? 2 : 1, MAX_DIM+1);
N = rng.uniform(1, MAX_POINTS+1); N = rng.uniform(1, MAX_POINTS+1);
N0 = rng.uniform(1, MAX(N/10, 2)); N0 = rng.uniform(1, MAX(N/10, 2));
K = rng.uniform(1, N+1); K = rng.uniform(1, N+1);
if (inVariant == VECTOR)
{
dims = 2;
std::vector<cv::Point2f> data0(N0);
rng.fill(data0, RNG::UNIFORM, -1, 1);
std::vector<cv::Point2f> data(N);
for( i = 0; i < N; i++ )
data[i] = data0[rng.uniform(0, N0)];
kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
5, KMEANS_PP_CENTERS);
}
else
{
Mat data0(N0, dims, CV_32F); Mat data0(N0, dims, CV_32F);
rng.fill(data0, RNG::UNIFORM, -1, 1); rng.fill(data0, RNG::UNIFORM, -1, 1);
Mat data(N, dims, CV_32F); Mat data;
switch (inVariant)
{
case MAT_N_DIM_C1:
data.create(N, dims, CV_32F);
for( i = 0; i < N; i++ )
data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
break;
case MAT_N_1_CDIM:
data.create(N, 1, CV_32FC(dims));
for( i = 0; i < N; i++ )
memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
break;
case MAT_1_N_CDIM:
data.create(1, N, CV_32FC(dims));
for( i = 0; i < N; i++ )
memcpy(data.data + i * dims * sizeof(float), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
break;
case MAT_N_DIM_C1_NONCONT:
data.create(N, dims + 5, CV_32F);
data = data(Range(0, N), Range(0, dims));
for( i = 0; i < N; i++ ) for( i = 0; i < N; i++ )
data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
break;
case MAT_N_1_CDIM_NONCONT:
data.create(N, 3, CV_32FC(dims));
data = data.colRange(0, 1);
for( i = 0; i < N; i++ )
memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
break;
}
kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
5, KMEANS_PP_CENTERS); 5, KMEANS_PP_CENTERS);
}
Mat hist(K, 1, CV_32S, Scalar(0)); Mat hist(K, 1, CV_32S, Scalar(0));
for( i = 0; i < N; i++ ) for( i = 0; i < N; i++ )
@ -2568,7 +2627,19 @@ protected:
} }
}; };
TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(); } TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); }
CV_ENUM(KMeansInputVariant, MAT_N_DIM_C1, MAT_N_1_CDIM, MAT_1_N_CDIM, MAT_N_DIM_C1_NONCONT, MAT_N_1_CDIM_NONCONT, VECTOR)
typedef testing::TestWithParam<KMeansInputVariant> Core_KMeans_InputVariants;
TEST_P(Core_KMeans_InputVariants, singular)
{
CV_KMeansSingularTest test;
test.safe_run(GetParam());
}
INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all());
TEST(CovariationMatrixVectorOfMat, accuracy) TEST(CovariationMatrixVectorOfMat, accuracy)
{ {

@ -33,7 +33,7 @@ int main( int /*argc*/, char** /*argv*/ )
{ {
int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1); int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1);
int i, sampleCount = rng.uniform(1, 1001); int i, sampleCount = rng.uniform(1, 1001);
Mat points(sampleCount, 2, CV_32F), labels; Mat points(sampleCount, 1, CV_32FC2), labels;
clusterCount = MIN(clusterCount, sampleCount); clusterCount = MIN(clusterCount, sampleCount);
Mat centers; Mat centers;

Loading…
Cancel
Save