kmeans in Android (Java)-

asked 2019-08-16 08:10:41 -0500

LiorA gravatar image

updated 2019-08-16 09:01:48 -0500


I've tried to use kmeans function, but something is not clear to me.

Lets say that I have an array of points and I want to center all of them to four points :

topLeft, topRight, bottomeft, bottomRight.

How I can achieve it ? I tried to make it work, but failed to understand (for now)..

also, It's very hard to understand what is happening on the Mat's.. No option to print/see the actual Mat on some console / or in deug mode ?

Thank's !!

the code:

public void colorMask(View view)
    //Image Input :
    Bitmap one =
            drawableToBitmap(getResources().getDrawable(R.drawable.dsc_1304_cutted_bigger, this.getTheme()));
    Mat img1 = new Mat();
    Utils.bitmapToMat(one, img1, true);// moving one to img1 Mat structure.

    // downsize the image.
    Mat pyrDowntmp = new Mat();
    Imgproc.resize(img1, pyrDowntmp, new Size(img1.cols() / 4, img1.rows() / 4));

    Mat pyrDown = new Mat();
    cvtColor(pyrDowntmp, pyrDown, COLOR_RGBA2RGB);

    List<Point> intersections1 = new ArrayList<>();

    org.opencv.core.Point pointsArray[] = new org.opencv.core.Point[ intersections1.size() ];

    Mat intersections = new Mat();
    Mat intersections32f = new Mat();

    // draw all the intersections. (see it ok)
    for (Point point: pointsArray)
        // draw on the actual image:
        circle(pyrDown, point, 5, new Scalar(255, 0, 0), 2);//Red

        // want to draw it on a Mat that will be given to kmeans as data mat.

        // tried to draw on a mat:
        circle(intersections, point, 5, new Scalar(255, 0, 0), 2);

        // tried to 'put' on 32f Mat.
        //(the first two parameters - issue an error.('need double')
        intersections32f.put(point.x, point.y, 1.0);

    intersections.convertTo(intersections32f, CvType.CV_32F);

    // want to find the 4 corners of the points..
    Mat labels = Mat.zeros(intersections32f.rows(), intersections32f.cols(), CvType.CV_32F);

    labels.put(0, 0, 1.0); // topLeft

    labels.put(0, labels.rows() - 1, 1); // bottomLeft

    labels.put(labels.cols() - 1, 0, 1); // topRight

    labels.put(labels.rows() - 1, labels.cols() - 1, 1); // bottomRight

    TermCriteria criteria = new TermCriteria(TermCriteria.COUNT, 100, 1);
    int attempts = 50;
    int flags = Core.KMEANS_PP_CENTERS;
    Mat centers = new Mat();
    double res = kmeans(intersections32f, 4, labels, criteria, attempts, flags, centers);

    Bitmap imageMatched = Bitmap.createBitmap(centers.cols(), centers.rows(), Bitmap.Config.RGB_565);
    Utils.matToBitmap(centers, imageMatched);

    public static double kmeans(@NotNull Mat data,
    int K,
    @NotNull Mat bestLabels,
    @NotNull TermCriteria criteria,
    int attempts,
    int flags)

edit retag flag offensive close merge delete


i don't think it's possible to preselect centers here, only labels (meaning, one per pixel)

berak gravatar imageberak ( 2019-08-16 08:40:52 -0500 )edit

Kmeans is a clustering algorithm. This means it will try to for groups of datapoints related to each other. Its does this by measuring a distance.

How it works(very simplified):
Define n clusters and give them a random position 

Repeat for each cluster until a cluster is empty or all points have been assigned
1) Check which points are closest to the center of the cluster
2) Assign the points from 1) to the cluster
3) Computer the average over all points and that the new center

So i dont think this algorithm will solve your problem "I want to center all of them to four points" because the cluster center will be moved constantly and maybe ends up in a position which is out of your bounding box.

You could try running with 1 cluster and a min distance anways.
holger gravatar imageholger ( 2019-08-16 09:24:12 -0500 )edit

@berak , yes, you are correct, but I'm not fully understood the label's role in the algorithm.

data/samples - the points in the grid.

K - the number of wanted clusters.

label - ...

Criteria - the base condition.

attempts - the number of times which the algorithm is executed using different initial labellings.

flags - behavioral flags.

centers - output of K points.

what is the labels ? Is it for 'color' different points ?.

LiorA gravatar imageLiorA ( 2019-08-16 13:41:08 -0500 )edit


If I define K=4 , and most points are in clusters - the center of each cluster is what I want..

I need something like this :

If I have the following :

And I want to get the center of each cluster, kmeans is not for it ?

LiorA gravatar imageLiorA ( 2019-08-16 13:54:24 -0500 )edit

No - each cluster has a center - the so called centroid. Which is just the average of all points. The role of the labels - i am at home so i cannot look it up - i think the labels just tells you to which cluster a point belongs to.

holger gravatar imageholger ( 2019-08-17 15:08:56 -0500 )edit

So this is exactly what I looking for...

LiorA gravatar imageLiorA ( 2019-08-31 11:11:07 -0500 )edit