2016-10-01 11 views
1

Я пытаюсь сделать сегментацию изображения с помощью OpenCV и Kmeans, код, который я только реализован следующий:как установить начальные центры Kmeans OpenCV C++

#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(); 
} 

Она работает довольно ну и он делает то, что я хочу, но я хотел бы установить свои собственные значения начальных центров. Я прочитал, что это можно сделать, используя флаг «KMEANS_USE_INITIAL_LABELS», но я не очень уверен в том, как его использовать, и как и где я должен устанавливать начальные значения. спасибо.

ответ

3

Функция позволяет непосредственно установить начальную маркировку, а не центры. К счастью, с k-means alternates between assignment and update steps вы можете получить эффект, который хотите косвенно.


От the docs:

этикетки - вход/выход целочисленный массив, который хранит кластерные индексы для каждого образца.

KMEANS_USE_INITIAL_LABELS Во время первой (и, возможно, единственной) попытки используйте присваиваемые пользователем метки вместо их вычисления из исходных центров. Для второй и дальнейших попыток используйте случайные или полуслучайные центры. Используйте один из значков KMEANS _ * _ CENTERS, чтобы указать точный метод.

Итак, что говорят документы, что вы можете установить начальную маркировку. Если вы хотите сделать это в вашем коде

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

инициализировать 3-й параметр, который ввод меток (для использования в первой итерации).


Если вы хотите, чтобы получить эффект от установки начальных центров, вы можете сделать следующее:

  1. Решите, какие центры.

  2. Рассчитать маркировку, как это делает алгоритм в the assignment step.

  3. Передайте полученную маркировку функции.

+0

Спасибо! это было очень полезно –

+0

Добро пожаловать. Всего наилучшего. –