OpenCV4Android Kmean doesn't work as expected

2020-06-29 01:42发布

问题:

This code should give centers mat with 3 rows and clusterCount number of columns

    Mat reshaped_image = imageMat.reshape(1, imageMat.cols()*imageMat.rows());
    Mat reshaped_image32f = new Mat();
    reshaped_image.convertTo(reshaped_image32f, CvType.CV_32F, 1.0 / 255.0);

    Mat labels = new Mat();
    TermCriteria criteria = new TermCriteria(TermCriteria.COUNT, 100, 1);
    Mat centers = new Mat();
    int clusterCount = 5, attempts = 1;
    Core.kmeans(reshaped_image32f, clusterCount, labels, criteria, attempts, Core.KMEANS_PP_CENTERS, centers);

I tried same code in C and got centers Mat with 3 rows and clusterCount number of columns.

But in java the Core.kmeans returning 4 columns and cluster number of rows.

centers.reshape(3);

so now the reshape function doesn't work on centers since the number of rows are depended on cluster size. In C the number of rows are always constant i.e 3.

so in java it gives error

the number of rows of the matrix cannot be divided by new number of rows

Can someone figure out what is the problem. I even tried this which is similar to my code and got same error.

Reference C code :

    cv::Mat reshaped_image = image.reshape(1, image.cols * image.rows);
    cv::Mat reshaped_image32f;
    reshaped_image.convertTo(reshaped_image32f, CV_32FC1, 1.0 / 255.0);

    cv::Mat labels;
    int cluster_number = 5;
    cv::TermCriteria criteria(cv::TermCriteria::COUNT, 100, 1);
    cv::Mat centers;
    cv::kmeans(reshaped_image32f, cluster_number, labels, criteria, 1, cv::KMEANS_PP_CENTERS, centers);

回答1:

Finally it worked :-

I converted bitmap to Mat using bitmapToMat function which returns a RGBA image. so the centers has 4 columns instead of 3.

If you are converting bitmap to Mat and if you need BGR image then do this

    Mat imageMat = new Mat();
    Utils.bitmapToMat(bitmap, imageMat);

    Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_BGRA2BGR);

Cheers