//----------------------------------------------------------------------------//
// //
// V e r t i c a l F i l t e r //
// //
//----------------------------------------------------------------------------//
// <editor-fold defaultstate="collapsed" desc="hdr"> //
// Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. //
// This software is released under the GNU General Public License. //
// Goto http://kenai.com/projects/audiveris to report bugs or suggestions. //
//----------------------------------------------------------------------------//
// </editor-fold>
package omr.run;
import net.jcip.annotations.NotThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class {@code VerticalFilter} is a specialization of
* {@link AdaptiveFilter} which computes mean and standard
* deviation values based on vertical tiles of integrals.
*
* <p>This implementation is meant to be functionally equivalent to
* {@link RandomFilter} with similar performances but much lower
* memory requirements.
*
* <p>It uses a vertical window which performs the computation in constant time,
* provided that the vertical window always moves to the right.
* Instead of a whole table of integrals, this class uses a vertical tile whose
* width equals the window size, and the height equals the picture height.
* <pre>
* +----------------+
* | TILE_WIDTH |
* 0---------------------------------------------+---------------+
* | | |
* | | |
* | | |
* | a| b|
* +---------------------------------------------+---------------+
* | | |
* | | WINDOW |
* | | |
* | | |
* | | + |
* | | |
* | | |
* | | |
* | c| d|
* +---------------------------------------------+---------------+
* </pre>
* Since only the (1 + WINDOW_SIZE) last columns are relevant, a tile
* uses a circular buffer to handle only those columns.
* <p>
* Drawback: the implementation of the tile as a circular buffer makes
* an instance of this class usable by only one thread at a time.
*
* @author ryo/twitter @xiaot_Tag
* @author Hervé Bitteur
*/
@NotThreadSafe
public class VerticalFilter
extends AdaptiveFilter
implements PixelFilter
{
//~ Static fields/initializers ---------------------------------------------
/** Usual logger utility */
private static final Logger logger = LoggerFactory.getLogger(
VerticalFilter.class);
//~ Constructors -----------------------------------------------------------
//
//----------------//
// VerticalFilter //
//----------------//
/**
* Create an adaptive wrapper on a raw pixel source.
*
* @param source the underlying source of raw pixels
* @param meanCoeff the coefficient for mean value
* @param stdDevCoeff the coefficient for standard deviation value
*/
public VerticalFilter (PixelSource source,
double meanCoeff,
double stdDevCoeff)
{
super(source, meanCoeff, stdDevCoeff);
// Prepare tiles
tile = new MyTile( /* squared => */
false);
sqrTile = new MyTile( /* squared => */
true);
}
//~ Methods ----------------------------------------------------------------
//
//----------------------//
// getDefaultDescriptor //
//----------------------//
public static FilterDescriptor getDefaultDescriptor ()
{
return AdaptiveDescriptor.getDefault();
}
//~ Inner Classes ----------------------------------------------------------
//
//--------//
// MyTile //
//--------//
/**
* A tile as a circular buffer limited by window width.
*/
private class MyTile
extends Tile
{
//~ Constructors -------------------------------------------------------
public MyTile (boolean squared)
{
super(2 + (2 * HALF_WINDOW_SIZE), source.getHeight(), squared);
}
//~ Methods ------------------------------------------------------------
@Override
protected void shiftTile (int x2)
{
// Make sure we don't violate the tile principle
if (x2 < xRight) {
logger.error("SlidingPixelSource can only move forward");
throw new IllegalStateException();
}
// Shift tile as needed to the right
while (xRight < x2) {
xRight++;
populateColumn(xRight);
}
}
}
}