Here you can find the source of fuzzyCompare(final BufferedImage img1, final BufferedImage img2, final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension)
Parameter | Description |
---|---|
img1 | The first image for the comparison |
img2 | The second image for the comparison |
colorTolerance | A threshold value that calculates the allowed difference in color between two pixels [0-1[ |
pixelTolerance | A threshold value that calculates the allowed number of different pixels per block [0-1[ |
fuzzyBlockDimension | The x and y dimension d of one block of pixels(d*d), which are validated together |
protected static Point[] fuzzyCompare(final BufferedImage img1, final BufferedImage img2, final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension)
//package com.java2s; //License from project: Open Source License import java.awt.Point; import java.awt.image.BufferedImage; import java.util.ArrayList; public class Main { /**/* w w w . j ava 2s. c o m*/ * Compares two images by partitioning them into blocks and checking the number of different pixels * in each block. Therefore the difference in color with the given color threshold is calculated. * If the number of pixels that are found as different in one block exceeds a number threshold the images * are treated as differently and the pixel coordinates are saved as Point objects. * * @param img1 * The first image for the comparison * @param img2 * The second image for the comparison * @param colorTolerance A threshold value that calculates the allowed difference in color between two pixels [0-1[ * @param pixelTolerance A threshold value that calculates the allowed number of different pixels per block [0-1[ * @param fuzzyBlockDimension The x and y dimension d of one block of pixels(d*d), which are validated together * @return Point[] array that contains the coordinates of pixels that are different */ protected static Point[] fuzzyCompare(final BufferedImage img1, final BufferedImage img2, final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension) { final ArrayList<Point> pixels = new ArrayList<>(); // Calculate the number of blocks for each axis final int horizontalBlockCount = img1.getWidth() / fuzzyBlockDimension; final int verticalBlockCount = img1.getHeight() / fuzzyBlockDimension; // For each block for (int x = 0; x < horizontalBlockCount; x++) { for (int y = 0; y < verticalBlockCount; y++) { final ArrayList<Point> tempCoordinates = new ArrayList<>(); final int horizontalBlockWidth = calcBlockLength(fuzzyBlockDimension, x, img1.getWidth()); final int verticalBlockHeight = calcBlockLength(fuzzyBlockDimension, y, img1.getHeight()); final int differencesAllowed = (int) Math .floor(horizontalBlockWidth * verticalBlockHeight * pixelTolerance); int differencesPerBlock = 0; // For each pixel in this block, check for differences for (int w = 0; w < horizontalBlockWidth; w++) { for (int h = 0; h < verticalBlockHeight; h++) { final int xCoord = x * fuzzyBlockDimension + w; final int yCoord = y * fuzzyBlockDimension + h; // calculate the difference and draw the differenceImage // if needed final double difference = calculatePixelRGBDiff(img1.getRGB(xCoord, yCoord), img2.getRGB(xCoord, yCoord)); // If there is a notable difference if (difference > colorTolerance) { // Increment differencesPerBlock and add the // coordinates to the // temporary arraylists differencesPerBlock++; tempCoordinates.add(new Point(xCoord, yCoord)); } } } // If the number of differences exceeds the threshold, save the coordinates of the pixels // that are different if (differencesPerBlock > differencesAllowed) { pixels.addAll(tempCoordinates); } // clear the temporary coordinates tempCoordinates.clear(); } } return pixels.toArray(new Point[pixels.size()]); } /** * Calculates whether the current block exceeds either the x or y coordinates of the image. * Checks one axis of the image at a time. * * @param axisPixelCount * The number of pixels in this block for axis that should be checked * @param n * index of the current block * @param imageSpan * the width/ height of the image * @return The number of pixels that can be used for the mask either in the x or y axis */ protected static int calcBlockLength(final int axisPixelCount, final int n, final int imageSpan) { if (axisPixelCount * (n + 1) > imageSpan) { return imageSpan % axisPixelCount; } return axisPixelCount; } /** * The method weights the red, green and blue values and determines the difference as humans would see it. Based on * a comparison algorithm from http://www.compuphase.com/cmetric.htm . The algorithm is based on experiments with * people, not theoretics. It is thereby not certain. * * @param rgb1 * color number 1 * @param rgb2 * color number 2 * @return the difference between the colors as percent from 0.0 to 1.0 */ protected static double calculatePixelRGBDiff(final int rgb1, final int rgb2) { final double MAX = 721.2489168102785; // Initialize the red, green, blue values final int r1 = (rgb1 >> 16) & 0xFF; final int g1 = (rgb1 >> 8) & 0xFF; final int b1 = rgb1 & 0xFF; final int r2 = (rgb2 >> 16) & 0xFF; final int g2 = (rgb2 >> 8) & 0xFF; final int b2 = rgb2 & 0xFF; final int rDiff = r1 - r2; final int gDiff = g1 - g2; final int bDiff = b1 - b2; // Initialize the weight parameters final int rLevel = (r1 + r2) / 2; final double rWeight = 2 + rLevel / 256; final double gWeight = 4.0; final double bWeight = 2 + ((255 - rLevel) / 256); final double cDiff = Math.sqrt(rWeight * rDiff * rDiff + gWeight * gDiff * gDiff + bWeight * bDiff * bDiff); return cDiff / MAX; } }