Sunteți pe pagina 1din 7

K-meuns clusterlng ln Juvu code found!

My blogpost on K-meuns clusterlng hus the hlghest number of vlews, so people ure probubly lnterested ln
lt. Sudly enough I lost the source code of the K-meuns uctlon u whlle ugo. Lust week I needed un externul
hurddlsk to muke u buck-up of some flles. There wus ulreudy some content on the dlsk. I found qulte
some pleces of code lncludlng the K-meuns code. Although lt ls qulte slmple code operutlng on (lf I
remember correctly 8-blt) greyscule lmuges, lt mlght glve some lnslghts ln how to do thls.
The whole code flle ls presented below. For more lnformutlon you cun vlew my eurller blogpost on K-
meuns clusterlng.
view sourceprint?
001
package actions;
002

003
import java.awt.Color;
004
import java.awt.image.BufferedImage;
005
import java.util.ArrayList;
006

007 /**
008
* This KMeansAction performs a K-means clustering action on a
BufferedImage
009 * @author Patrick van Kouteren
010 *
011 */
012

013
public class KMeansAction {
014

015 BufferedImage image_temp;
016
boolean not_terminated;
017
int loops, changedPixels;
018 int[] histogram;
019 ArrayList classes;
020
int [] lowerbounds;
021
public final static int MEAN_BY_MOD = 1;
022
public final static int MEAN_BY_SPACE = 2;
023
public final static int MEAN_AT_RANDOM = 3;
024

025 /**
026 * Controls the actual work:
027 * - Initialization
028 * - Loop until termination condition is met
029
* + for each pixel: assign pixel to a class such that the
distance from the pixel to the mean of that class is minimized
030
* + for each class: recalculate the means of the class based on
pixels belonging to that class
031 * - End loop
032 * @param image
033 * @param bins (k)
034 * @param histogram
035 */
036
public KMeansAction(BufferedImage
image, int bins,int[]histogram, int initway) {
037 this.histogram = histogram;
038
lowerbounds = new int[bins];
039 initialize(image, bins, initway);
040 calculateBounds();
041
while (not_terminated) {
042 recalculateMeans();
043 loops++;
044 checkTermination();
045 }
046 processImage(image, bins);
047 }
048

049 /**
050 * Set the new color values for the image
051 * @param image
052 */
053
private void processImage(BufferedImage image, int bins) {
054
int delta = 255 / (bins-1);
055
for (int h = 0; h < image.getHeight(); h++){
056
for (int w = 0; w < image.getWidth(); w++){
057
Color rgb = new Color(image.getRGB(w, h));
058
int grey = rgb.getRed();
059
for (int i = 0; i classes.get(i).lowerbound &&
grey < classes.get(i).upperbound) {
060
int g = i*delta;
061
image_temp.setRGB(w,h,(new Color(g, g,
g)).getRGB());
062 }
063 }
064 }
065 }
066 }
067

068 /**
069 * Returns the image created by the processImage method
070 * @return the result image
071 */
072
public BufferedImage getResultImage() {
073
return image_temp;
074 }
075

076 /**
077
* Just for fun: returns the number of loops which were needed for
getting a stable result
078 * @return number of loops for stable result
079 */
080
public int getLoops(){
081
return loops;
082 }
083

084 /**
085
* Initializes the algorithm. Creates k ClusterClasses and puts
them into a LinkedList
086 * @param image
087 * @param bins
088 */
089 @SuppressWarnings("unchecked")
090
private void initialize(BufferedImage image, int bins, intinitway){
091 image_temp = image;
092 loops = 0;
093 changedPixels = 0;
094 not_terminated = true;
095
classes = new ArrayList();
096
for (int i = 0; i < bins; i++) {
097
ClusterClass cc = new ClusterClass(createMean(initway,
bins, i, image));
098 classes.add(cc);
099 }
100

101 }
102

103 /**
104
* Controls the calculations of the upper- and lowerbounds of
ClusterClasses and sets them
105 *
106 */
107
private void calculateBounds() {
108
for (int i = 0; i < classes.size(); i++){
109
int lb = calculateLowerBound(classes.get(i));
110 lowerbounds[i] = lb;
11
1
classes.get(i).setBounds(lb,calculateUpperBound(classes.ge
t(i)) );
112 }
113 }
114

115 /**
116 * Does the actual calculation of the lowerbound
117 * @param ClusterClass
118 * @return Lowerbound
119 */
120
private int calculateLowerBound(ClusterClass cc) {
121
int cMean = cc.getMean();
122
int currentBound = 0;
123
for (int i = 0; i< classes.size(); i++)
{ if (cMean > classes.get(i).getMean()) {
124
currentBound = Math.max((cMean +
classes.get(i).getMean())/2, currentBound);
125 }
126
else {
127 }
128 }
129
return currentBound;
130 }
131

132 /**
133 * Does the actual calculation of the upperbound
134 * @param ClusterClass
135 * @return Upperbound
136 */
137
private int calculateUpperBound(ClusterClass cc) {
138
int cMean = cc.getMean();
139
int currentBound = 255;
140
for (int i = 0; i< classes.size(); i++) {
141
if (cMean < classes.get(i).getMean()) {
142
currentBound = Math.min((cMean +
classes.get(i).getMean())/2, currentBound);
143 }
144
else {}
145 }
146
return currentBound;
147 }
148

149 /**
150
* Takes care of the recalculation of the means of the
ClusterClasses
151 *
152 */
153
private void recalculateMeans() {
154
for (int i = 0; i= 50) {
155 not_terminated = false;
156 }
157
if (changedPixels <= 300) {
158 not_terminated = false;
159 }
160 }
161

162
private void calculateChangedPixels() {
163
int changed = 0;
164
for (int i = 0; i< lowerbounds[i]) {
165
for (int j = c; j lowerbounds[i]) {
166
for (int j = lowerbounds[i]; j< image.getHeight();
h++){
167
for (int w = 0; w < image.getWidth(); w++){
168 pixelindex+=1;
169
if (pixelindex % bins == index) {
170
Color rgb = new Color(image.getRGB(w, h));
171 sum+= rgb.getRed();
172 value+=1;
173 }
174 }}
175
return sum/value;
176

177
case MEAN_BY_SPACE:
178
return (int)(255 / (bins-1) * index);
179
case MEAN_AT_RANDOM:
180 Double dmean = Math.random() * 255;
181
return (int) Math.floor(dmean);
182 default:
183
return 0;
184 }
185 }
186 }</pre>
187
In addition to this, the custom class ClusterClass is defined as:
188
<pre lang="java">package actions;
189

190 /**
191
* The ClusterClass is just a class holding the important cluster
properties.
192 * @author Patrick van Kouteren
193 *
194 */
195

196
public class ClusterClass {
197
int mean, upperbound, lowerbound;
198

199
public ClusterClass(int m) {
200 mean = m;
201 }
202

203
public void setBounds(int lb, int ub) {
204 lowerbound = lb;
205 upperbound = ub;
206 }
207

208
public void setMean(int i) {
209 mean = i;
210 }
211

212
public int getMean() {
213
return mean;
214 }
215

216
public int getLowerBound() {
217
return lowerbound;
218 }
219

220
public int getUpperBound() {
221
return upperbound;
222 }
223

224
public void calculateMean(int [] histogram) {
225
int tempMean = 0;
226
int counter = 0;
227
for (int i = lowerbound; i&lt;= upperbound; i++) {
228 counter += histogram[i];
229 tempMean += histogram[i] * i;
230 }
231 mean = tempMean / counter;
232 }
233

234 }

S-ar putea să vă placă și