Repository: commons-math
Updated Branches:
  refs/heads/master 81585a3c4 -> f0943a724


Add userguide example for image clustering.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/f0943a72
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/f0943a72
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/f0943a72

Branch: refs/heads/master
Commit: f0943a7242041a16c8f7fca845592e48bb19ac74
Parents: 81585a3
Author: Thomas Neidhart <thomas.neidh...@gmail.com>
Authored: Mon Dec 28 21:01:18 2015 +0100
Committer: Thomas Neidhart <thomas.neidh...@gmail.com>
Committed: Mon Dec 28 21:01:18 2015 +0100

----------------------------------------------------------------------
 .../commons/math4/userguide/ExampleUtils.java   |  10 +
 .../clustering/ImageClusteringExample.java      | 203 +++++++++++++++++++
 src/userguide/resources/ColorfulBird.jpg        | Bin 0 -> 98227 bytes
 src/userguide/resources/references.txt          |   4 +-
 4 files changed, 216 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/f0943a72/src/userguide/java/org/apache/commons/math4/userguide/ExampleUtils.java
----------------------------------------------------------------------
diff --git 
a/src/userguide/java/org/apache/commons/math4/userguide/ExampleUtils.java 
b/src/userguide/java/org/apache/commons/math4/userguide/ExampleUtils.java
index e58540d..dddc96c 100644
--- a/src/userguide/java/org/apache/commons/math4/userguide/ExampleUtils.java
+++ b/src/userguide/java/org/apache/commons/math4/userguide/ExampleUtils.java
@@ -17,12 +17,14 @@
 package org.apache.commons.math4.userguide;
 
 import java.awt.Component;
+import java.awt.Graphics2D;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.image.BufferedImage;
 import java.io.File;
+import java.io.IOException;
 
 import javax.imageio.ImageIO;
 import javax.swing.JFileChooser;
@@ -100,5 +102,13 @@ public class ExampleUtils {
         component.paint(image.getGraphics());
         return image;
     }
