Package jjil.algorithm

Source Code of jjil.algorithm.MaskedGray8SubImgGen

/*
* MaskedGray8SubImgGen.java
*
* Given a target image size and a horizontal and vertical offset
* generates a series of subimages within the input image,
* each subimage offset by an integral multiple of the
* offset with size equal to the target size and lying
* entirely within the original image. The offset of the
* subimage in the input image is given in the subimage class.
* In this masked version only subimages whose center is not a masked
* point (mask image value = 0) will be generated.
*
* Created on July 1, 2007, 1:51 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*
* Copyright 2007 by Jon A. Webb
*     This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Lesser General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 Lesser General Public License for more details.
*
*    You should have received a copy of the Lesser GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/

package jjil.algorithm;
import jjil.core.Error;
import jjil.core.Gray8MaskedImage;
import jjil.core.Gray8OffsetImage;
import jjil.core.Image;
import jjil.core.PipelineStage;

/**
* Generates subimages from a source Gray8Image, using a mask. In a normal
* subimage generator subimages are generated evenly spaced across the input
* image. Here, the subimage is generated only if is center point is not masked.
* This can increase processing speed in hierarchical detection operations since features
* detected at coarser resolution don't have to be redetected at finer resolution.
* @author webb
*/
public class MaskedGray8SubImgGen extends PipelineStage {
    Gray8MaskedImage imageInput;  // input image
    boolean oSubImageReady; // true if sub image position is OK
    int nHeight;            // target height
    int nHorizLimit = 0;    // number of subimages generated horizontally
    int nVertLimit = 0;     // number of subimages generated vertically
    int nHorizIndex = 0;    // current subimiage index, horizontal
    int nVertIndex = 0;     // current subimage index, vertical
    int nWidth;             // target width
    int nXOffset;           // x offset multiple for subimages
    int nYOffset;           // y offset multiple for subimages
   
    /**
     * Creates a new instance of MaskedGray8SubImgGen.
     * @param nWidth the width of the generated subimage.
     * @param nHeight the height of the generated subimage.
     * @param nXOffset the horizontal offset between subimages.
     * @param nYOffset the vertical offset between subimages.
     */
    public MaskedGray8SubImgGen(int nWidth, int nHeight, int nXOffset, int nYOffset) {
        this.nWidth = nWidth;
        this.nHeight = nHeight;
        this.nXOffset = nXOffset;
        this.nYOffset = nYOffset;
        this.oSubImageReady = false;
        // create an output image. We'll reuse this
        // image, changing the contents and offset,
        // for every Gray8OffsetImage we output.
        super.imageOutput = new Gray8OffsetImage(
            this.nWidth,
            this.nHeight,
            0,
            0);
    }
   
    /** advanceToNextSubImage advances to the next position for generating
     * a subimage. It returns true iff there is a non-masked position within
     * the image where a subimage can be generated.
     */
    private boolean advanceToNextSubImage() {
        if (oSubImageReady) {
            return this.nVertIndex <= this.nVertLimit;
        }
        // advance to next subimage position
        this.nHorizIndex ++;
        if (this.nHorizIndex > this.nHorizLimit) {
            this.nVertIndex ++;
            this.nHorizIndex = 0;
        }
        // nPos is the byte address that we will test in the mask image
        // to see if it is OK to generate a subimage. It is the midpoint
        // of the subimage.
        int nPos = (this.nHeight / 2 +
                this.nVertIndex * this.nYOffset) * this.imageInput.getWidth() +
                this.nWidth / 2 + this.nHorizIndex * this.nXOffset;
        // starting at the current position, search forward for a position
        // that is not masked.
        while (this.nVertIndex <= this.nVertLimit) {
            while (this.nHorizIndex <= this.nHorizLimit) {
                if (this.imageInput.getMaskData()[nPos] == Byte.MIN_VALUE) {
                    // found it
                    oSubImageReady = true;
                    return true;
                }
                this.nHorizIndex ++;
                nPos += this.nWidth;
            }
            this.nHorizIndex = 0;
            this.nVertIndex ++;
            // reset nPos for next row of subimages
            nPos = (this.nHeight / 2 +
                this.nVertIndex * this.nYOffset) * this.imageInput.getWidth() +
                this.nWidth / 2;
        }
        this.oSubImageReady = true;
        return false;
    }
   
