org.uva.itast.blended.omr.BufferedImageUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.uva.itast.blended.omr.BufferedImageUtil.java

Source

/*
 * ====================================================================
 *
 * License:        GNU General Public License
 *
 * Note: Original work copyright to respective authors
 *
 * This file is part of Blended (c) 2009-2010 University of Valladolid..
 *
 * Blended is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * Blended is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *
 * Module developed at the University of Valladolid http://www.eduvalab.uva.es
 *
 * http://www.itnt.uva.es , http://www.eduvalab.uva.es
 *
 * Designed and directed by Juan Pablo de Castro with 
 * the effort of many other students of telecommunication 
 * engineering.
 * This module is provides as-is without any 
 * guarantee. Use it as your own risk.
 *
 * @author Juan Pablo de Castro
 * @author Jesus Rodilana
 * @author Mara Jess Verd 
 * @author Luisa Regueras 
 * @author Elena Verd
 * 
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package blended
 ***********************************************************************/

/***********************************************************************
 * Module developed at the University of Valladolid http://www.eduvalab.uva.es
 * Designed and directed by Juan Pablo de Castro with 
 * the effort of many other students of telecommunciation 
 * engineering this module is provides as-is without any 
 * guarantee. Use it as your own risk.
 *
 * @author Juan Pablo de Castro and Miguel Baraja Campesino and many others.
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package blended
 ***********************************************************************/

package org.uva.itast.blended.omr;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.uva.itast.blended.omr.pages.SubImage;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.NotFoundException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;

public class BufferedImageUtil {

    /**
     * Logger for this class
     */
    private static final Log logger = LogFactory.getLog(BufferedImageUtil.class);

    /**
     * 
     * @param img
     * @param x
     * @param y
     * @param template
     * @param dump
     * @return ratio of pixels differences between template and image
     */
    public static double templateXOR(BufferedImage img, int x, int y, BufferedImage template, boolean dump) {
        int diff = 0, total = 0;
        if (y < 0) {
            logger.debug("coordinate in XOR template should not be <0: y=" + y);
            y = 0;
        }
        if (x < 0) {
            logger.debug("coordinate in XOR template should not be <0: x=" + x);
            x = 0;
        }
        int templateHeight = template.getHeight();
        int templateWidth = template.getWidth();
        int imgHeight = img.getHeight();
        int imgWidth = img.getWidth();
        if (dump && logger.isDebugEnabled()) {
            logger.debug(
                    "templateXOR - Testing XOR Width=" + templateWidth + "from upper-left x=" + x + ", y=" + y); //$NON-NLS-1$ //$NON-NLS-2$

            for (int j = y; j < y + templateHeight && j < imgHeight; j++) {
                for (int i = x; i < x + templateWidth && i < imgWidth; i++) {
                    float luminance = getLuminance(img, j, i);
                    boolean isblack = (luminance < 0.75 ? true : false);
                    boolean tempIsBlack = isBlack(template, j - y, i - x);
                    System.out.print(isblack ? "*" : (tempIsBlack ? "O" : "_"));
                }
                System.out.println("<-");
            }
        } // end debug

        for (int j = y; j < y + templateHeight && j < imgHeight; j++) {
            for (int i = x; i < x + templateWidth && i < imgWidth; i++) {
                float luminance = getLuminance(img, j, i);
                boolean isblack = (luminance < 0.75 ? true : false);
                boolean templateIsWhite = isWhite(template, j - y, i - x);
                boolean templateIsBlack = isBlack(template, j - y, i - x);

                if ((isblack & templateIsWhite) | ((!isblack) & templateIsBlack)) {
                    diff++;
                }
                total++;
            }

        }
        if (dump && logger.isDebugEnabled()) {
            logger.debug("templateXOR- Diffs=" + diff + " out of " + total); //$NON-NLS-1$ //$NON-NLS-2$
        }
        return ((double) diff) / total;
    }

