博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Java】K-means算法Java实现以及图像切割
阅读量:6123 次
发布时间:2019-06-21

本文共 4333 字,大约阅读时间需要 14 分钟。

1.K-means算法简述以及代码原型

数据挖掘中一个重要算法是K-means。我这里就不做具体介绍。假设感兴趣的话能够移步陈皓的博客:   

  讲得非常好

    总的来讲,k-means聚类须要下面几个步骤:

         ①.初始化数据

         ②.计算初始的中心点,能够随机选择

         ③.计算每一个点到每一个聚类中心的距离。而且划分到距离最短的聚类中心簇中

         ④.计算每一个聚类簇的平均值,这个均值作为新的聚类中心,反复步骤3

         ⑤.假设达到最大循环或者是聚类中心不再变化或者聚类中心变化幅度小于一定范围时,停止循环。

    恩。原理就是这样,超级简单。可是Java算法实现起来代码量并不小。这个代码也不算是全然自己写的啦。也有些借鉴。我把k-means实现封装在了一个类里面,这样就能够随时调用了呢。

      

import java.util.ArrayList;import java.util.Random;public class kmeans {	private int k;//簇数	private int m;//迭代次数	private int dataSetLength;//数据集长度	private ArrayList
dataSet;//数据集合 private ArrayList
center;//中心链表 private ArrayList
> cluster;//簇 private ArrayList
jc;//误差平方和,这个是用来计算中心聚点的移动哦 private Random random; //设置原始数据集合 public void setDataSet(ArrayList
dataSet){ this.dataSet=dataSet; } //获得簇分组 public ArrayList
> getCluster(){ return this.cluster; } //构造函数,传入要分的簇的数量 public kmeans(int k){ if(k<=0) k=1; this.k=k; } //初始化 private void init(){ m=0; random=new Random(); if(dataSet==null||dataSet.size()==0) initDataSet(); dataSetLength=dataSet.size(); if(k>dataSetLength) k=dataSetLength; center=initCenters(); cluster=initCluster(); jc=new ArrayList
(); } //初始化数据集合 private void initDataSet(){ dataSet=new ArrayList
(); double[][] dataSetArray=new double[][]{ {8,2},{3,4},{2,5},{4,2}, {7,3},{6,2},{4,7},{6,3},{5,3},{6,3},{6,9}, {1,6},{3,9},{4,1},{8,6}}; for(int i=0;i
initCenters(){ ArrayList
center= new ArrayList
(); //生成一个随机数列。 int[] randoms=new int[k]; boolean flag; int temp=random.nextInt(dataSetLength); randoms[0]=temp; for(int i=1;i
> initCluster(){ ArrayList
> cluster= new ArrayList
>(); for(int i=0;i
()); return cluster; } //计算距离 private double distance(double[] element,double[] center){ double distance=0.0f; double x=element[0]-center[0]; double y=element[1]-center[1]; double z=element[2]-center[2]; double sum=x*x+y*y+z*z; distance=(double)Math.sqrt(sum); return distance; } //计算最短的距离 private int minDistance(double[] distance){ double minDistance=distance[0]; int minLocation=0; for(int i=0;i
=50) break; //否则继续生成新的中心 setNewCenter(); m++; cluster.clear(); cluster=initCluster(); } }
//仅仅暴露一个接口给外部类	public void execute(){		System.out.print("start kmeans\n");		Kmeans();		System.out.print("kmeans end\n");	}
//用来在外面打印出来已经分好的聚类	public void printDataArray(ArrayList
data,String dataArrayName){ for(int i=0;i
  嗯。代码就是这样。凝视写的非常具体,也都能看得懂。

以下我给一个測试样例。

import java.util.ArrayList;public class Test {	public static void main(String[] args){		kmeans k=new kmeans(2);		ArrayList
dataSet=new ArrayList
(); dataSet.add(new double[]{2,2,2}); dataSet.add(new double[]{1,2,2}); dataSet.add(new double[]{2,1,2}); dataSet.add(new double[]{1,3,2}); dataSet.add(new double[]{3,1,2}); dataSet.add(new double[]{-2,-2,-2}); dataSet.add(new double[]{-1,-2,-2}); dataSet.add(new double[]{-2,-1,-2}); dataSet.add(new double[]{-3,-1,-2}); dataSet.add(new double[]{-1,-3,-2}); k.setDataSet(dataSet); k.execute(); ArrayList
> cluster=k.getCluster(); for(int i=0;i
   没啥难度,也就是输入写初始数据。然后运行k-means在进行分类。最后打印一下。

这个原型代码非常粗糙。没有加入聚类个数以及循环次数的变量。这些须要自己动手啦。

2.k-means应用图像切割

  我们能够把k-means聚类放在图像切割上,也就是说把一个颜色的像素分为一类,然后再涂一个颜色。

像这样。

左边就是聚类之前的,右边是聚类之后的
,看起来还是满炫酷的。事实上聚类算法也是非常easy扩展到这里的。
有以下四个提示(由于是作业,我决定先不放马,不然到时候作业雷同我的学分就咖喱gaygay了):
   ①.上面的原型代码是对二维的数据进行分类,那我们也知道。一个颜色有RGB三种原色构成,也就是说我们仅仅须要 在二维的基础上。加上一维数据就吼啦。非常easy有木有,改变下数组结构,在距离计算编程三维欧式距离就吼。
   ②.Java有自带的图像处理类,所以读取数据敲击方便。我给一点代码提示哦
//读取指定文件夹的图片数据,而且写入数组,这个数据要继续处理	private int[][] getImageData(String path){		BufferedImage bi=null;		try{			bi=ImageIO.read(new File(path));		}catch (IOException e){			e.printStackTrace();		}		int width=bi.getWidth();		int height=bi.getHeight();		int [][] data=new int[width][height];		for(int i=0;i
//介货是用来输出图像的
           private void ImagedataOut(String path){		Color c0=new Color(255,0,0);		Color c1=new Color(0,255,0);		Color c2=new Color(0,0,255);		Color c3=new Color(128,128,128);		BufferedImage nbi=new BufferedImage(source.length,source[0].length,BufferedImage.TYPE_INT_RGB);		for(int i=0;i
     非常舒爽。你问我dataItem是啥?等我交完作业我就告诉你。 
    ③.有一点不同的是。注意数据格式。胖胖開始用的就是int类型,结果在计算新的聚类中心的时候溢出了呢。。

。所幸鹏鹏改成了double。可是鹏鹏在计算距离的时候又写错了,最后还是机智的胖胖鹏解决掉了全部的bug。

    ④.注意读取图片的时候保护好数据的顺序,也就是用一个二维数组来存储,这样在写的时候就不用记录像素点的位置,输出的时候也非常方便。
   就是这些。。。

等我作业交完就来一次完整的代码解说。

你可能感兴趣的文章
Windows Server已可安装Docker,Azure开始支持Mesosphere
查看>>
简洁优雅地实现夜间模式
查看>>
react学习总结
查看>>
微软正式发布PowerShell Core 6.0
查看>>
Amazon发布新的会话管理器
查看>>
InfoQ趋势报告:DevOps 和云计算
查看>>
舍弃Python,为什么知乎选用Go重构推荐系统?
查看>>
在soapui上踩过的坑
查看>>
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
must implement java.io.Serializable hessian
查看>>
Microsoft Licenses Flash Lite for Windows Mobile Users
查看>>
HDOJ 2020 绝对值排序
查看>>
HDOJ/HDU 2560 Buildings(嗯~水题)
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
[20170628]12C ORA-54032.txt
查看>>
除以2
查看>>
高可用集群原理解析
查看>>
Nginx配置URL转向tomcat
查看>>