图像处理------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 原理 ...
随机推荐
- Python CRM项目六
自定义Django Admin的action 在Django Admin中,可以通过action来自定义一些操作,其中默认的action的功能是选中多条数据来进行删除操作 我们在king_admin中 ...
- 以Apache模块的方式编译安装php-5.5.4
新建用户及用户组 groupadd webuser useradd -g webuser webuser 下载php-5.5 下载地址:http://pan.baidu.com/s/1o6I6Lnk ...
- 安装phpredis-master步骤备忘
下载软件包下载地址: http://pan.baidu.com/s/1i37R8TB 解包 tar -zxvf phpredis-master.tar.gz cd phpredis-master /o ...
- zookeeper,win版本搭建集群遇坑记录
版本:3.4.10 问题:启动 zkServer.cmd时报错如下, 解决办法: bin目录下 zkEnv.cmd配置 修改为: 把双引号放在外面. 此时运行zkServer.cmd 用zkCli.c ...
- Oracle打印日历功能
Oracle用SQL打印日历 1.1 打印当月日历 , D, NULL)) SUN, , D, NULL)) MON, , D, NULL)) TUE, , D, NULL)) WED, , D, ...
- [Cpp] 面向对象程序设计 C++
初始化列表(包括成员对象初始化) 初始化列表 ( 推荐 ) : 可以初始化任何类型的数据, 不管是不是普通类型还是对象,都建议用. 不再需要在构造器中赋值了, 而且初始化列表比构造函数要早执行. ...
- C#基础拾遗系列之一:先看懂IL代码
一.前言 首先,想说说为什么要写这样系列的文章,有时候在和同事朋友聊天的时候,经常会听到这样的话题: (1)在这家公司没什么长进,代码太烂,学不到东西.(你有没有想想框架为什么这样写,代码还可以怎么去 ...
- 济南清北学堂游记 Day 7.
完结撒花? 最后的模拟赛与讲题.大家似乎仍然乐在其中,虽然看评测结果,仍然是满地红. 其实到了最后已经是没有多少可写的了..... 一个精彩的地方是晚上填表的时候,群里炸锅了已经.到处都在刷CCL老师 ...
- GSS1
于是我拿合并返回节点的线段树(我也不知道应该叫什么名)水了一下$GSS1$ 比$NOIp$之前写的不知道高到哪里去了,并且只用了$\frac{1}{3}$的时间 #include <iostre ...
- BZOJ 1069: [SCOI2007]最大土地面积 [旋转卡壳]
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2978 Solved: 1173[Submit][Sta ...