图像处理------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 原理 ...
随机推荐
- 08_Python编码与解码
一.编码的由来 因为计算机只能处理010101二进制数据,如果要处理文本,图像,视频等,需要我们把数据转换成01010二进制格式才能被计算机处理 最先出现的是ASCII,用8位一个字节来表示,成为单字 ...
- Go笔记-流程控制
[if] if 是用于测试某个条件的语句,如果该条件(逻辑型或布尔型)成立,则会执行大括号内的代码,第一个大括号必须和if 或者else同行,否则非法 // 方式1 if condition { // ...
- Jquery DataTable控制显示列,导出EXCEL
1.初始化 var table = $('#table').DataTable({ "data": data[0].DATA, "columns": data[ ...
- 《Thinking in Java》学习笔记(四)
1.Java中的闭包与回调 闭包(Closure)是一种能被调用的对象,它保存了创建它的作用域的信息.JAVA并不能显式地支持闭包,但是在JAVA中,闭包可以通过“接口+内部类”来实现,因为对于非静态 ...
- 在ASP.NET MVC中使用Web API和EntityFramework构建应用程序
最近做了一个项目技术预研:在ASP.NET MVC框架中使用Web API和EntityFramework,构建一个基础的架构,并在此基础上实现基本的CRUD应用. 以下是详细的步骤. 第一步 在数据 ...
- Sql2012数据库还原
Sql2012数据库还原(通过.bak数据库备份文件) 昨天系统挂了,那叫一个悲惨,重装了系统,但是sql2012的数据没有备份,同事帮忙发来备份文件(.bak),开始还原数据. 步骤:1 自己新建一 ...
- 【剑指offer28:字符串的排列】【java】
题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. import ja ...
- 💈 A Cross-Thread Call Helper Class
Conmajia © 2012, 2018 Introduction When you are working on background threads and call frontend GUI ...
- Java经典编程题50道之四十二
809*??=800*??+9*??+1,其中??代表的两位数,8*??的结果为两位数,9*??的结果为3位数.求??代表的两位数,以及809*??后的结果. public class Example ...
- java7 - JDK
一.学习大纲: 1. 熟练使用 JDK 文档 2. 软件包 java.lang 提供利用 Java 编程语言进行程序设计的基础类. 3. 软件包 java.math 提供用于执行任意精度整数算法 (B ...