基于K-means的彩色图像聚类之代码实现

K-means 用于聚类,原理很简单,就是将样本按照一定的“距离”,聚类成K个类,聚类过程是一个迭代的过程,即每次都重新计算类中样本的均值作为新的聚类中心。原理很简单,有很多博客写得比较详细,我这里就略过,在此只贴代码和结果。

#include"K-means.h"
/***************************************************************************************************
*function: cluster the rgb image using k-means method
*description:the distance is the sum of absolute difference of the Rgb color component
              that is, dis = abs(r0 -r1) + abs(g0 -g1) + abs(b0 -b1), and the initial cluster center
              is random;
*param:
*src                                    I               输入彩色图像
*dst                                    O               输出聚类结果
*width                                  I               图像的宽
*height                                 I               图像的高
*clusterNum                             I               聚类个数
*runTime                                I               迭代次数
*centerColor                            I               聚类颜色结构体
****************************************************************************************************/
void TongKmeans(u08 *src, u08 *dst, s32 width, s32 height, 
                s32 clusterNum, s32 runTime, clusterCenter *centerColor)
{
    s32 crossIdx = 0;
    clusterCenter center[100] = {0};
    s32 idx     = 0;
    RNG rng;
    // inition of the cluster center
    for (s32 k = 0; k < clusterNum; k++)
    {
        center[k].px = rng.uniform(0,width);
        center[k].py = rng.uniform(0,height);
        s32 idx = 3 * (center[k].py * width +center[k].px); 
        center[k].color[0] = src[idx];
        center[k].color[1] = src[idx + 1];
        center[k].color[2] = src[idx + 2];
    }

    // iteration of clustering
    for ( s32  n = 0; n < runTime; n++)
    {
       // the cluster num should smaller than 300
        s32 clusterSum[300][3] = {0};
        s32 numCount[300]      = {0};

        for (s32 i = 0; i < height; i++)
        {   
            crossIdx = 3 * i * width;

            for (s32 j = 0; j < width; j ++)
            {   
                s32 minDis   =   10000000;
                s32 clusterK = 0;

                for ( s32 k = 0; k < clusterNum; k++)
                {
                    s32 dis =  abs(src[crossIdx]     - center[k].color[0])
                            +  abs(src[crossIdx + 1] - center[k].color[1])
                            +  abs(src[crossIdx + 2] - center[k].color[2]);
                    if (dis < minDis)
                    {
                        clusterK = k;
                        minDis   = dis;
                    }
                }
                // color the pix with certain color
                dst[crossIdx]     = centerColor[clusterK].color[0];
                dst[crossIdx + 1] = centerColor[clusterK].color[1];
                dst[crossIdx + 2] = centerColor[clusterK].color[2];

                clusterSum[clusterK][0] += src[crossIdx];
                clusterSum[clusterK][1] += src[crossIdx + 1];
                clusterSum[clusterK][2] += src[crossIdx + 2];
                numCount[clusterK]++;
                crossIdx += 3;
            }     
        }
        for ( s32 k = 0; k < clusterNum; k++)
        {   
            if (numCount[k] == 0)
            {   
                continue;
            }
            // renew the cluster center
            f32 coe = 1.0f / numCount[k];
            center[k].color[0] = (u08)(coe * clusterSum[k][0]);
            center[k].color[1] = (u08)(coe * clusterSum[k][1]);
            center[k].color[2] = (u08)(coe * clusterSum[k][2]);
        }
    }
}

原图是这样的:



当迭代次数为3, 聚类个数为2时,结果如下:


当迭代次数为10, 分类个数为2时,如下:


可以看出,K-means 在迭代3次或之前就已经收敛了。

那么,改变一下聚类个数,将聚类个数分别设置为10和50,迭代次数依然是3,结果如下:



聚类个数越多,图片就被细分的越厉害,当然,所使用的的聚类标准是比较简单的RGB距离,效果并不是最佳,更多的距离标准可以采用YUV、LAB等其他颜色空间。

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值