org.jaitools.media.jai.regionalize.RegionalizeDescriptor Maven / Gradle / Ivy
Show all versions of jt-regionalize Show documentation
/*
* Copyright (c) 2009-2011, Michael Bedward. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jaitools.media.jai.regionalize;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.registry.RenderedRegistryMode;
/**
* Describes the "Regionalize" operation.
*
* This operation takes a single source image and identifies regions
* of connected pixels with uniform value, where value comparisons
* take into account a user-specified tolerance.
*
* Note: At present, this operator only deals with a single band.
*
* Algorithm
* The operator scans the source image left to right, top to bottom. When
* it reaches a pixel that has not been allocated to a region yet it uses
* that pixel as the starting point for a flood-fill search (similar to
* flood-filling in a paint program). The value of the starting pixel is
* recorded as the reference value for the new region. The search works
* its way outwards from the starting pixel, testing other pixels for
* inclusion in the region. A pixel will be included if:
{@code
* |value - reference value| <= tolerance} where tolerance is a
* user-specified parameter.
*
* If the diagonal parameter is set to true, the flood-fill search will
* include pixels that can only be reached via a diagonal step; if false,
* only orthogonal steps are taken.
*
* The search continues until no further pixels can be added to the region.
* The region is then allocated a unique integer ID and summary statistics
* (bounds, number of pixels, reference value) are recorded for it.
*
* The output of the operation is an image of data type TYPE_INT, where each
* pixel's value is its region ID. A {@linkplain Region} object can be
* retrieved as a property of the output image using the property name
* {@linkplain RegionalizeDescriptor#REGION_DATA_PROPERTY}).
*
* Example
*
{@code
* RenderedImage myImg = ...
*
* ParameterBlockJAI pb = new ParameterBlockJAI("regionalize");
* pb.setSource("source0", myImg);
* pb.setParameter("band", 0);
* pb.setParameter("tolerance", 0.1d);
* pb.setParameter("diagonal", false);
* RenderedOp regionImg = JAI.create("Regionalize", pb);
*
* // have a look at the image (this will force rendering and
* // the calculation of region data)
*
* // print the summary data
* RegionData regData =
* (RegionData)op.getProperty(RegionalizeDescriptor.REGION_DATA_PROPERTY);
*
* List<Region> regions = regData.getData();
* Iterator<Region> iter = regions.iterator();
* System.out.println("ID\tValue\tSize\tMin X\tMax X\tMin Y\tMax Y");
* while (iter.hasNext()) {
* Region r = iter.next();
* System.out.println( String.format("%d\t%.2f\t%d\t%d\t%d\t%d\t%d",
* r.getId(),
* r.getRefValue(),
* r.getNumPixels(),
* r.getMinX(),
* r.getMaxX(),
* r.getMinY(),
* r.getMaxY() ));
* }
* }
*
*
* Summary of parameters:
*
* Summary of parameters
*
* Name
* Class
* Default
* Description
*
*
*
* band
* int
* 0
* The source image band to process
*
*
*
* tolerance
* double
* 0
* Tolerance for comparison of image values
*
*
*
* diagonal
* boolean
* false
*
* If {@code true} diagonal connections are allowed; if {@code false}
* only orthogonal connections are allowed
*
*
*
*
* @author Michael Bedward
* @since 1.0
* @version $Id$
*/
public class RegionalizeDescriptor extends OperationDescriptorImpl {
/**
* The propoerty name to retrieve the {@linkplain Region}
* object which holds summary data for regions identified in
* the source image and depicted in the destination image
*/
public static final String REGION_DATA_PROPERTY = "regiondata";
static final int BAND_ARG_INDEX = 0;
static final int TOLERANCE_ARG_INDEX = 1;
static final int DIAGONAL_ARG_INDEX = 2;
private static final String[] paramNames =
{"band", "tolerance", "diagonal"};
private static final Class[] paramClasses =
{Integer.class, Double.class, Boolean.class};
private static final Object[] paramDefaults =
{Integer.valueOf(0), Double.valueOf(0d), Boolean.TRUE};
/** Constructor. */
public RegionalizeDescriptor() {
super(new String[][]{
{"GlobalName", "Regionalize"},
{"LocalName", "Regionalize"},
{"Vendor", "org.jaitools.media.jai"},
{"Description", "Identifies sufficiently uniform regions in a source image"},
{"DocURL", "http://code.google.com/p/jaitools/"},
{"Version", "1.0.0"},
{"arg0Desc", "band (int) - the band to regionalize"},
{"arg1Desc", "tolerance (double) - tolerance for pixel value comparison"},
{"arg2Desc", "diagonal (boolean) - true to include diagonal neighbours;" +
"false for only orthogonal neighbours"}
},
new String[]{RenderedRegistryMode.MODE_NAME}, // supported modes
1, // number of sources
paramNames,
paramClasses,
paramDefaults,
null // valid values (none defined)
);
}
}