如何设置K-means openCV c ++的初始中心

Posted

技术标签:

【中文标题】如何设置K-means openCV c ++的初始中心【英文标题】:how to set initial centers of K-means openCV c++ 【发布时间】:2017-02-09 17:04:36 【问题描述】:

我正在尝试使用 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”来完成,但我不太确定如何使用它,以及我应该如何以及在哪里设置初始值。 谢谢。

【问题讨论】:

【参考方案1】:

该功能允许您直接设置初始标签,而不是中心。幸运的是,自从k-means alternates between assignment and update steps,你可以间接得到你想要的效果。


来自the docs:

labels – 输入/输出整数数组,用于存储每个样本的集群索引。

KMEANS_USE_INITIAL_LABELS 在第一次(也可能是唯一一次)尝试中,使用用户提供的标签,而不是从初始中心计算它们。对于第二次和进一步的尝试,使用随机或半随机中心。使用 KMEANS_*_CENTERS 标志之一来指定确切的方法。

所以,文档说的是您可以设置初始标签。如果你想这样做,在你的代码中

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

将第三个参数初始化为输入标签(用于第一次迭代)。


如果想得到设置初始中心的效果,可以这样做:

    确定中心是什么。

    像the assignment step 中的算法一样计算标签。

    将生成的标签传递给函数。

【讨论】:

既然您已经设置了attempts = 3; flags = KMEANS_USE_INITIAL_LABELS,接下来的 2 次尝试将使用哪种算法?如何确保在第一次尝试后使用KMEANS_PP_CENTERS?谢谢

以上是关于如何设置K-means openCV c ++的初始中心的主要内容,如果未能解决你的问题,请参考以下文章

Problem C: 类的初体验(III)

数据结构c语言版 使用线性表的顺序储存结构定义(静态)实现线性表的初

一FFmpeg 的初尝试《FFmpeg 音视频开发基础入门到实战》

一FFmpeg 的初尝试《FFmpeg 音视频开发基础入门到实战》

一FFmpeg 的初尝试《FFmpeg 音视频开发基础入门到实战》

一FFmpeg 的初尝试《FFmpeg 音视频开发基础入门到实战》