<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Patrick&#039;s playground &#187; K-means clustering</title>
	<atom:link href="http://www.vankouteren.eu/blog/tag/k-means-clustering/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.vankouteren.eu/blog</link>
	<description>Random thoughts, problems and solutions</description>
	<lastBuildDate>Sun, 29 Jan 2012 07:53:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>K Means clustering and Histogram equalization source code</title>
		<link>http://www.vankouteren.eu/blog/2010/03/k-means-clustering-and-histogram-equalization-source-code/</link>
		<comments>http://www.vankouteren.eu/blog/2010/03/k-means-clustering-and-histogram-equalization-source-code/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 06:41:54 +0000</pubDate>
		<dc:creator>Patrick van Kouteren</dc:creator>
				<category><![CDATA[JAVA]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Histogram equalization]]></category>
		<category><![CDATA[k-means]]></category>
		<category><![CDATA[K-means clustering]]></category>
		<category><![CDATA[source code]]></category>

		<guid isPermaLink="false">http://www.vankouteren.eu/blog/?p=195</guid>
		<description><![CDATA[As there was some interest in source code in two earlier posts (post 1, post 2) I've posted the source code here. It's also available through the download page. Please note that the code itself is at least 4 years old and there are far better ways to solve some things. I therefore suggest that [...]]]></description>
			<content:encoded><![CDATA[<p>As there was some interest in source code in two earlier posts (<a href="http://www.vankouteren.eu/blog/2009/09/k-means-clustering-in-java-code-found/" target="_blank">post 1</a>, <a href="http://www.vankouteren.eu/blog/2007/10/k-means-clustering-implementation-in-java/" target="_blank">post 2</a>) I've posted the source code <a href="http://www.vankouteren.eu/downloads/Ispe-dev.zip" target="_blank">here</a>.</p>
<p>It's also available through the <a href="http://www.vankouteren.eu/blog/downloads/" target="_blank">download page</a>.</p>
<p>Please note that the code itself is at least 4 years old and there are far better ways to solve some things. I therefore suggest that it is used for studying purposes only. Comments and improvments are very much appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vankouteren.eu/blog/2010/03/k-means-clustering-and-histogram-equalization-source-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>K-means clustering in Java code found!</title>
		<link>http://www.vankouteren.eu/blog/2009/09/k-means-clustering-in-java-code-found/</link>
		<comments>http://www.vankouteren.eu/blog/2009/09/k-means-clustering-in-java-code-found/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 13:36:45 +0000</pubDate>
		<dc:creator>Patrick van Kouteren</dc:creator>
				<category><![CDATA[JAVA]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[k-means]]></category>
		<category><![CDATA[K-means clustering]]></category>

		<guid isPermaLink="false">http://www.vankouteren.eu/blog/?p=144</guid>
		<description><![CDATA[My blogpost on K-means clustering has the highest number of views, so people are probably interested in it. Sadly enough I lost the source code of the K-means action a while ago. Last week I needed an external harddisk to make a back-up of some files. There was already some content on the disk. I [...]]]></description>
			<content:encoded><![CDATA[            <script type="text/javascript" src="http://www.vankouteren.eu/blog/wp-content/plugins/wordpress-code-snippet/scripts/shBrushJava.js"></script>
<p>My <a title="K-means clustering implementation in JAVA" href="http://www.vankouteren.eu/blog/2007/10/k-means-clustering-implementation-in-java/">blogpost on K-means clustering</a> has the highest number of views, so people are probably interested in it. Sadly enough I lost the source code of the K-means action a while ago. Last week I needed an external harddisk to make a back-up of some files. There was already some content on the disk. I found quite some pieces of code including the K-means code. Although it is quite simple code operating on (if I remember correctly 8-bit) greyscale images, it might give some insights in how to do this.</p>
<p><span id="more-144"></span>The whole code file is presented below. For more information you can view <a title="K-means clustering implementation in JAVA" href="http://www.vankouteren.eu/blog/2007/10/k-means-clustering-implementation-in-java/">my earlier blogpost</a> on K-means clustering.</p>
<p><pre class="brush: java">package actions;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
 * This KMeansAction performs a K-means clustering action on a BufferedImage
 * @author Patrick van Kouteren
 *
 */

public class KMeansAction {

		BufferedImage image_temp;
		boolean not_terminated;
		int loops, changedPixels;
		int[] histogram;
		ArrayList classes;
		int [] lowerbounds;
		public final static int MEAN_BY_MOD = 1;
		public final static int MEAN_BY_SPACE = 2;
		public final static int MEAN_AT_RANDOM = 3;

		/**
		 * Controls the actual work:
		 * - Initialization
		 * - Loop until termination condition is met
		 *  + for each pixel: assign pixel to a class such that the distance from the pixel to the mean of that class is minimized
		 *  + for each class: recalculate the means of the class based on pixels belonging to that class
		 * - End loop
		 * @param image
		 * @param bins (k)
		 * @param histogram
		 */
		public KMeansAction(BufferedImage image, int bins, int[]histogram, int initway) {
			this.histogram = histogram;
			lowerbounds = new int[bins];
			initialize(image, bins, initway);
			calculateBounds();
			while (not_terminated) {
				recalculateMeans();
				loops++;
				checkTermination();
				}
			processImage(image, bins);
		}

		/**
		 * Set the new color values for the image
		 * @param image
		 */
		private void processImage(BufferedImage image, int bins) {
			int delta = 255 / (bins-1);
			for (int h = 0; h &amp;lt; image.getHeight(); h++){
				for (int w = 0; w &amp;lt; image.getWidth(); w++){
					Color rgb = new Color(image.getRGB(w, h));
					int grey = rgb.getRed();
					for (int i = 0; i classes.get(i).lowerbound &amp;amp;&amp;amp; grey &amp;lt; classes.get(i).upperbound) {
							int g = i*delta;
							image_temp.setRGB(w,h,(new Color(g, g, g)).getRGB());
						}
					}
				}
			}
		}

		/**
		 * Returns the image created by the processImage method
		 * @return the result image
		 */
		public BufferedImage getResultImage() {
			return image_temp;
		}

		/**
		 * Just for fun: returns the number of loops which were needed for getting a stable result
		 * @return number of loops for stable result
		 */
		public int getLoops(){
			return loops;
		}

		/**
		 * Initializes the algorithm. Creates k ClusterClasses and puts them into a LinkedList
		 * @param image
		 * @param bins
		 */
		@SuppressWarnings(&quot;unchecked&quot;)
		private void initialize(BufferedImage image, int bins, int initway){
			image_temp = image;
			loops = 0;
			changedPixels = 0;
			not_terminated = true;
			classes = new ArrayList();
			for (int i = 0; i &amp;lt; bins; i++) {
				ClusterClass cc = new ClusterClass(createMean(initway, bins, i, image));
				classes.add(cc);
			}

		}

		/**
		 * Controls the calculations of the upper- and lowerbounds of ClusterClasses and sets them
		 *
		 */
		private void calculateBounds() {
			for (int i = 0; i &amp;lt; classes.size(); i++){
				int lb = calculateLowerBound(classes.get(i));
				lowerbounds[i] = lb;
				classes.get(i).setBounds(lb,calculateUpperBound(classes.get(i)) );
				}
		}

		/**
		 * Does the actual calculation of the lowerbound
		 * @param ClusterClass
		 * @return Lowerbound
		 */
		private int calculateLowerBound(ClusterClass cc) {
			int cMean = cc.getMean();
			int currentBound = 0;
			for (int i = 0; i&amp;lt; classes.size(); i++) { 					if (cMean &amp;gt; classes.get(i).getMean()) {
						currentBound = Math.max((cMean + classes.get(i).getMean())/2, currentBound);
					}
					else {
					}
				}
			return currentBound;
			}

		/**
		 * Does the actual calculation of the upperbound
		 * @param ClusterClass
		 * @return Upperbound
		 */
		private int calculateUpperBound(ClusterClass cc) {
				int cMean = cc.getMean();
				int currentBound = 255;
				for (int i = 0; i&amp;lt; classes.size(); i++) {
						if (cMean &amp;lt; classes.get(i).getMean()) {
							currentBound = Math.min((cMean + classes.get(i).getMean())/2, currentBound);
						}
						else {}
					}
				return currentBound;
				}

		/**
		 * Takes care of the recalculation of the means of the ClusterClasses
		 *
		 */
		private void recalculateMeans() {
			for (int i = 0; i= 50) {
				not_terminated = false;
			}
			if (changedPixels &amp;lt;= 300) {
				not_terminated = false;
			}
		}

		private void calculateChangedPixels() {
			int changed = 0;
			for (int i = 0; i&amp;lt; lowerbounds[i]) {
					for (int j = c; j lowerbounds[i]) {
					for (int j = lowerbounds[i]; j&amp;lt; image.getHeight(); h++){
					for (int w = 0; w &amp;lt; image.getWidth(); w++){
						pixelindex+=1;
						if (pixelindex % bins == index) {
							Color rgb = new Color(image.getRGB(w, h));
							sum+= rgb.getRed();
							value+=1;
						}
					}}
				return sum/value;

			case MEAN_BY_SPACE:
				return (int)(255 / (bins-1) * index);
			case MEAN_AT_RANDOM:
				Double dmean = Math.random() * 255;
				return (int) Math.floor(dmean);
			default:
				return 0;
			}
		}
}&lt;/pre&gt;
In addition to this, the custom class ClusterClass is defined as:
&lt;pre lang=&quot;java&quot;&gt;package actions;

/**
 * The ClusterClass is just a class holding the important cluster properties.
 * @author Patrick van Kouteren
 *
 */

public class ClusterClass {
	int mean, upperbound, lowerbound;

	public ClusterClass(int m) {
		mean = m;
	}

	public void setBounds(int lb, int ub) {
		lowerbound = lb;
		upperbound = ub;
	}

	public void setMean(int i) {
		mean = i;
	}

	public int getMean() {
		return mean;
	}

	public int getLowerBound() {
		return lowerbound;
	}

	public int getUpperBound() {
		return upperbound;
	}

	public void calculateMean(int [] histogram) {
		int tempMean = 0;
		int counter = 0;
		for (int i = lowerbound; i&amp;lt;= upperbound; i++) {
			counter += histogram[i];
			tempMean += histogram[i] * i;
		}
		mean = tempMean / counter;
	}

}</pre></p>
<p>The source code might not be completely visible. It can be viewed in a blank screen <a title="View code in blank screen" href="http://www.vankouteren.eu/downloads/KMeansAction.java">here</a>. As mentioned in the replies to this post, I forgot to add the ClusterClass. It can be viewed in a blank screen <a title="ClusterClass" href="http://www.vankouteren.eu/downloads/ClusterClass.java" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vankouteren.eu/blog/2009/09/k-means-clustering-in-java-code-found/feed/</wfw:commentRss>
		<slash:comments>69</slash:comments>
		</item>
	</channel>
</rss>

