Kmeans方法——图像分割

Kmeans算法是非常经典的聚类算法,在数据挖掘中kmeans经常用来做数据预处理,在图像处理中也可以用作图像的分割。opencv中提供了完整的kmeans算法,其函数原型为:
double kmeans( InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers = noArray() );

其中data表示用于聚类的数据,是N维的数组类型(Mat型),必须浮点型;

K表示需要聚类的类别数;

bestLabels聚类后的标签数组,Mat型;

criteria迭代收敛准则(MAX_ITER最大迭代次数,EPS最高精度);

attemps表示尝试的次数,防止陷入局部最优;

flags 表示聚类中心的选取方式(KMEANS_RANDOM_CENTERS 随机选取,KMEANS_PP_CENTERS使用Arthur提供的算法,KMEANS_USE_INITIAL_LABELS使用初始标签);

centers 表示聚类后的类别中心;

关于Kmeans的理论可以参考:Kmeans理论

下面是Kmeans示例:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat src = imread("E://testimage//image.png");
    namedWindow("input_image", WINDOW_AUTOSIZE);
    imshow("input_image", src);


    Scalar  colorTab[] = {
        Scalar(0,0,255),
        Scalar(0,255,0),
        Scalar(255,0,0),
        Scalar(255,0,255),
        Scalar(0,255,255),
        Scalar(255,255,0),
    };

    int width = src.cols;
    int height = src.rows;
    int dims = src.channels();

    int SampleCount = width*height;
    int clusterCount = 4;//簇群


    //RGB数组转换到样本数据
    Mat points(SampleCount, dims, CV_32F,Scalar(10));
    Mat lables;
    Mat centers(clusterCount, 1, points.type());

    int index = 0;
    for (int j = 0;j < height;j++)          
        {
            for (int i = 0;i < width;i++)
            {
                index = j* width+ i;
                Vec3b rgb = src.at<Vec3b>(j, i);
                points.at<float>(index, 0) = static_cast<int>(rgb[0]);
                points.at<float>(index, 1) = static_cast<int>(rgb[1]);
                points.at<float>(index, 2) = static_cast<int>(rgb[2]);
            }
        }
    //运行kmeans;
    kmeans(points, clusterCount, lables, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1), 3, KMEANS_PP_CENTERS, centers);


    //显示图像分割结果

    Mat result = Mat::zeros(src.size(), src.type());
    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < width;j++)
        {
            index = i*width + j;
            int lable = lables.at<int>(index, 0);
            result.at<Vec3b>(i, j)[0] = colorTab[lable][0];
            result.at<Vec3b>(i, j)[1] = colorTab[lable][1];
            result.at<Vec3b>(i, j)[2] = colorTab[lable][2];


        }

    }
    namedWindow("output_image", WINDOW_AUTOSIZE);
    imshow("output_image", result);



    waitKey(0);
    return 0;
}

效果图:
<code>这里写图片描述</code>
这里写图片描述

猜你喜欢

转载自blog.csdn.net/songjinxaing/article/details/82117263