kmeans in Android (Java)-
Hi,
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));
img1.release();
Mat pyrDown = new Mat();
cvtColor(pyrDowntmp, pyrDown, COLOR_RGBA2RGB);
pyrDowntmp.release();
List<Point> intersections1 = new ArrayList<>();
org.opencv.core.Point pointsArray[] = new org.opencv.core.Point[ intersections1.size() ];
intersections1.toArray(pointsArray);
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);
imageViewMy.setImageBitmap(imageMatched);
/*
public static double kmeans(@NotNull Mat data,
int K,
@NotNull Mat bestLabels,
@NotNull TermCriteria criteria,
int attempts,
int flags)
*/
}
i don't think it's possible to preselect centers here, only labels (meaning, one per pixel)
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.
@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 ?.
@holger
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 : https://docs.opencv.org/3.0-beta/doc/...
If I have the following : https://imgur.com/a/EHECQqS
And I want to get the center of each cluster, kmeans is not for it ?
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.