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>
这里写图片描述

运用K-means算法进行图像分割, K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。 k个初始类聚类中心点的选取对聚类结果具有较大的 公式 公式 影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。 算法过程如下: 1)从N个文档随机选取K个文档作为质心 2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类 3)重新计算已经得到的各个类的质心 4)迭代2~3步直至新的质心与原质心相等或小于指定阈值,算法结束 具体如下: 输入:k, data[n]; (1) 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1]; (2) 对于data[0]….data[n],分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i; (3) 对于所有标记为i点,重新计算c[i]={ 所有标记为i的data[j]之和}/标记为i的个数; (4) 重复(2)(3),直到所有c[i]值的变化小于给定阈值。 折叠工作原理 K-MEANS算法的工作原理及流程 K-MEANS算法 输入:聚类个数k,以及包含 n个数据对象的数据库。 输出:满足方差最小标准的k个聚类。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值