1

I want to implement K-means clustering for segmenting an image based on color intensity and actually i do not know how to get the segmented image and ROI after applying Core.kmeans function. I followed the steps in the question in here here but there is no answer to how to proceed from this point. Any help would be appreciated.

Thanks in advance.

This the code I am using based on different sources and actually it is not working

 //convert to lab with three channels
            Mat imgLab = new Mat();
            Mat imgMat = new Mat();
            Imgproc.cvtColor(imgMat, imgLab, Imgproc.COLOR_RGB2Lab, 3);

            // separate channels
            List<Mat> lab_planes = new ArrayList<Mat>(3);
            Core.split(imgMat, lab_planes);
            Mat channel = lab_planes.get(2);
            channel = Mat.zeros(imgLab.rows(), imgLab.cols(), CvType.CV_8UC1);

            // use only AB channels in Lab color space
            lab_planes.set(2, channel);
            Core.merge(lab_planes,imgLab);

            Mat samples = imgLab.reshape(1, imgLab.cols() * imgLab.rows());
            Mat samples32f = new Mat();
            samples.convertTo(samples32f, CvType.CV_32F, 1.0 / 255.0);
            Mat labels = new Mat();
            TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 100, 1);
            Mat centers = new Mat();
            //Mat clusteredLab = new Mat();

            int nColors = 3; //number of clusters (k)
            int attempt = 3; //number of attempts

            // repeat the clustering 3 times to avoid local minima
            Core.kmeans(samples32f, nColors, labels, criteria, attempt, Core.KMEANS_PP_CENTERS, centers);

            centers.convertTo(centers, CvType.CV_8UC1);
            centers.reshape(3);

            //the rest of code for RGB image not Lab

            List<Mat> clusters = new ArrayList<Mat>();
            for (int i = 0; i < centers.rows(); i++) {
                clusters.add(Mat.zeros(samples.size(), samples.type()));
            }

            Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
            for (int i = 0; i < centers.rows(); i++) counts.put(i, 0);

            int rows = 0;
            for (int y = 0; y < samples.rows(); y++) {
                for (int x = 0; x < samples.cols(); x++) {
                    int label = (int) labels.get(rows, 0)[0];
                    int r = (int) centers.get(label, 2)[0];
                    int g = (int) centers.get(label, 1)[0];
                    int b = (int) centers.get(label, 0)[0];
                    counts.put(label, counts.get(label) + 1);
                    clusters.get(label).put(y, x, b, g, r);
                    rows++;
                }
            }
            return clusters;

        }
Nani
  • 97
  • 13
  • 2
    The [second snippet here](https://stackoverflow.com/a/34734939/5008845) should get you started (although in C++). If you need further help, please post the code you're using, the errors you get, where you got stuck, etc... – Miki Jun 06 '17 at 10:07
  • It should return the labels of each pixel/point, so you need to find the min and max in X and Y and with that you will have a square that is the ROI you are looking for. To segment the image base on the kmeans result, just color the pixel with the same label with the same color and change the color for each label, you can also put the pixel positions (AKA 2d points) in a array for further analysis. – api55 Jun 06 '17 at 12:14
  • Many thanks for your answer. Can you please post some code to help me understand the whole picture. – Nani Jun 06 '17 at 12:41

0 Answers0