package fr.unistra.pelican.algorithms.descriptors.texture; import java.awt.Point; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.Descriptor; import fr.unistra.pelican.Image; import fr.unistra.pelican.algorithms.morphology.gray.GrayErosion; import fr.unistra.pelican.util.data.DoubleArrayData; /** * This class computes normalised covariance curve on 4 directions * (0,45,90,135). * * example : Given 25 as number of different lengths, 25 values are computed for * each orientation, with pixel distances ranging from 1 to 2 x 25, in * increments of 2. The user is encouraged to employ different SE forms. * * All pixels beyond image borders are ignored. * * MASK SUPPORT NOTE : put a msk wich B-dim different of that of input, and you'll * end just screwed up. * * @author Erchan Aptoula * @author Régis Witz (mask support, normalization and framework adaptation) */ public class Covariance extends Descriptor { /** The length of the covariance curve for each orientation. */ public int length = 25; /** Input image. */ public Image input; /** Output covariance curve. */ public DoubleArrayData output; /** Constructor */ public Covariance() { super(); super.inputs = "input"; super.options = "length"; super.outputs = "output"; } public static DoubleArrayData exec( Image input ) { return ( DoubleArrayData ) new Covariance().process( input ); } /** * Computes normalised covariance curve on 4 directions (0,45,90,135) * * @param input * The input image * @param length * The length of the covariance curve for each orientation * @return The output covariance curve */ public static DoubleArrayData exec( Image input, int length ) { return ( DoubleArrayData ) new Covariance().process( input, length ); } /** @see fr.unistra.pelican.Algorithm#launch() */ @SuppressWarnings("unchecked") public void launch() { int bdim = this.input.getBDim(); int size = this.length * 4 * bdim; Double[] curve = new Double[ size ]; for ( int i = 1 ; i <= this.length ; i++ ) for ( int n = 0 ; n < 4 ; n++ ) for ( int b = 0 ; b < bdim ; b++ ) curve[ i-1 + n*this.length + b*4*length ] = new Double(0); Double[] originalVolumes = new Double[ bdim ]; for ( int b = 0 ; b < bdim ; b++ ) originalVolumes[b] = this.volume( this.input, b ); int n; // every size for ( int i = 1 ; i <= this.length ; i++ ) { int side = i*2 + 1; // vertical line_____________________________ n = 0; BooleanImage se = new BooleanImage( side,side, 1,1,1 ); se.setCenter( new Point( i,i ) ); se.setPixelXYBoolean( 0,i, true ); se.setPixelXYBoolean( side-1,i, true ); Image tmp = GrayErosion.exec( this.input,se ); for ( int b = 0 ; b < bdim ; b++ ) curve[ b + n*bdim + ( i-1 )*4*bdim ] = this.volume( tmp,b ) / ( originalVolumes[b] * 4 * this.length ); // left diagonal line________________________ n = 1; se = new BooleanImage( side,side, 1,1,1 ); se.setCenter( new Point( i,i ) ); se.setPixelXYBoolean( 0,0, true ); se.setPixelXYBoolean( side-1,side-1, true ); tmp = GrayErosion.exec( this.input,se ); for ( int b = 0 ; b < bdim ; b++ ) curve[ i-1 + n*this.length + b*4*this.length ] = this.volume( tmp,b ) / ( originalVolumes[b] * 4 * this.length ); // horizontal line___________________________ n = 2; se = new BooleanImage( side,side, 1,1,1 ); se.setCenter( new Point( i,i ) ); se.setPixelXYBoolean( i,0, true ); se.setPixelXYBoolean( i,side-1, true ); tmp = GrayErosion.exec( this.input,se ); for ( int b = 0 ; b < bdim ; b++ ) curve[ i-1 + n*this.length + b*4*this.length ] = this.volume( tmp,b ) / ( originalVolumes[b] * 4 * this.length ); // right diagonal line_______________________ n = 3; se = new BooleanImage( side,side, 1,1,1 ); se.setCenter( new Point( i,i ) ); se.setPixelXYBoolean( side-1,0, true ); se.setPixelXYBoolean( 0,side-1, true ); tmp = GrayErosion.exec( this.input,se ); for ( int b = 0 ; b < bdim ; b++ ) curve[ i-1 + n*this.length + b*4*this.length ] = this.volume( tmp, b ) / ( originalVolumes[b] * 4 * this.length ); } this.output = new DoubleArrayData(); this.output.setDescriptor( ( Class ) this.getClass() ); this.output.setValues( curve ); } private Double volume( Image img, int channel ) { Double d = new Double( 0.0 ); for ( int x = 0 ; x < img.getXDim() ; x++ ) { for ( int y = 0 ; y < img.getYDim() ; y++ ) { if ( this.input.isPresentXYB( x,y,channel ) ) d += img.getPixelXYBDouble( x,y, channel ); } } return d; } }