changeset 103:befe5e58f30f

Refactoring, added and improved JavaDoc, fix some minor issues.
author Pavel Tisnovsky <ptisnovs@redhat.com>
date Tue, 01 Oct 2013 09:35:08 +0200
parents 18a11b9d62ea
children 3100f7de547b
files ChangeLog src/org/thermostat/qa/framework/ImageProcessing.java test.properties
diffstat 3 files changed, 95 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Sep 30 10:22:07 2013 +0200
+++ b/ChangeLog	Tue Oct 01 09:35:08 2013 +0200
@@ -1,3 +1,8 @@
+2013-10-01  Pavel Tisnovsky  <ptisnovs@redhat.com>
+
+	* src/org/thermostat/qa/framework/ImageProcessing.java:
+	Refactoring, added and improved JavaDoc, fix some minor issues.
+
 2013-09-30  Pavel Tisnovsky  <ptisnovs@redhat.com>
 
 	* src/org/thermostat/qa/framework/ThermostatTest.java:
--- a/src/org/thermostat/qa/framework/ImageProcessing.java	Mon Sep 30 10:22:07 2013 +0200
+++ b/src/org/thermostat/qa/framework/ImageProcessing.java	Tue Oct 01 09:35:08 2013 +0200
@@ -35,6 +35,14 @@
 import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
 