    // We are done producing images when the advance returns no more images
    /**
     * Returns true iff there is another image available from getFront().
     * Note that the existence of another image from
     * MaskedGray8SubImgGen depends on the mask image so there's no way to guarantee
     * there will be even one subimage generated for a particular input. You must
     * always call isEmpty().
     * @return true iff there is another image available from getFront().
     */
    public boolean isEmpty() {
        return !advanceToNextSubImage();
     }
   
    // Return the next subimage and increment the indices
    /**
     * Returns the next subimage generated. The subimage will have its offset
     * set to indicate where it was generated in the input image.
     * @return a MaskedGray8SubImage that is the next subimage in the input Gray8Image to
     * be processed.
     * @throws jjil.core.Error if no subimage is available (you have to call isEmpty() to determine if
     * a subimage is available. As few as 0 subimage can be generated for a
     * given input if the entire image is masked.) Also throws if the output
     * image (stored in the superclass) has been changed in type.
     */
     public Image getFront() throws jjil.core.Error
    {
        // reuse output image
        // check to make sure nobody damaged it somehow
        if (!(super.imageOutput instanceof Gray8OffsetImage)) {
            throw new Error(
                            Error.PACKAGE.ALGORITHM,
                            ErrorCodes.OBJECT_NOT_EXPECTED_TYPE,
                            imageOutput.toString(),
                            "Gray8SubImage",
                            null);
        }
        if (!advanceToNextSubImage()) {
            throw new Error(
                            Error.PACKAGE.ALGORITHM,
                            ErrorCodes.SUBIMAGE_NO_IMAGE_AVAILABLE,
                            this.toString(),
                            null,
                            null);
        }
       
        byte[] dataIn = this.imageInput.getData();
        // offset of first pixel of the subimage within the
        // larget image.
        int nHOffset = this.nXOffset * this.nHorizIndex;
        int nVOffset = this.nYOffset * this.nVertIndex;
        Gray8OffsetImage imageResult = (Gray8OffsetImage) super.imageOutput;
        imageResult.setXOffset(nHOffset);
        imageResult.setYOffset(nVOffset);
        byte[] dataOut = imageResult.getData();
        // don't access outside the image
        int nLimitY = Math.min(this.imageInput.getHeight() - nVOffset, this.nHeight);
        int nLimitX = Math.min(this.imageInput.getWidth() - nHOffset, this.nWidth);
        for (int i=0; i<nLimitY; i++) {
            int nVInLoc = i + nVOffset;
            System.arraycopy(
                    dataIn,
                    nVInLoc*this.imageInput.getWidth() + nHOffset,
                    dataOut,
                    i*this.nWidth,
                    nLimitX);
        }

        this.oSubImageReady = false;
        return imageResult;
    }

   
    /**
     * Accepts a new MaskedGray8Image and initializes all the generator indices.
     * @param image The input MaskedGray8Image.
     * @throws jjil.core.Error if the input is not of type MaskedGray8Image or is smaller than the
     * subimages to be generated.
     */
    public void push(Image image) throws jjil.core.Error {
        if (!(image instanceof Gray8MaskedImage)) {
            throw new Error(
                            Error.PACKAGE.ALGORITHM,
                            ErrorCodes.OBJECT_NOT_EXPECTED_TYPE,
                            image.toString(),
                            "Gray8MaskedImage",
                            null);
        }
        if (image.getWidth() < this.nWidth || image.getHeight() < this.nHeight) {
            throw new Error(
                            Error.PACKAGE.ALGORITHM,
                            ErrorCodes.IMAGE_TOO_SMALL,
                            image.toString(),
                            new Integer(this.nWidth).toString(),
                            new Integer(this.nHeight).toString());
        }
        this.imageInput = (Gray8MaskedImage) image;
        // we want to find the largest integer l such that
        // (l-1) * w + w  <= iw
        // where l = computed limit on index
        // w = subimage width or height
        // iw = image width or height
        // or l = (iw - w) / w  + 1 (truncated)
        // Java division truncates
        this.nHorizLimit = (image.getWidth() - this.nWidth) / this.nXOffset;
        this.nVertLimit = (image.getHeight() - this.nHeight) / this.nYOffset;
        this.nHorizIndex = -1; // first time through increments
        this.nVertIndex = 0;
        this.oSubImageReady = false;
    }
   
}
TOP

Related Classes of jjil.algorithm.MaskedGray8SubImgGen

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.