1. 程式人生 > >【Java】K-means演算法Java實現以及影象分割(續)

【Java】K-means演算法Java實現以及影象分割(續)

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class ImageCluster {
	//主要功能就是讀取一副影象,再對影象進行分割
	//需要分類的簇數
	private int k;
	//迭代次數
	private int m;
	//資料集合
	private dataItem[][] source;
	//中心集合
	private dataItem[] center;
	//統計每個簇的各項資料的總和,用於計算新的點數
	private dataItem[] centerSum;
	
	//讀取指定目錄的圖片資料,並且寫入陣列,這個資料要繼續處理
	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<width;i++)
			for(int j=0;j<height;j++)
				data[i][j]=bi.getRGB(i, j);
		return data;
	}
	//用來處理獲取的畫素資料,提取我們需要的寫入dataItem陣列
	private dataItem[][] InitData(int [][] data){
		dataItem[][] dataitems=new dataItem[data.length][data[0].length];
		for(int i=0;i<data.length;i++){
			for(int j=0;j<data[0].length;j++){
				dataItem di=new dataItem();
				Color c=new Color(data[i][j]);
				di.r=(double)c.getRed();
				di.g=(double)c.getGreen();
				di.b=(double)c.getBlue();
				di.group=1;
				dataitems[i][j]=di;
			}
		}
		return dataitems;
	}
	//生成隨機的初始中心
	private void initCenters(int k){
		center =new dataItem[k];
		centerSum=new dataItem[k];//用來統計每個聚類裡面的RGB分別之和,方便計算均值
		int width,height;
		for(int i=0;i<k;i++){
			//boolean flag=true;
			dataItem cent=new dataItem();
			dataItem cent2=new dataItem();
		
			width=(int)(Math.random()*source.length);
			height=(int)(Math.random()*source[0].length);
			cent.group=i;
			cent.r=(double)source[width][height].r;
			cent.g=(double)source[width][height].g;
			cent.b=(double)source[width][height].b;
			center[i]=cent;
			

			cent2.r=cent.r;
			cent2.g=cent.g;
			cent2.b=cent.b;
			cent2.group=0;
			centerSum[i]=cent2;
			
			width=0;height=0;
		}
		System.out.println("初始4箇中心");
		for (int i = 0; i < center.length; i++)
		{				
			System.out.println("("+center[i].r+","+center[i].g+","+center[i].b+")");
		}
	}
	//計算兩個畫素之間的歐式距離,用RGB作為三維座標
	private double distance(dataItem first,dataItem second){
		double distance=0;
		distance=Math.sqrt(Math.pow((first.r-second.r),2)+Math.pow((first.g-second.g),2)+
				Math.pow((first.b-second.b),2));
		return distance;
	}
	//返回一個數組中最小的座標
	private int minDistance(double[] distance){
		double minDistance=distance[0];
		int minLocation=0;
		for(int i=0;i<distance.length;i++){
			if(distance[i]<minDistance){
				minDistance=distance[i];
				minLocation=i;
			}else if(distance[i]==minDistance){
				if((Math.random()*10)<5){
					minLocation=i;
				}
			}
		}
		return minLocation;
	}
	//每個點進行分類
	private void clusterSet(){
		int group=-1;
		double distance[]=new double[k];
		for(int i=0;i<source.length;i++){
			for(int j=0;j<source[0].length;j++){
				//求出距離中心點最短的中心
				for(int q=0;q<center.length;q++){
					distance[q]=distance(center[q],source[i][j]);
				}
				group=minDistance(distance);//尋找該點最近的中心
				source[i][j].group=group;//把該點進行分類
				centerSum[group].r+=source[i][j].r;//分類完求出該類的RGB和
				centerSum[group].g+=source[i][j].g;
				centerSum[group].b+=source[i][j].b;
				centerSum[group].group+=1;//這個就是用來統計聚類裡有幾個點
				group=-1;
			}
		}
	}
	//設定新的中心
	public void setNewCenter(){
		for(int i=0;i<centerSum.length;i++){
			System.out.println(i+":"+centerSum[i].group+":"+centerSum[i].r+":"+centerSum[i].g+":"+centerSum[i].b);
                        //取平均值為新的中心
			center[i].r=(int)(centerSum[i].r/centerSum[i].group);
			center[i].g=(int)(centerSum[i].g/centerSum[i].group);
			center[i].b=(int)(centerSum[i].b/centerSum[i].group);
			//重置之前的求和結果
			centerSum[i].r=center[i].r;
			centerSum[i].g=center[i].g;
			centerSum[i].b=center[i].b;
			centerSum[i].group=0;
		}
	}
	//輸出聚類好的資料
	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<source.length;i++){
			for(int j=0;j<source[0].length;j++){
				if(source[i][j].group==0)
					nbi.setRGB(i, j, c0.getRGB());
				else if(source[i][j].group==1)
					nbi.setRGB(i, j, c1.getRGB());
				else if(source[i][j].group==2)
					nbi.setRGB(i, j, c2.getRGB());
				else if (source[i][j].group==3)
					nbi.setRGB(i, j, c3.getRGB());
				//Color c=new Color((int)center[source[i][j].group].r,
				//		(int)center[source[i][j].group].g,(int)center[source[i][j].group].b);
				//nbi.setRGB(i, j, c.getRGB());
			}
		}
		try{
			ImageIO.write(nbi, "jpg", new File(path));
		}catch(IOException e){
			e.printStackTrace();
			}
	}
	//進行kmeans計算的核心函式
	public void kmeans(String path,int k,int m){
		source=InitData(getImageData(path));
		/*測試輸出
		for(int i=0;i<source.length;i++)
			for(int j=0;j<source[0].length;j++)
				System.out.println("("+source[i][j].x+","+source[i][j].y+","+source[i][j].r+","+source[i][j].g+","+source[i][j].b+")");
		*/
		this.k=k;
		this.m=m;
		//初始化聚類中心
		initCenters(k);
		/*測試輸出
		for (int i = 0; i < center.length; i++)			
			System.out.println("("+center[i].x+","+center[i].y+","+center[i].r+","+center[i].g+","+center[i].b+")");
		*/
		//進行m次聚類
		for(int level=0;level<m;level++){
			clusterSet();
			setNewCenter();
			for (int i = 0; i < center.length; i++)
			{				
				System.out.println("("+center[i].r+","+center[i].g+","+center[i].b+")");
			}
		}
		clusterSet();
		System.out.println("第"+m+"次迭代完成,聚類中心為:");
		for (int i = 0; i < center.length; i++)
		{				
			System.out.println("("+center[i].r+","+center[i].g+","+center[i].b+")");
		}
		System.out.println("迭代總次數:"+m);//進行影象輸出,這個隨意改
		ImagedataOut("E:\\Android\\kmeans\\src\\test4.jpg");
	}

}
     我的程式碼註釋寫的很清楚了。。。。我覺得說的再多都不如靜下心來讀程式碼。

