图像处理------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 原理 ...
随机推荐
- java基础(六) switch语句的深入解析
引言 switch 语句是非常的基础的知识,掌握起来也不难掌握,语法比较简单.但大部分人基本是知其然,不知其所以然.譬如 早期JDK只允许switch的表达式的值 int及int类型以下的基本类型 ...
- tensorflow.python.framework.errors_impl.OutOfRangeError: FIFOQueue
tensorflow.python.framework.errors_impl.OutOfRangeError: FIFOQueue 原创文章,请勿转载哦~!! 觉得有用的话,欢迎一起讨论相互学习~F ...
- linux下网卡相关查看设置
查整机硬件信息命令dmesg 查看网卡设备相关dmesg | grep eth 查看网卡eth0信息dmesg | grep eth0 使用ethtool命令查看指定网卡信息ethtool eth0 ...
- JMeter监控服务器CPU、内存的方法
jmeter也可以像loadrunner一样监控服务器CPU.内存等性能参数,不过需要安装一些插件 一.首先下载监控服务器的插件 链接:https://pan.baidu.com/s/1o9Zuw ...
- 好用的开源库(二)——uCrop 图片裁剪
最近想要实现图片裁剪的功能,在Github上找到了这个uCrop,star的人挺多的,便是决定入坑,结果长达一个小时的看资料+摸索,终于是在项目中实现了图片裁剪的功能,今天便是来介绍一下uCrop的使 ...
- SpringMVC源码情操陶冶-AnnotationDrivenBeanDefinitionParser注解解析器
mvc:annotation-driven节点的解析器,是springmvc的核心解析器 官方注释 Open Declaration org.springframework.web.servlet.c ...
- java中Queue简介
Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构 offer,add区别:一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝.这时新的 offer 方法 ...
- bzoj 4835: 遗忘之树 [树形DP]
4835: 遗忘之树 题意:点分治,选标号最小的重心,上一次重心向下一次重心连有向边,求原树方案数. md我真不知道当初比赛时干什么去了...现在一眼秒啊... \(size[v]=\frac{siz ...
- BZOJ 1192: [HNOI2006]鬼谷子的钱袋 [娱乐]
题意: n个数分组,使得小于n的每个数都能表示出来,最少几组 就是“最优集合”的超级弱化版.....每次+=now+1 然后一个貌似科学的方法是n二进制拆分 #include <iostream ...
- InnoDB索引
名词解释 clustered index(聚集索引) 对(primary key)主键索引的一种表述.InnoDB表存储是基于primary key列来组织的,这样做可以加快查询和排序速度.为了获得最 ...