    /**
     * 
     * @param img
     * @param x
     * @param y
     * @param template
     * @param dump
     * @return ratio of pixels differences between template and image
     */
    public static double templateCoincidences(BufferedImage img, int x, int y, BufferedImage template,
            boolean dump) {
        int matches = 0, total = 0;
        if (y < 0) {
            logger.warn("coordinate in XOR template should not be <0: y=" + y);
            y = 0;
        }
        if (x < 0) {
            logger.warn("coordinate in XOR template should not be <0: x=" + x);
            x = 0;
        }
        int templateHeight = template.getHeight();
        int templateWidth = template.getWidth();
        int imgHeight = img.getHeight();
        int imgWidth = img.getWidth();
        if (dump && logger.isDebugEnabled()) {
            logger.debug(
                    "templateXOR - Testing XOR Width=" + templateWidth + "from upper-left x=" + x + ", y=" + y); //$NON-NLS-1$ //$NON-NLS-2$

            for (int j = y; j < y + templateHeight && j < imgHeight; j++) {
                for (int i = x; i < x + templateWidth && i < imgWidth; i++) {
                    float luminance = getLuminance(img, j, i);
                    boolean isblack = (luminance < 0.75 ? true : false);
                    boolean tempIsBlack = isBlack(template, j - y, i - x);
                    System.out.print(isblack ? "*" : (tempIsBlack ? "O" : "_"));
                }
                System.out.println("<-");
            }
        } // end debug

        for (int j = y; j < y + templateHeight && j < imgHeight; j++) {
            for (int i = x; i < x + templateWidth && i < imgWidth; i++) {

                boolean templateIsWhite = isWhite(template, j - y, i - x);
                boolean templateIsBlack = isBlack(template, j - y, i - x);
                float luminance = getLuminance(img, j, i);
                boolean isblack = (luminance < 0.75 ? true : false);

                if (templateIsBlack && isblack) // find pixels matches
                {
                    matches++;
                }
                total++;
            }

        }
        if (dump && logger.isDebugEnabled()) {
            logger.debug("templateXOR- Coincidences=" + matches + " out of " + total); //$NON-NLS-1$ //$NON-NLS-2$
        }
        return ((double) matches) / total;
    }

    /**
     * Determina si un determinado pxel es blanco o no
     * 
     * @param template
     * @param j
     * @param i
     * @return
     */
    private static boolean isWhite(BufferedImage template, int j, int i) {
        return (template.getRGB(i, j) == Color.WHITE.getRGB() ? true : false);
    }

    /**
     * Determina si un determinado pxel es negro o no
     * 
     * @param template
     * @param j
     * @param i
     * @return
     */
    private static boolean isBlack(BufferedImage template, int j, int i) {
        return (template.getRGB(i, j) == Color.BLACK.getRGB() ? true : false);
    }

