алгоритм — как установить начальные центры K-средних openCV Stack Overflow

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

#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», но я не очень уверен, как его использовать, как и где я должен установить начальные значения.
Благодарю.

2

Решение

Функция позволяет напрямую установить начальную маркировка, не центры. К счастью, так как k-означает чередование между этапами назначения и обновления, Вы можете получить желаемый эффект косвенно.


От документы:

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

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. Рассчитайте маркировку как алгоритм в шаг назначения.

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

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]