+    
+    public static BufferedImage resizeImage(BufferedImage originalImage, int 
width, int height, int type) throws IOException {
+        BufferedImage resizedImage = new BufferedImage(width, height, type);
+        Graphics2D g = resizedImage.createGraphics();
+        g.drawImage(originalImage, 0, 0, width, height, null);
+        g.dispose();
+        return resizedImage;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/f0943a72/src/userguide/java/org/apache/commons/math4/userguide/clustering/ImageClusteringExample.java
----------------------------------------------------------------------
diff --git 
a/src/userguide/java/org/apache/commons/math4/userguide/clustering/ImageClusteringExample.java
 
b/src/userguide/java/org/apache/commons/math4/userguide/clustering/ImageClusteringExample.java
new file mode 100644
index 0000000..67e197a
--- /dev/null
+++ 
b/src/userguide/java/org/apache/commons/math4/userguide/clustering/ImageClusteringExample.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math4.userguide.clustering;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+
+import org.apache.commons.math4.ml.clustering.CentroidCluster;
+import org.apache.commons.math4.ml.clustering.Clusterable;
+import org.apache.commons.math4.ml.clustering.KMeansPlusPlusClusterer;
+import org.apache.commons.math4.userguide.ExampleUtils;
+import org.apache.commons.math4.userguide.ExampleUtils.ExampleFrame;
+
+/**
+ * This example shows how clustering can be applied to images.
+ */
+@SuppressWarnings("serial")
+public class ImageClusteringExample {
+
+    public static class Display extends ExampleFrame {
+        
+        private BufferedImage referenceImage;
+        private BufferedImage clusterImage;
+        
+        private Raster referenceRaster;
+        
+        private ImagePainter painter;
+        
+        private JSpinner clusterSizeSpinner;
+
+        public Display() throws Exception {
+            setTitle("Commons-Math: Image Clustering Example");
+            setSize(900, 350);
+            
+            setLayout(new FlowLayout());
+
+            Box bar = Box.createHorizontalBox();
+
+            referenceImage = ExampleUtils.resizeImage(
+                    ImageIO.read(new File("resources/ColorfulBird.jpg")),
+                    350,
+                    240,
+                    BufferedImage.TYPE_INT_RGB);
+
+            referenceRaster = referenceImage.getData();
+
+            clusterImage = new BufferedImage(referenceImage.getWidth(),
+                                             referenceImage.getHeight(),
+                                             BufferedImage.TYPE_INT_RGB);
+
+            JLabel picLabel = new JLabel(new ImageIcon(referenceImage));
+            bar.add(picLabel);
+
+            painter = new ImagePainter(clusterImage.getWidth(), 
clusterImage.getHeight());
+            bar.add(painter);
+
+            JPanel controlBox = new JPanel();
+            controlBox.setLayout(new GridLayout(5, 1));
+            controlBox.setBorder(BorderFactory.createLineBorder(Color.black, 
1));
+            
+            JPanel sizeBox = new JPanel();
+            JLabel sizeLabel = new JLabel("Clusters:");
+            sizeBox.add(sizeLabel);
+            
+            SpinnerNumberModel model = new SpinnerNumberModel(3, 2, 10, 1);
+            clusterSizeSpinner = new JSpinner(model);
+            
+            sizeLabel.setLabelFor(clusterSizeSpinner);
+            sizeBox.add(clusterSizeSpinner);
+            controlBox.add(sizeBox, BorderLayout.NORTH);
+
+            JButton startButton = new JButton("Cluster");
+            startButton.setActionCommand("cluster");
+            controlBox.add(startButton, BorderLayout.CENTER);
+
+            bar.add(controlBox);
+
+            add(bar);
+
+            startButton.addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    clusterImage();
+                }
+            });
+        }
+        
+        private void clusterImage() {
+            List<PixelClusterable> pixels = new ArrayList<PixelClusterable>();
+            for (int row = 0; row < referenceImage.getHeight(); row++) {
+                for (int col = 0; col < referenceImage.getWidth(); col++) {
+                    pixels.add(new PixelClusterable(col, row));
+                }
+            }
+            
+            int clusterSize = ((Number) 
clusterSizeSpinner.getValue()).intValue();
+            KMeansPlusPlusClusterer<PixelClusterable> clusterer =
+                    new KMeansPlusPlusClusterer<PixelClusterable>(clusterSize);
+            List<CentroidCluster<PixelClusterable>> clusters = 
clusterer.cluster(pixels);
+            
+            WritableRaster raster = clusterImage.getRaster();
+            for (CentroidCluster<PixelClusterable> cluster : clusters) {
+                double[] color = cluster.getCenter().getPoint();
+                for (PixelClusterable pixel : cluster.getPoints()) {
+                    raster.setPixel(pixel.x, pixel.y, color);
+                }
+            }
+            
+            Display.this.repaint();
+        }
+
+        private class PixelClusterable implements Clusterable {
+            
+            private final int x;
+            private final int y;
+            private double[] color;
+            
+            public PixelClusterable(int x, int y) {
+                this.x = x;
+                this.y = y;
+                this.color = null;
+            }
+
+            @Override
+            public double[] getPoint() {
+                if (color == null) {
+                    color = referenceRaster.getPixel(x, y, (double[]) null);
+                }
+                return color;
+            }
+
+        }
+
+        private class ImagePainter extends Component {
+            
+            private int width;
+            private int height;
+
+            public ImagePainter(int width, int height) {
+                this.width = width;
+                this.height = height;
+            }
+
+            public Dimension getPreferredSize() {
+                return new Dimension(width, height);
+            }
+
+            @Override
+            public Dimension getMinimumSize() {
+                return getPreferredSize();
+            }
+
+            @Override
+            public Dimension getMaximumSize() {
+                return getPreferredSize();
+            }
+
+            public void paint(Graphics g) {
+                g.drawImage(clusterImage, 0, 0, this);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        ExampleUtils.showExampleFrame(new Display());
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/f0943a72/src/userguide/resources/ColorfulBird.jpg
----------------------------------------------------------------------
diff --git a/src/userguide/resources/ColorfulBird.jpg 
b/src/userguide/resources/ColorfulBird.jpg
new file mode 100644
index 0000000..5753596
Binary files /dev/null and b/src/userguide/resources/ColorfulBird.jpg differ

http://git-wip-us.apache.org/repos/asf/commons-math/blob/f0943a72/src/userguide/resources/references.txt
----------------------------------------------------------------------
diff --git a/src/userguide/resources/references.txt 
b/src/userguide/resources/references.txt
index e61925f..f05294b 100644
--- a/src/userguide/resources/references.txt
+++ b/src/userguide/resources/references.txt
@@ -1,2 +1,4 @@
 monalisa.png - http://commons.wikimedia.org/wiki/File:Mona_Lisa.jpg
-the image is public domain in the United States, and those countries with a 
copyright term of life of the author plus 100 years or less.
\ No newline at end of file
+the image is public domain in the United States, and those countries with a 
copyright term of life of the author plus 100 years or less.
+
+ColorfulBird.jpg - 
http://www.wall321.com/Animals/Birds/colorful_birds_tropical_head_3888x2558_wallpaper_6566
\ No newline at end of file

Reply via email to