相關推薦

JavaK-means演算法Java實現以及影象分割

import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class

Pythonk-means演算法實現

# -*- coding: utf-8 -*- import math import random import matplotlib.pyplot as plt from matplotlib import colors as m_colors #生成樣本點 def g

利用k-means演算法對灰度影象分割

本文主要利用k-means來對灰度影象進行分割。首先對k-means進行簡單的介紹,然後直接上程式碼。那麼什麼是k-means演算法?K-means演算法是硬聚類演算法,是典型的基於原型的目標函式聚類方法的代表,它是資料點到原型的某種距離作為優化的目標函式,利用函式求極值的方法得到迭代運算的調整規則

機器學習K-Means演算法的原理流程、程式碼實現及優缺點

分類是根據樣本某些屬性或某類特徵(可以融合多類特徵),把樣本型別歸為已確定的某一類別中。機器學習中常見的分類演算法有:SVM(支援向量機)、KNN(最鄰近法)、Decision Tree(決策樹分類法)

基於Redis Lua指令碼實現的分散式鎖Java實現

最近專案中需要用到一個分散式的鎖,考慮到基於會話節點實現的zookeeper鎖效能不夠,於是想使用redis來實現一個分散式的鎖。看了網上的幾個實現方案後,發現都不夠嚴謹。比如這篇:用Redis實現分散式鎖裡面設計的鎖有個最大的問題是鎖的超時值TTL會一直被改寫

JavaGradle構建SpringMVC框架實現App請求介面圖文超詳細

Gradle構建SpringMVC框架實現App請求介面 最近這段時間忙著在找工作,面試不是很多。閒著沒什麼事幹就想著把積累的一點後臺的知識理一理,雖然不一定非得做這方面的工作,但是以後的工作中,遇到一些問題可以快速的定位到。接觸後臺的時間很短,在上一家公司的時候也做

程式碼K-means聚類詳解及實現 Matlab聚類工具箱和自己實現

