一:数学原理

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));

重新计算Cluster中心点RGB值的代码如下:

private double[] reCalculateClusterCenters() {// clear the points nowfor(int i=0; i<clusterCenterList.size(); i++){clusterCenterList.get(i).setNumOfPoints(0);}// recalculate the sum and total of points for each clusterdouble[] 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;
}

四:运行效果


五: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>();}@Overridepublic BufferedImage filter(BufferedImage src, BufferedImage dest) {// initialization the pixel dataint 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 centerRandom 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 pointfor (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 pointdouble[] 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 imagedest = 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(); // rowint col = (int)p.getY(); // columnindex = row * width + col;outPixels[index] = clusterCenterList.get(i).getPixelColor();}}}// fill the pixel datasetRGB( 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 pointdouble[] 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 nowfor(int i=0; i<clusterCenterList.size(); i++){clusterCenterList.get(i).setNumOfPoints(0);}// recalculate the sum and total of points for each clusterdouble[] 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));}}

转载请注明出自gloomyfish博客

图像处理之K-Means算法演示相关推荐

  1. kmeans改进 matlab,基于距离函数的改进k―means 算法

    摘要:聚类算法在自然科学和和社会科学中都有很普遍的应用,而K-means算法是聚类算法中经典的划分方法之一.但如果数据集内相邻的簇之间离散度相差较大,或者是属性分布区间相差较大,则算法的聚类效果十分有 ...

  2. k means算法C语言伪代码,K均值算法(K-Means)

    1. K-Means算法步骤 算法步骤 收敛性定义,畸变函数(distortion function): 伪代码: 1) 创建k个点作为K个簇的起始质心(经常随机选择) 2) 当任意一个点的蔟分配结果 ...

  3. k均值聚类算法(K Means)及其实战案例

    算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...

  4. K means 图片压缩

    k-means的基本原理较为清晰,这里不多赘述,本次博客主要通过基础的k means算法进行图像的压缩处理. 原理分析 在彩色图像中,每个像素的大小为3字节(RGB),可以表示的颜色总数为256 * ...

  5. OpenCV官方文档 理解k - means聚类

    理解k - means聚类 目标 在这一章中,我们将了解k - means聚类的概念,它是如何工作等. 理论 我们将这个处理是常用的一个例子. t恤尺寸问题 考虑一个公司要发布一个新模型的t恤. 显然 ...

  6. k近邻算法_图穷匕见:K近邻算法与手写数字识别

    机器学习算法是从数据中产生模型,也就是进行学习的算法.我们把经验提供给算法,它就能够根据经验数据产生模型.在面对新的情况时,模型就会为我们提供判断(预测)结果.例如,我们根据"个子高.腿长. ...

  7. 基于SPSS的K均值算法

    文章目录 前言 一.K均值算法是什么? 二.动画演示 1.网站 2.示例 三.缺点解决(K-means++算法) 四.SPSS实现 总结 前言 菜鸡学习数学建模 一.K均值算法是什么? K-means ...

  8. 图像处理之特殊灰度算法技巧

    - created by gloomyfish 图像处理之特殊灰度算法技巧 介绍几种特殊的灰度算法滤镜,将彩色图像转换为灰度图像.其中涉及到的有基于阈值的图 像二值化,弗洛伊德.斯坦德伯格抖动算法,基 ...

  9. 机器学习第七章之K近邻算法

    K近邻算法(了解) 7.1 K近邻算法 7.1.1 K近邻算法的原理介绍 7.1.2 K近邻算法的计算步骤及代码实现 7.2 数据预处理之数据归一化 7.2.1 min-max标准化 7.2.2 Z- ...

  10. 机器学习算法系列(二十二)-近似k近邻算法-Annoy(Approximate Nearest Neighbor / ANN)

    阅读本文需要的背景知识点:k近邻算法.一丢丢编程知识 一.引言   前面一节我们学习了机器学习算法系列(二十一)-k近邻算法(k-Nearest Neighbor / kNN Algorithm),其 ...

最新文章

  1. c#如何取自身应用程序文件名和路径?
  2. 利用pyBoard的实验来讨论部分MicroPython特性
  3. 24、Power Query-数学运算的应用(统计男女人数)
  4. Java核心类库-IO-打印流(PrintStream/PrintWriter)
  5. 汇编语言-010(循环移位ROL,ROR 、进位循环进位RCL,RCR 、有符号数溢出 、双精度移位SHLD,SHRD、SHL和ADD计算 、位运算应用)
  6. Tyvj 1176 火焰巨魔的惆怅
  7. 如何解决网页中console的显示内容出现undefined和null_如何优雅地处理前端异常?...
  8. Maven使用技巧001--- 离线更新nexus中央仓库索引的方案
  9. 21天Jenkins打卡Day13视图
  10. ABB码垛算法程序与设计接口参考案例
  11. 网站优化工具-YUI Compressor
  12. python只保留大写字母_python 将文件中除保留字外的小写字母换成大写字母(转换后可运行)...
  13. 去吧!设计模式之桥接模式
  14. 计算机蜂鸣无法开机,计算机开机后会时常出现3声蜂鸣是什么原因
  15. 全栈工程师和架构师的区别
  16. win10禁止计算机进入休眠,Win10怎么关闭系统休眠 Win10关闭系统休眠方法
  17. 视频 | 太壮观了!阿尔乌拉打破全球最大热气球发光表演纪录
  18. python变量及数据类型
  19. ABP框架—项目文件介绍(2)
  20. “第三方支付”盈利模式

热门文章

  1. 自动建站.实现虚拟二级目录
  2. 迷宫问题----经典回溯法解决
  3. ElasticSearch.net NEST批量创建修改删除索引完整示例
  4. 计算机ei期刊最新版2018,2018年EI收录中文期刊目录
  5. 鬼故事之中学异事(01)
  6. Edge上的gmail网页改为纯文字模式后改不回标准模式(HTML Gmail)问题和解决方法
  7. 蒙特卡罗模拟赌徒人生
  8. 奥运比赛电视直播一览表
  9. 【论文写作】Word文档中的MathType公式大小不一导致版面很难看完美解决方法
  10. 学习笔记——VLSI测试方法学和可测性设计