图像处理------K-Means算法演示
一:数学原理
K-Means算法的作者是MacQueen, 基本的数学原理很容易理解,假设有一个像素
数据集P。我们要根据值不同将它分为两个基本的数据集合Cluster1, Cluster2,使
用K-Means算法大致如下:
假设两个Cluster的RGB值分别为112,225,244和23,34,99则像素集合中的像素点
a(222,212,234), b(198,205,229), c(25,77,52),d(34,55,101)计算每个像素点与这
两个cluster中心点的欧几里德距离,则像素点a, b属于前面一个cluster, c,d属于
后面一个cluster。然后在根据(222+198)/2, (212+205)/2, (234+52)/2更新cluster
的RGB值,对后一个cluster做同样处理。然后再计算每个像素点到cluster中心点
的欧几里德距离。最终值没有变化则得到分类Cluster点集合。
二:算法基本流程

三:算法关键代码解析
初始化cluster中心点代码如下:
- Random random = new Random();
- for (int i = 0; i < numOfCluster; i++)
- {
- int randomNumber1 = random.nextInt(width);
- int randomNumber2 = random.nextInt(height);
- index = randomNumber2 * width + randomNumber1;
- ClusterCenter cc = new ClusterCenter(randomNumber1, randomNumber2, inPixels[index]);
- cc.setcIndex(i);
- clusterCenterList.add(cc);
- }
初始化所有像素点代码如下:
- // create all cluster point
- for (int row = 0; row < height; ++row)
- {
- for (int col = 0; col < width; ++col)
- {
- index = row * width + col;
- int color = inPixels[index];
- pointList.add(new ClusterPoint(row, col, color));
- }
- }
计算两个像素点之间欧几里德距离的代码如下:
- // int pa = (p.getPixelColor() >> 24) & 0xff;
- int pr = (p.getPixelColor() >> 16) & 0xff;
- int pg = (p.getPixelColor() >> 8) & 0xff;
- int pb = p.getPixelColor() & 0xff;
- // int ca = (c.getPixelColor() >> 24) & 0xff;
- int cr = (c.getPixelColor() >> 16) & 0xff;
- int cg = (c.getPixelColor() >> 8) & 0xff;
- int cb = c.getPixelColor() & 0xff;
- return Math.sqrt(Math.pow((pr - cr), 2.0) + Math.pow((pg - cg), 2.0) + Math.pow((pb - cb), 2.0));
; i<clusterCenterList.size(); i++)
四:运行效果