一. 聚類 先說說聚類。顧名思義,就是有一團資料,根據某種準則把相似的資料分別聚在一起,形成不同的類別(每個類別稱為一簇)。聚類是一種無監督的演算法。所謂無監督就是說,雖然聚類把物體分類到了不同的簇,只能知道哪些資料是屬於同一類的,至於這一類資料到底是什麼,並不知道。

JavaFlumeFlume-NG啟動過程源代碼分析

code extends fix tar top 依據 oid article gif 從bin/flume 這個shell腳本能夠看到Flume的起始於org.apache.flume.node.Application類,這是flume的main函數所在。   m

YOLOV2K-means 計算 anchor boxes

目錄 k-means原理 問題 演算法概要 k-means演算法缺點 k-means++演算法 k-means 計算 anchor boxes 距離公式 程式碼實現 參考 k-means原理 K-means演算法是很典型的基於距離的聚類演算法,採用距離

k-Means演算法Matlab實現

clc; clear; %讀取資料檔案,生成點矩陣 fileID = fopen('D:\matlabFile\data.txt');  C=textscan(fileID,'%f %f');  fclose(fileID);  %顯示陣列結果 %celldisp(C);

K-meansK-means++演算法程式碼實現Python

K-means和K-means++主要區別在於,K-means++演算法選擇初始類中心時,儘可能選擇相距較遠的類中心,而K-means僅僅是隨機初始化類中心。 #K-means演算法 from pylab import * from numpy import * impo

第124篇 一對一視頻錄制及網站註冊 周四

一對一視頻錄制 網站註冊 關鍵詞:一對一視頻錄制,網站註冊一、一對一視頻錄制1.1 參考網址https://www.webrtc-experiment.com/RecordRTC/視頻錄制下載網址:https://github.com/muaz-khan/RecordRTC1.2 網頁錄制本地:ht

第135篇 一對一視頻錄制及必填項紅色星標及隱藏index.php及必選項不能為空 周一

一對一視頻錄制 必填項紅色星標 隱藏index.php 必選項不能為空 關鍵詞:一對一視頻錄制, 必填項紅色星標, 隱藏index.php, 必選項不能為空一、一對一視頻錄制1.1 需要做的二、我的網站2.1 必填項紅色星標代碼如下:<spanstyle="color:red;">

西安用Leangoo做Scrum敏捷開發實戰課免費

帶來 互聯網產品 簽到 class -s 認證 名企 gin light Leangoo誠邀您參加 2017《用leangoo做Scrum敏捷開發》實戰課!在此實戰課上,您不僅可以聽到一線資深敏捷顧問帶來的敏捷落地實踐經驗,還可以和眾多企業同仁共同探討敏捷實踐過程中的酸甜

Learning多項式乘法與快速傅裏葉變換FFT

alt 技術 cos 相同 es2017 define ostream 意思 呵呵 簡介:   FFT主要運用於快速卷積,其中一個例子就是如何將兩個多項式相乘,或者高精度乘高精度的操作。   顯然暴搞是$O(n^2)$的復雜度,然而FFT可以將其將為$O(n lg

網路程式設計基礎day09:socket解決粘包問題之MD5

本節內容 1、概述 2、程式碼實現 一、概述   上一篇部落格講到的用MD5來校驗還是用的之前解決粘包的方法,就是客戶端傳送一個請求,等待服務端的確認的這樣的一個笨方法。下面我們用另外一種方法:就是客戶端已經知道可接收多少資料了,既然客戶端已經知道接收多少資料了,那麼客戶端在接收資料的時候,正好接收已

LeetCode149. Max Points on a Line 解題報告Python

作者: 負雪明燭 id: fuxuemingzhu 個人部落格: http://fuxuemingzhu.cn/ 目錄 題目描述 題目大意 解題方法 字典+最大公約數 日期

LeetCode669. Trim a Binary Search Tree 解題報告Python

作者: 負雪明燭 id: fuxuemingzhu 個人部落格: http://fuxuemingzhu.cn/ 目錄 題目描述 題目大意 解題方法 遞迴 日期 題目

LiveData 在 SnackBar/Navigation 情景下的使用SingleLiveEvent

前言 本文翻譯自【LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)】,詳細介紹了 liveData 的使用。感謝作者 Jose Alcérreca。水平有限,歡迎指正討論。 前面兩篇介紹 LiveDa

LeetCode19. Remove Nth Node From End of ListC++

地址:https://leetcode.com/problems/remove-nth-node-from-end-of-list/ 題目: Given a linked list, remove the