how to set initial centers of K-means openCV c++

你。 提交于 2019-12-22 13:47:29

问题


I am trying to do a segmentation of an image using OpenCv and Kmeans, the code that I have just implemented is the following:

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

int main(int, char** argv)
{
    Mat src, Imagen2, Imagris, labels, centers,imgfondo;
    src = imread("C:/Users/Sebastian/Documents/Visual Studio 2015/Projects/ClusteringImage/data/leon.jpg");
    imgfondo = imread("C:/Users/Sebastian/Documents/Visual Studio 2015/Projects/ClusteringImage/data/goku640.jpg");
    if (src.empty()|| imgfondo.empty())
    {
        printf("Error al cargar imagenes");
        waitKey();
        return -1;
    }
    Mat samples(src.rows * src.cols, 3, CV_32F);
    for (int y = 0; y < src.rows; y++)
        for (int x = 0; x < src.cols; x++)
            for (int z = 0; z < 3; z++)
                samples.at<float>(y + x*src.rows, z) = src.at<Vec3b>(y, x)[z];
    //KMEANS_USE_INITIAL_LABELS
    kmeans(samples, 2, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_USE_INITIAL_LABELS, centers);
    Mat new_image(src.size(), src.type());
    int cluster;
    if (centers.at<float>(0, 1) > centers.at<float>(1, 1))  cluster = 0;
    else        cluster = 1;
    for (int y = 0; y < src.rows; y++)
        for (int x = 0; x < src.cols; x++)
        {
            int cluster_idx = labels.at<int>(y + x*src.rows, 0);
            if (cluster_idx == cluster)
            {
                new_image.at<Vec3b>(y, x)[0] = imgfondo.at<Vec3b>(y, x)[0];
                new_image.at<Vec3b>(y, x)[1] = imgfondo.at<Vec3b>(y, x)[1];
                new_image.at<Vec3b>(y, x)[2] = imgfondo.at<Vec3b>(y, x)[2];
            }
            else
            {
                new_image.at<Vec3b>(y, x)[0] = src.at<Vec3b>(y, x)[0];
                new_image.at<Vec3b>(y, x)[1] = src.at<Vec3b>(y, x)[1];
                new_image.at<Vec3b>(y, x)[2] = src.at<Vec3b>(y, x)[2];
            }
        }
    imshow("Original image", src);
    imshow("clustered image", new_image);
    waitKey();
}

It works pretty well and it does what i want, but i would like to set my own initial centers values. I have read that it could be done using the flag "KMEANS_USE_INITIAL_LABELS" but im not very sure about how to use it, and how and where should I set the initial values. thanks.


回答1:


The function allows you to directly set the initial labeling, not centers. Fortunately, since k-means alternates between assignment and update steps, you can get the effect you want indirectly.


From the docs:

labels – Input/output integer array that stores the cluster indices for every sample.

KMEANS_USE_INITIAL_LABELS During the first (and possibly the only) attempt, use the user-supplied labels instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random centers. Use one of KMEANS_*_CENTERS flag to specify the exact method.

So, what the docs say is that you can set the initial labeling. If you want to do this, in your code

kmeans(samples, 2, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_USE_INITIAL_LABELS, centers);

initialize the 3rd parameter to be the input labels (for use in the first iteration).


If you want to get the effect of setting the initial centers, you can do the following:

  1. Decide what the centers are.

  2. Calculate the labeling like the algorithm does in the assignment step.

  3. Pass the resulting labeling to the function.



来源:https://stackoverflow.com/questions/39803033/how-to-set-initial-centers-of-k-means-opencv-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!