Package jjil.algorithm

Source Code of jjil.algorithm.Gray8UnsignedBackgroundSubtract

package jjil.algorithm;

import jjil.core.Error;
import jjil.core.Gray32Image;
import jjil.core.Gray8Image;
import jjil.core.Image;
import jjil.core.PipelineStage;

/**
* Compensates for uneven background illumination in an input image,
* at the same time changing an unsigned byte image to a signed
* byte image, which is the type used through JJIL. Unsigned byte
* images are supplied by, e.g., the Google G1 phone when operating
* in preview mode.
* @author webb
*
*/
public class Gray8UnsignedBackgroundSubtract extends PipelineStage {
  Gray32Image mg32 = null;
  int mnHeight;
  int mnWidth;
 
  /**
   * Set the width and height of the window used for averaging when computing
   * the background illumination.
   * @param nWidth width to average over
   */
  public Gray8UnsignedBackgroundSubtract(int nWidth, int nHeight) {
    this.mnWidth = nWidth;
    this.mnHeight = nHeight;
  }

  /**
   * Compute an output Gray8Image which is the difference of the input
   * unsigned Gray8Image and an average of a window of width x height
   * size of the input. This is done using a cumulative sum operation
   * so the operation is done efficiently.
   */
  public void push(Image imageInput) throws Error {
        if (!(imageInput instanceof Gray8Image)) {
            throw new Error(
                    Error.PACKAGE.ALGORITHM,
                    ErrorCodes.IMAGE_NOT_GRAY8IMAGE,
                    imageInput.toString(),
                    null,
                    null);
        }
        if (this.mnWidth > imageInput.getWidth() ||
            this.mnHeight > imageInput.getHeight()) {
            throw new Error(
            Error.PACKAGE.ALGORITHM,
            ErrorCodes.PARAMETER_OUT_OF_RANGE,
            imageInput.toString(),
            Integer.toString(this.mnWidth),
            Integer.toString(this.mnHeight));
        }
        // if the image size is changed or this is the first time
        // allocate the intermediate Gray32Image.
        if (this.mg32 == null ||
            !this.mg32.getSize().equals(imageInput.getSize())) {
          this.mg32 = new Gray32Image(
              imageInput.getWidth(), imageInput.getHeight());
        }
        Gray8Image gray = (Gray8Image) imageInput;
        byte[] grayData = gray.getData();
        int[] gray32Data = this.mg32.getData();
        // First row
        int nSum = 0;
        for (int j=0; j<gray.getWidth(); j++) {
            /* Store unsigned byte value into Gray32Image
             */
            int grayUnsigned = 0xff & grayData[j];
            /* Assign 32-bit output */
            nSum += grayUnsigned;
            gray32Data[j] = nSum;
        }
        // Other rows
        for (int i=1; i<gray.getHeight(); i++) {
            nSum = 0;
            for (int j=0; j<gray.getWidth(); j++) {
                /* Get unsigned byte value as an int
                 */
                int grayUnsigned = grayData[i*gray.getWidth()+j] & 0xff;
                nSum += grayUnsigned;
                gray32Data[i*gray.getWidth()+j] =
                        gray32Data[(i-1)*gray.getWidth()+j] +
                        nSum;
            }
        }
        // now compute the average value at each pixel and subtract it
        // from the input, replacing the original image
        for (int i=0; i<gray.getHeight(); i++) {
          /* nTop and nBottom are the top and bottom rows of the averaging
           * window, taking into account edge effects
           */
          int nTop, nBottom;
          if (i<this.mnHeight/2) {
            nTop = 0;
            nBottom = this.mnHeight;
          } else if (i>=gray.getHeight()-this.mnHeight/2) {
            nBottom = gray.getHeight()-1;
            nTop = nBottom - this.mnHeight;
          } else {
            nTop = i-this.mnHeight/2;
            nBottom = i+this.mnHeight/2;           
          }
          for (int j=0; j<this.mnWidth/2; j++) {
            /* nLeft and nRigth are the left and right edges of the
             * averaging window, taking into account edge effects
             */
            int nLeft = 0;
            int nRight = this.mnWidth;
            // compute the sum of the averaging window using the cumulative
            // sum array
            nSum = gray32Data[nBottom*gray.getWidth()+nRight] -
              gray32Data[nTop*gray.getWidth()+nLeft];
            // compute the difference between this pixel and the averaged
            // value
            grayData[i*gray.getWidth()+j] =
              (byte) ((grayData[i*gray.getWidth()+j] & 0xff) -
                  nSum / (this.mnWidth * this.mnHeight));
          }
          for (int j=this.mnWidth/2; j<gray.getWidth()-this.mnWidth/2; j++) {
            /* nLeft and nRigth are the left and right edges of the
             * averaging window, taking into account edge effects
             */
            int nLeft = j-this.mnWidth/2;
            int nRight = j + this.mnWidth/2;
            // compute the sum of the averaging window using the cumulative
            // sum array
            nSum = gray32Data[nBottom*gray.getWidth()+nRight] -
              gray32Data[nTop*gray.getWidth()+nLeft];
            // compute the difference between this pixel and the averaged
            // value
            grayData[i*gray.getWidth()+j] =
              (byte) ((grayData[i*gray.getWidth()+j] & 0xff) -
                  nSum / (this.mnWidth * this.mnHeight));
          }
          for (int j=gray.getWidth()-this.mnWidth/2; j<gray.getWidth(); j++) {
            /* nLeft and nRigth are the left and right edges of the
             * averaging window, taking into account edge effects
             */
            int nRight = gray.getWidth()-1;
            int nLeft = nRight-this.mnWidth;
            // compute the sum of the averaging window using the cumulative
            // sum array
            nSum = gray32Data[nBottom*gray.getWidth()+nRight] -
              gray32Data[nTop*gray.getWidth()+nLeft];
            // compute the difference between this pixel and the averaged
            // value
            grayData[i*gray.getWidth()+j] =
              (byte) ((grayData[i*gray.getWidth()+j] & 0xff) -
                  nSum / (this.mnWidth * this.mnHeight));
          }
        }
        // output result
        super.setOutput(gray);
  }

}
TOP

Related Classes of jjil.algorithm.Gray8UnsignedBackgroundSubtract

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.