五:K-Means算法源代码
- package com.gloomyfish.segmentation.kmeans;
- import java.awt.image.BufferedImage;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- import com.gloomyfish.filter.study.AbstractBufferedImageOp;
- import com.gloomyfish.segmentation.fuzzycmeans.ClusterPoint;
- public class KMeansProcessor extends AbstractBufferedImageOp {
- private List<ClusterCenter> clusterCenterList;
- private List<ClusterPoint> pointList;
- private int numOfCluster;
- public KMeansProcessor(int clusters)
- {
- this.numOfCluster = clusters;
- pointList = new ArrayList<ClusterPoint>();
- this.clusterCenterList = new ArrayList<ClusterCenter>();
- }
- @Override
- public BufferedImage filter(BufferedImage src, BufferedImage dest) {
- // initialization the pixel data
- int width = src.getWidth();
- int height = src.getHeight();
- int[] inPixels = new int[width*height];
- src.getRGB( 0, 0, width, height, inPixels, 0, width );
- int index = 0;
- //Create random points to use a the cluster center
- Random random = new Random();
- for (int i = 0; i < numOfCluster; i++)
- {
- int randomNumber1 = random.nextInt(width);
- int randomNumber2 = random.nextInt(height);
- index = randomNumber2 * width + randomNumber1;
- ClusterCenter cc = new ClusterCenter(randomNumber1, randomNumber2, inPixels[index]);
- cc.setcIndex(i);
- clusterCenterList.add(cc);
- }
- // create all cluster point
- for (int row = 0; row < height; ++row)
- {
- for (int col = 0; col < width; ++col)
- {
- index = row * width + col;
- int color = inPixels[index];
- pointList.add(new ClusterPoint(row, col, color));
- }
- }
- // initialize the clusters for each point
- double[] clusterDisValues = new double[clusterCenterList.size()];
- for(int i=0; i<pointList.size(); i++)
- {
- for(int j=0; j<clusterCenterList.size(); j++)
- {
- clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i), clusterCenterList.get(j));
- }
- pointList.get(i).setClusterIndex(getCloserCluster(clusterDisValues));
- }
- // calculate the old summary
- // assign the points to cluster center
- // calculate the new cluster center
- // computation the delta value
- // stop condition--
- double[] oldClusterCenterColors = reCalculateClusterCenters();
- while(true)
- {
- stepClusters();
- double[] newClusterCenterColors = reCalculateClusterCenters();
- if(isStop(oldClusterCenterColors, newClusterCenterColors))
- {
- break;
- }
- else
- {
- oldClusterCenterColors = newClusterCenterColors;
- }
- }
- //update the result image
- dest = createCompatibleDestImage(src, null );
- index = 0;
- int[] outPixels = new int[width*height];
- for (int j = 0; j < pointList.size(); j++)
- {
- for (int i = 0; i < clusterCenterList.size(); i++)
- {
- ClusterPoint p = this.pointList.get(j);
- if (clusterCenterList.get(i).getcIndex() == p.getClusterIndex())
- {
- int row = (int)p.getX(); // row
- int col = (int)p.getY(); // column
- index = row * width + col;
- outPixels[index] = clusterCenterList.get(i).getPixelColor();
- }
- }
- }
- // fill the pixel data
- setRGB( dest, 0, 0, width, height, outPixels );
- return dest;
- }
- private boolean isStop(double[] oldClusterCenterColors, double[] newClusterCenterColors) {
- for(int i=0; i<oldClusterCenterColors.length; i++)
- {
- System.out.println("cluster " + i + " old : " + oldClusterCenterColors[i] + ", new : " + newClusterCenterColors[i]);
- if(oldClusterCenterColors[i] != newClusterCenterColors[i])
- {
- return false;
- }
- }
- System.out.println();
- return true;
- }
- /**
- * update the cluster index by distance value
- */
- private void stepClusters()
- {
- // initialize the clusters for each point
- double[] clusterDisValues = new double[clusterCenterList.size()];
- for(int i=0; i<pointList.size(); i++)
- {
- for(int j=0; j<clusterCenterList.size(); j++)
- {
- clusterDisValues[j] = calculateEuclideanDistance(pointList.get(i), clusterCenterList.get(j));
- }
- pointList.get(i).setClusterIndex(getCloserCluster(clusterDisValues));
- }
- }
- /**
- * using cluster color of each point to update cluster center color
- *
- * @return
- */
- private double[] reCalculateClusterCenters() {
- // clear the points now
- for(int i=0; i<clusterCenterList.size(); i++)
- {
- clusterCenterList.get(i).setNumOfPoints(0);
- }
- // recalculate the sum and total of points for each cluster
- double[] redSums = new double[3];
- double[] greenSum = new double[3];
- double[] blueSum = new double[3];
- for(int i=0; i<pointList.size(); i++)
- {
- int cIndex = (int)pointList.get(i).getClusterIndex();
- clusterCenterList.get(cIndex).addPoints();
- int ta = (pointList.get(i).getPixelColor() >> 24) & 0xff;
- int tr = (pointList.get(i).getPixelColor() >> 16) & 0xff;
- int tg = (pointList.get(i).getPixelColor() >> 8) & 0xff;
- int tb = pointList.get(i).getPixelColor() & 0xff;
- ta = 255;
- redSums[cIndex] += tr;
- greenSum[cIndex] += tg;
- blueSum[cIndex] += tb;
- }
- double[] oldClusterCentersColors = new double[clusterCenterList.size()];
- for(int i=0; i<clusterCenterList.size(); i++)
- {
- double sum = clusterCenterList.get(i).getNumOfPoints();
- int cIndex = clusterCenterList.get(i).getcIndex();
- int red = (int)(greenSum[cIndex]/sum);
- int green = (int)(greenSum[cIndex]/sum);
- int blue = (int)(blueSum[cIndex]/sum);
- System.out.println("red = " + red + " green = " + green + " blue = " + blue);
- int clusterColor = (255 << 24) | (red << 16) | (green << 8) | blue;
- clusterCenterList.get(i).setPixelColor(clusterColor);
- oldClusterCentersColors[i] = clusterColor;
- }
- return oldClusterCentersColors;
- }
- /**
- *
- * @param clusterDisValues
- * @return
- */
- private double getCloserCluster(double[] clusterDisValues)
- {
- double min = clusterDisValues[0];
- int clusterIndex = 0;
- for(int i=0; i<clusterDisValues.length; i++)
- {
- if(min > clusterDisValues[i])
- {
- min = clusterDisValues[i];
- clusterIndex = i;
- }
- }
- return clusterIndex;
- }
- /**
- *
- * @param point
- * @param cluster
- * @return distance value
- */
- private double calculateEuclideanDistance(ClusterPoint p, ClusterCenter c)
- {
- // int pa = (p.getPixelColor() >> 24) & 0xff;
- int pr = (p.getPixelColor() >> 16) & 0xff;
- int pg = (p.getPixelColor() >> 8) & 0xff;
- int pb = p.getPixelColor() & 0xff;
- // int ca = (c.getPixelColor() >> 24) & 0xff;
- int cr = (c.getPixelColor() >> 16) & 0xff;
- int cg = (c.getPixelColor() >> 8) & 0xff;
- int cb = c.getPixelColor() & 0xff;
- return Math.sqrt(Math.pow((pr - cr), 2.0) + Math.pow((pg - cg), 2.0) + Math.pow((pb - cb), 2.0));
- }
- }
图像处理------K-Means算法演示的更多相关文章
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- K-means算法
K-means算法很简单,它属于无监督学习算法中的聚类算法中的一种方法吧,利用欧式距离进行聚合啦. 解决的问题如图所示哈:有一堆没有标签的训练样本,并且它们可以潜在地分为K类,我们怎么把它们划分呢? ...
- JS写的排序算法演示
看到网上有老外写的,就拿起自已之前完成的jmgraph画图组件也写了一个.想了解jmgraph的请移步:https://github.com/jiamao/jmgraph 当前演示请查看:http:/ ...
- 用Python从零开始实现K近邻算法
KNN算法的定义: KNN通过测量不同样本的特征值之间的距离进行分类.它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别.K通 ...
- 02-18 scikit-learn库之k近邻算法
目录 scikit-learn库之k近邻算法 一.KNeighborsClassifier 1.1 使用场景 1.2 代码 1.3 参数详解 1.4 方法 1.4.1 kneighbors([X, n ...
- 使用K均值算法进行图片压缩
K均值算法 上一期介绍了机器学习中的监督式学习,并用了离散回归与神经网络模型算法来解决手写数字的识别问题.今天我们介绍一种机器学习中的非监督式学习算法--K均值算法. 所谓非监督式学习,是一种 ...
- AlgorithmMan,一套免费的算法演示神器
概述 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/971 访问. 文章末尾附带GitHub开源下载地址. 0.概述 ...
- K近邻算法:机器学习萌新必学算法
摘要:K近邻(k-NearestNeighbor,K-NN)算法是一个有监督的机器学习算法,也被称为K-NN算法,由Cover和Hart于1968年提出,可以用于解决分类问题和回归问题. 1. 为什么 ...
- K 均值算法-如何让数据自动分组
公号:码农充电站pro 主页:https://codeshellme.github.io 之前介绍到的一些机器学习算法都是监督学习算法.所谓监督学习,就是既有特征数据,又有目标数据. 而本篇文章要介绍 ...
- 机器学习算法之K近邻算法
0x00 概述 K近邻算法是机器学习中非常重要的分类算法.可利用K近邻基于不同的特征提取方式来检测异常操作,比如使用K近邻检测Rootkit,使用K近邻检测webshell等. 0x01 原理 ...
随机推荐
- 包装类和基本类型区别?(integer和int取值范围一样大)
1.声明方式不同,int不需要new .Integer需要new 2.性质上根本不同点:int是基本数据类型.Integer是引用数据类型,它有自己的属性,方法 3.存储位置和方式不同:int是存储在 ...
- 针对Chrome谷歌等浏览器不再支持showModalDialog的解决方案
最近在维护一个老项目,之前都是用IE来调试代码的.今天想着测试一下项目的兼容性,就用了谷歌浏览器,然后就遇到这样一个问题:一段用showModalDialog实现弹出模态框和返回值的js代码,在调试时 ...
- 图说:为什么Java中的字符串被定义为不可变的
8张图,看懂Java字符串的不变性 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时,其实会在堆内存中创建 ...
- 不需要客户端插件PHP也能实现单点登录
分析CAS原理,构建PHP单点登录 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户 只需要登录一次就 ...
- Kafka Producer Consumer
Producer API org.apache.kafka.clients.producer.KafkaProducer props.put("bootstrap.servers" ...
- CF 375D. Tree and Queries【莫队 | dsu on tree】
题意: 一棵树,询问一个子树内出现次数$≥k$的颜色有几种 强制在线见上一道 用莫队不知道比分块高到哪里去了,超好写不用调7倍速度!!! 可以用分块维护出现次数这个权值,实现$O(1)-O(\sqrt ...
- POJ 3590 The shuffle Problem [置换群 DP]
传送门 $1A$太爽了 从此$Candy?$完全理解了这种$DP$做法 和bzoj1025类似,不过是求最大的公倍数,并输出一个字典序最小的方案 依旧枚举质因子和次数,不足的划分成1 输出方案从循环长 ...
- 反反爬虫 IP代理
0x01 前言 一般而言,抓取稍微正规一点的网站,都会有反爬虫的制约.反爬虫主要有以下几种方式: 通过UA判断.这是最低级的判断,一般反爬虫不会用这个做唯一判断,因为反反爬虫非常容易,直接随机UA即可 ...
- 01-vagrant安装centos7
1. 安装VirtualBox 2. 安装Vagrant 3. 下载 centos-7.0-x86_64.box [安装命令] $ mkdir vagrant $ cd vagrant $ vag ...
- Windows Server 2016-重置目录还原模式密码
目录还原模式:Directory Services Restore Mode,简称DSRM,又称目录服务恢复模式.是Windows域控制器的服务器安全模式启动选项.DSRM允许管理员用来修复或还原修复 ...