Java BufferedImage Operation fuzzyCompare(final BufferedImage img1, final BufferedImage img2, final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension)

Here you can find the source of fuzzyCompare(final BufferedImage img1, final BufferedImage img2, final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension)

Description

Compares two images by partitioning them into blocks and checking the number of different pixels in each block.

License

Open Source License

Parameter

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

Return

Point[] array that contains the coordinates of pixels that are different

Declaration

protected static Point[] fuzzyCompare(final BufferedImage img1, final BufferedImage img2,
        final double colorTolerance, final double pixelTolerance, final int fuzzyBlockDimension) 

Method Source Code

//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;
    }
}

Related

  1. findLegendLH(BufferedImage bufferedImage)
  2. findTranslation(AffineTransform at, BufferedImage bi)
  3. fixImage(BufferedImage img, String ext)
  4. floatBufferToGrayBufferedImage(FloatBuffer floatBuffer, BufferedImage bi)
  5. floodFill(BufferedImage img, int startX, int startY, Color targetColor, Color replacementColor)
  6. fuzzyEquals(BufferedImage a, BufferedImage b, int threshold)
  7. genBlackAndWhiteImage(BufferedImage image)
  8. generate(int w, int h, BufferedImage img)
  9. generateBufferedImageFromComponent(Component component)