如何设置 K-means openCV c++ 的初始中心
how to set initial centers of K-means openCV c++
我正在尝试使用 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" 来完成,但我不太确定如何使用它,以及我应该如何以及在何处设置初始值。
谢谢。
该函数允许您直接设置初始 labeling,而不是 centers。还好,既然k-means alternates between assignment and update steps,就可以间接得到自己想要的效果
来自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.
所以,文档说的是您可以设置初始 标签。如果你想这样做,在你的代码中
kmeans(samples, 2, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_USE_INITIAL_LABELS, centers);
将第三个参数初始化为输入标签(用于第一次迭代)。
如果你想得到设置初始中心的效果,可以这样做:
确定中心是什么。
像 the assignment step 中的算法一样计算标签。
将生成的标签传递给函数。
我正在尝试使用 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" 来完成,但我不太确定如何使用它,以及我应该如何以及在何处设置初始值。 谢谢。
该函数允许您直接设置初始 labeling,而不是 centers。还好,既然k-means alternates between assignment and update steps,就可以间接得到自己想要的效果
来自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.
所以,文档说的是您可以设置初始 标签。如果你想这样做,在你的代码中
kmeans(samples, 2, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_USE_INITIAL_LABELS, centers);
将第三个参数初始化为输入标签(用于第一次迭代)。
如果你想得到设置初始中心的效果,可以这样做:
确定中心是什么。
像 the assignment step 中的算法一样计算标签。
将生成的标签传递给函数。