//----------------------------------------------------------------------------// // // // B a s i c A R T E x t r a c t o 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.moments; import static omr.moments.ARTMoments.*; import java.awt.image.WritableRaster; /** * Class {@code BasicARTExtractor} implements extraction * of ART Moments. * * See MPEG-7 Experimentation Model for the original C++ code * * @author Hervé Bitteur */ public class BasicARTExtractor extends AbstractExtractor<ARTMoments> { //~ Static fields/initializers --------------------------------------------- // Zernike basis function radius private static final int LUT_RADIUS = 50; /** Real values of ARTMoments basis function */ private static final LUT[][] realLuts = new LUT[ANGULAR][RADIAL]; /** Imaginary values of ARTMoments basis function */ private static final LUT[][] imagLuts = new LUT[ANGULAR][RADIAL]; static { initLUT(); } //~ Constructors ----------------------------------------------------------- /** * Creates a new BasicARTExtractor object and process * the provided foreground points. */ public BasicARTExtractor () { } //~ Methods ---------------------------------------------------------------- @Override public void reconstruct (WritableRaster raster) { ///throw new UnsupportedOperationException("Not supported yet."); } //----------------// // extractMoments // //----------------// @Override protected void extractMoments () { final LUT anyLut = realLuts[0][0]; // Just for template final int lutRadius = anyLut.getRadius(); final double centerX = center.getX(); final double centerY = center.getY(); // Coefficients, real part & imaginary part final double[][] coeffReal = new double[ANGULAR][RADIAL]; final double[][] coeffImag = new double[ANGULAR][RADIAL]; for (int i = 0; i < mass; i++) { // Map image coordinate to LUT coordinates double x = xx[i] - centerX; double y = yy[i] - centerY; double lx = ((x * lutRadius) / radius) + lutRadius; double ly = ((y * lutRadius) / radius) + lutRadius; // Summation of basis function if (anyLut.contains(lx, ly)) { for (int p = 0; p < ANGULAR; p++) { for (int r = 0; r < RADIAL; r++) { coeffReal[p][r] += realLuts[p][r].interpolate(lx, ly); coeffImag[p][r] -= imagLuts[p][r].interpolate(lx, ly); } } } } // Save to descriptor for (int p = 0; p < ANGULAR; p++) { for (int r = 0; r < RADIAL; r++) { double real = coeffReal[p][r] / mass; double imag = coeffImag[p][r] / mass; descriptor.setMoment(p, r, Math.hypot(imag, real)); // descriptor.setArgument(p, r, Math.atan2(imag, real)); // descriptor.setReal(p, r, real); // descriptor.setImag(p, r, imag); } } } //---------// // initLUT // //---------// /** * Compute, once for all, the lookup table values. */ private static void initLUT () { // Allocate LUT's for (int p = 0; p < ANGULAR; p++) { for (int r = 0; r < RADIAL; r++) { realLuts[p][r] = new BasicLUT(LUT_RADIUS); imagLuts[p][r] = new BasicLUT(LUT_RADIUS); } } final LUT anyLut = realLuts[0][0]; // Just for template final int lutSize = anyLut.getSize(); final int lutRadius = anyLut.getRadius(); for (int x = 0; x < lutSize; x++) { double tx = (x - lutRadius) / (double) lutRadius; // [-1..+1] for (int y = 0; y < lutSize; y++) { double ty = (y - lutRadius) / (double) lutRadius; // [-1..+1] double rad = Math.hypot(tx, ty); // [0..sqrt(2)] if (rad < 1) { // We are within circle double angle = Math.atan2(ty, tx); for (int p = 0; p < ANGULAR; p++) { for (int r = 0; r < RADIAL; r++) { double temp = Math.cos(rad * Math.PI * r); realLuts[p][r].assign( x, y, temp * Math.cos(angle * p)); imagLuts[p][r].assign( x, y, temp * Math.sin(angle * p)); } } } else { // We are on or outside circle for (int p = 0; p < ANGULAR; p++) { for (int r = 0; r < RADIAL; r++) { realLuts[p][r].assign(x, y, 0); imagLuts[p][r].assign(x, y, 0); } } } } } } }