    /**
     * Estimates the mean luminance of a subimage
     * 
     * @param img
     * @param downsampling
     * @return array meanluminance,minlum,maxlum
     */
    public static float[] statsLuminance(SubImage img, int downsampling) {
        float luminanceSum = 0;
        float min = 1;
        float max = 0;
        Rectangle captured = img.getCapturedBoundingBox();
        Rectangle represented = img.getBoundingBox();
        Point reference = img.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);
        int pixels = 0;
        float luminance;
        for (int y = ystart; y < ystart + captured.height; y += downsampling)
            for (int x = xstart; x < xstart + captured.width; x += downsampling) {
                luminance = getLuminance(img, y, x);
                luminanceSum += luminance;
                min = Math.min(min, luminance);
                min = Math.min(min, luminance);
                max = Math.max(max, luminance);
                pixels++;
            }
        return new float[] { luminanceSum / pixels, min, max };
    }

    /**
     * Obtiene la luminancia de un pixel
     * 
     * @param img
     * @param j
     * @param i
     * @return
     */
    public static float getLuminance(BufferedImage img, int j, int i) {

        int rgb = img.getRGB(i, j);
        float red = ((rgb & 0xff0000) >> 16) / 255.f;
        float green = ((rgb & 0xff00) >> 8) / 255.f;
        float blue = (rgb & 0xff) / 255.f;
        float luminance = (float) ((.299 * red) + (.587 * green) + (.114 * blue));
        return luminance;

    }

    /**
     * Dibuja de una marca de color blanco o negro en un BufferedImage
     * 
     * @param img
     * @param x
     * @param y
     * @param color
     */
    public static void putMarkBufferedImage(BufferedImage img, int x, int y, boolean color) {
        if (color) {
            img.setRGB(x, y, Color.BLACK.getRGB());
            img.setRGB(x + 1, y + 1, Color.BLACK.getRGB());
            img.setRGB(x - 1, y - 1, Color.BLACK.getRGB());
            img.setRGB(x + 1, y, Color.BLACK.getRGB());
            img.setRGB(x - 1, y, Color.BLACK.getRGB());
            img.setRGB(x, y + 1, Color.BLACK.getRGB());
            img.setRGB(x, y - 1, Color.BLACK.getRGB());
            img.setRGB(x + 1, y - 1, Color.BLACK.getRGB());
            img.setRGB(x - 1, y + 1, Color.BLACK.getRGB());
            img.setRGB(x - 1, y - 1, Color.BLACK.getRGB());
        } else {
            img.setRGB(x, y, Color.WHITE.getRGB());
            img.setRGB(x + 1, y + 1, Color.WHITE.getRGB());
            img.setRGB(x - 1, y - 1, Color.WHITE.getRGB());
            img.setRGB(x + 1, y, Color.WHITE.getRGB());
            img.setRGB(x - 1, y, Color.WHITE.getRGB());
            img.setRGB(x, y + 1, Color.WHITE.getRGB());
            img.setRGB(x, y - 1, Color.WHITE.getRGB());
            img.setRGB(x + 1, y - 1, Color.WHITE.getRGB());
            img.setRGB(x - 1, y + 1, Color.WHITE.getRGB());
            img.setRGB(x - 1, y - 1, Color.WHITE.getRGB());
        }

    }

    /**
     * Makes a 2Dbinarization withZXING library
     * @param img
     */
    public static void binarizeWithZxing(SubImage subImage) {
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(subImage);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        //      BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));

        // copy results in subImage
        Rectangle captured = subImage.getCapturedBoundingBox();
        Point reference = subImage.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);

        BitMatrix blackMatrix;
        try {
            blackMatrix = bitmap.getBlackMatrix();
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        }

        for (int y = ystart; y < ystart + captured.height; y++)
            for (int x = xstart; x < xstart + captured.width; x++) {
                if (blackMatrix.get(x, y))
                    subImage.setRGB(x, y, 0xff000000);
                else
                    subImage.setRGB(x, y, 0xffffffff);
            }

        //      try
        //      {
        //         File testPath=File.createTempFile("Xzing", "png",OMRUtils.getDebugOutputPath(omr));
        //         if (logger.isDebugEnabled())
        //            OMRUtils.dumpBlackPoint(testPath.toURI(), subImage, bitmap);   
        //      }
        //      catch (IOException e)
        //      {
        //         // TODO Auto-generated catch block
        //         e.printStackTrace();
        //      }
    }

    /**
     * 
     * @param img
     * @param f
     */
    public static void threshold(SubImage img, float f) {
        Rectangle captured = img.getCapturedBoundingBox();
        Point reference = img.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);

        float luminance;
        for (int y = ystart; y < ystart + captured.height; y++)
            for (int x = xstart; x < xstart + captured.width; x++) {
                luminance = getLuminance(img, y, x);
                if (luminance > f)
                    img.setRGB(x, y, 0xffffff);
                else
                    img.setRGB(x, y, 0x000000);
            }
    }

    public static void thresholdAndInvert(SubImage img, float f) {
        Rectangle captured = img.getCapturedBoundingBox();
        Point reference = img.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);

        float luminance;
        for (int y = ystart; y < ystart + captured.height; y++)
            for (int x = xstart; x < xstart + captured.width; x++) {
                luminance = getLuminance(img, y, x);
                if (luminance < f)
                    img.setRGB(x, y, 0xffffff);
                else
                    img.setRGB(x, y, 0x000000);
            }
    }

    public static void invert(SubImage img) {
        Rectangle captured = img.getCapturedBoundingBox();
        Point reference = img.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);

        for (int y = ystart; y < ystart + captured.height; y++)
            for (int x = xstart; x < xstart + captured.width; x++) {
                img.setRGB(x, y, 0xffffff - img.getRGB(x, y));
            }
    }

    public static void scale(SubImage img, float ratio) {
        Rectangle captured = img.getCapturedBoundingBox();
        Point reference = img.getReference();
        int xstart = Math.max(captured.x - reference.x, 0);
        int ystart = Math.max(captured.y - reference.y, 0);

        for (int y = ystart; y < ystart + captured.height; y++)
            for (int x = xstart; x < xstart + captured.width; x++) {
                img.setRGB(x, y, (int) (ratio * img.getRGB(x, y)));
            }
    }

    /**
     * Rotates 90, -90 deegrees
     * @param imageToRotate
     * @param degrees 90 or -90 rotation.
     * @return
     */
    public static BufferedImage rotateImage(BufferedImage imageToRotate, float degrees) {
        if (degrees != 90.0 && degrees != -90.0)
            throw new IllegalArgumentException("Only implemented +90 and -90 rotation");

        BufferedImage rotatedImage = new BufferedImage(imageToRotate.getHeight(null), imageToRotate.getWidth(null),
                imageToRotate.getType());

        Graphics2D g2d = (Graphics2D) rotatedImage.getGraphics();
        g2d.rotate(Math.toRadians(degrees));
        g2d.drawImage(imageToRotate, 0, -rotatedImage.getWidth(null), null);

        return rotatedImage;
    }

}