+
+
+/**
+ * This class contains methods for checking if some input image contains given
+ * pattern. Current algorithm can be used for sRGB images.
+ * 
+ * @author Pavel Tisnovsky
+ */
 public class ImageProcessing {
 
     /**
@@ -45,24 +53,28 @@
 
     /**
      * Create three-dimensional array with the same size as tested image
-     * dimensions (last dimension is used for storing RGB components).
+     * dimensions (the last dimension is used for storing RGB components).
      * 
      * @param testImage
      *            tested image
      * @return newly created two-dimensional array
      */
-    private static float[][][] createArrayForOneColorComponent(BufferedImage testImage)
+    private static float[][][] createArrayForAllColorComponents(BufferedImage testImage)
     {
         return new float[testImage.getHeight()][testImage.getWidth()][3];
     }
 
     /**
-     * Conversion from BufferedImage into three dimensional float arrays.
-     * It's much faster to work with float arrays even if it's memory inefficient.
-     *
+     * Perform conversion from BufferedImage into three dimensional float
+     * arrays. It's much faster to work with float arrays on current CPUs even
+     * if it's memory inefficient. Pixels in the float array are stored with
+     * offset=average_value. This means, that value of color components might
+     * be negative. 
+     * 
      * @param testImage
      *            tested image
-     * @param array array to fill
+     * @param array
+     *            array to fill
      */
     private static void convertImageToFloatArray(BufferedImage testImage, float[][][] array)
     {
@@ -73,6 +85,7 @@
         {
             for (int x = 0; x < testImage.getWidth(); x++)
             {
+                // get the RGBA values packed in one integer
                 int c = testImage.getRGB(x, y);
                 // filter out alpha channel
                 c = c & 0xffffff;
@@ -93,6 +106,7 @@
         {
             for (int x = 0; x < testImage.getWidth(); x++)
             {
+                // get the RGBA values packed in one integer
                 int c = testImage.getRGB(x, y);
                 // filter out alpha channel
                 c = c & 0xffffff;
@@ -103,57 +117,83 @@
         }
     }
 
-    public static Rectangle findPattern(BufferedImage marker, BufferedImage screen){
-        Rectangle actionArea = new Rectangle(0,0,screen.getWidth(),screen.getHeight());
-        Rectangle result = new Rectangle(0,0,0,0);
+    /**
+     * Tries to find given pattern in an input image. Only the exact pattern
+     * could be found by this method.
+     * 
+     * @param pattern
+     *            given pattern stored represented as BufferedImage
+     * @param inputImage
+     *            input image
+     * @return rectangle containing area where the pattern has been found, or
+     *         null
+     */
+    public static Rectangle findPattern(BufferedImage pattern, BufferedImage inputImage){
+        Rectangle actionArea = new Rectangle(0, 0, inputImage.getWidth(), inputImage.getHeight());
+        Rectangle result = new Rectangle(0, 0, 0, 0);
         boolean found = false;
         boolean ok = true;
-        
-        for(int x = actionArea.x; (x < (actionArea.x + actionArea.width - marker.getWidth()) ) && !found; x++){
-            for(int y= actionArea.y; (y < (actionArea.y + actionArea.height - marker.getHeight()) ) && !found; y++){
-                
-                for(int mx = 0; (mx < marker.getWidth()) && ok; mx++){
-                    for(int my = 0; (my < marker.getHeight()) && ok; my++){
-                        if(marker.getRGB(mx, my) != screen.getRGB(x+mx,y+my)){
+
+        PATTERN_FOUND:
+        for (int x = actionArea.x; (x < (actionArea.x + actionArea.width - pattern.getWidth())) && !found; x++)
+        {
+            for (int y = actionArea.y; (y < (actionArea.y + actionArea.height - pattern.getHeight())) && !found; y++)
+            {
+                for (int mx = 0; (mx < pattern.getWidth()) && ok; mx++)
+                {
+                    for (int my = 0; (my < pattern.getHeight()) && ok; my++)
+                    {
+                        if (pattern.getRGB(mx, my) != inputImage.getRGB(x + mx, y + my))
+                        {
                             ok = false;
                         }
                     }
                 }
-                if( ok ){
+                if (ok)
+                {
                     found = true;
                     result.x = x;
                     result.y = y;
-                    result.height = marker.getHeight();
-                    result.width = marker.getWidth();
-                }else{
-                    ok = true;
-                }                
+                    result.height = pattern.getHeight();
+                    result.width = pattern.getWidth();
+                    break PATTERN_FOUND;
+                }
+                ok = true;
             }
         }
-        
-        if(found){
-            return result;
-        }else{
-            return null;
-        }
+
+        // if the pattern has not been found, return null instead of the proper rectangle
+        return found ? result : null;
     }
 
-    private static Rectangle findBlurredPattern(BufferedImage marker, BufferedImage testImage)
+    /**
+     * Tries to find given pattern in an input image.
+     * 
+     * @param pattern
+     *            given pattern stored represented as BufferedImage
+     * @param inputImage
+     *            input image
+     * @return rectangle containing area where the pattern have been found, or
+     *         null
+     */
+    protected static Rectangle findBlurredPattern(BufferedImage pattern, BufferedImage inputImage)
     {
-        int maxX = testImage.getWidth() - marker.getWidth() - 1;
-        int maxY = testImage.getHeight() - marker.getHeight() - 1;
-        int markerMaxX = marker.getWidth();
-        int markerMaxY = marker.getHeight();
+        int maxX = inputImage.getWidth() - pattern.getWidth() - 1;
+        int maxY = inputImage.getHeight() - pattern.getHeight() - 1;
+        int markerMaxX = pattern.getWidth();
+        int markerMaxY = pattern.getHeight();
 
         // it is much faster to work directly with color components stored as float values
-        float[][][] testImageArray = createArrayForOneColorComponent(testImage);
-        float[][][] markerImageArray = createArrayForOneColorComponent(marker);
+        float[][][] testImageArray = createArrayForAllColorComponents(inputImage);
+        float[][][] markerImageArray = createArrayForAllColorComponents(pattern);
 
         //System.out.println("Starting conversion");
-        convertImageToFloatArray(testImage, testImageArray);
-        convertImageToFloatArray(marker, markerImageArray);
+        convertImageToFloatArray(inputImage, testImageArray);
+        convertImageToFloatArray(pattern, markerImageArray);
         //System.out.println("Conversion done");
 
+        // autocorellation value is needed to compute and compare correlation values
+        // and to find the exact pattern (if it exists in the input image)
         double autocorrelation = computeCorrelation(markerMaxX, markerMaxY, markerImageArray, markerImageArray, 0, 0);
 
         int bestX = -1;
@@ -166,7 +206,7 @@
             //System.out.println("Processing line: " + yoffset + " of " + (maxY - 1));
             for (int xoffset = 0; (xoffset < maxX) && !foundExact; xoffset++)
             {
-                double correlation = computeCorrelation(markerMaxX, markerMaxY, testImageArray, markerImageArray, yoffset, xoffset);
+                double correlation = computeCorrelation(markerMaxX, markerMaxY, testImageArray, markerImageArray, xoffset, yoffset);
                 if (correlation > bestCorrelation)
                 {
                     bestCorrelation = correlation;
@@ -187,22 +227,27 @@
         {
             return null;
         }
-        return new Rectangle(bestX, bestY, marker.getWidth(), marker.getHeight());
+        // pattern has been found!
+        return new Rectangle(bestX, bestY, pattern.getWidth(), pattern.getHeight());
     }
 
     /**
-     * Compute correlation for given two images and 2D offset.
-     *
+     * Compute correlation for given two images and a 2D offset.
+     * 
      * @param maxX
      * @param maxY
      * @param testImageArray
+     *            first input array
      * @param markerImageArray
+     *            second input array
+     * @param xoffset
+     *            horizontal part of an offset
      * @param yoffset
-     * @param xoffset
-     * @return
+     *            vertical part of an offset
+     * @return correlation of two arrays with the given offset
      */
     private static double computeCorrelation(int maxX, int maxY, float[][][] testImageArray,
-                    float[][][] markerImageArray, int yoffset, int xoffset)
+                    float[][][] markerImageArray, int xoffset, int yoffset)
     {
         double correlation = 0;
         for (int y = 0; y < maxY; y++)
--- a/test.properties	Mon Sep 30 10:22:07 2013 +0200
+++ b/test.properties	Tue Oct 01 09:35:08 2013 +0200
@@ -1,6 +1,6 @@
 thermostat_executable_path=/home/jfabriko/thermostaty/testing_thermostat/thermostat/distribution/target/image/bin/
 thermostat_executable_name=thermostat
-thermostat_output_version=version6-0.14.0
+thermostat_output_version=0.12.0
 thermostat_home=/home/jfabriko/thermostaty/testing_thermostat/thermostat/distribution/target/image/
 thermostat_user_home=/home/jfabriko/.thermostat/
 apache_tomcat_home=/home/jfabriko/thermostaty/apache-tomcat-7.0.42/