001 package util.wavelet; 002 import java.util.List; 003 import static java.lang.Math.*; 004 005 /** A wavelet scale containing wavelet coefficients. 006 * @author John Talbot 007 */ 008 public class Scale extends Signal { 009 010 /** The scale number. Higher numbers indicate smoother scales. */ 011 int scaleNumber; 012 013 /** A lookup table for efficiently accessing the Structure at a given index, if -1 then no structure*/ 014 protected int[] structureLookupTable; 015 016 /** Structures in this level. */ 017 public java.util.List<Structure> structures; // LAZY evaluation if a threshold is given in constructor, null otherwise 018 019 /** If true only positive features are detected. */ 020 public static final boolean POSITIVE = true; 021 022 /** 023 * Construct using an array of wavelet coefficients and an array of noise values encoded 024 * as an instance of signal. 025 * 026 * @param signal a {@link SimpleSignal} 027 */ 028 public Scale(SimpleSignal signal, int scaleNumber) { 029 super(signal); 030 this.scaleNumber = scaleNumber; 031 } 032 033 /** 034 * Find the {@link Structure} instances defined as a contiguous set of wavelet coefficients above noise. 035 * 036 * @return a list of Structure instances 037 */ 038 void findStructures() { 039 if (structures != null) return; 040 structures = new java.util.ArrayList<Structure>(16); 041 structureLookupTable = new int[size()]; 042 int currentLabel = 0; 043 int start = 0; 044 boolean inStructure = false; 045 for (int i = 0; i < size(); i++) { 046 if ( POSITIVE && isAboveNoise(i) || !POSITIVE && isBelowNoise(i)) { 047 structureLookupTable[i] = currentLabel; 048 if (!inStructure) { 049 inStructure = true; 050 start = i; 051 } 052 } else { 053 structureLookupTable[i] = NOISE; // flag this position as noise 054 if (inStructure) { 055 inStructure = false; 056 structures.add(new Structure(this, start, i)); // 'end' defined as one more than the actual end 057 currentLabel++; 058 } 059 } 060 } 061 } 062 063 static final int NOISE = -1; 064 065 /** 066 * Get the {@link Structure} at the given pixel position or null if none exists there. 067 * 068 * @param position pixel position 069 * @return the {@link Structure} at the given position or null if none exists there 070 */ 071 public Structure getStructure(int position) { 072 if (structures == null) findStructures(); // LAZY evaluation 073 if (structureLookupTable[position] == NOISE ) 074 return null; 075 else 076 return getStructures().get(structureLookupTable[position]); 077 } 078 079 /** 080 * Get the Structures. 081 * @return a list of Structures found in this scale 082 */ 083 public java.util.List<Structure> getStructures() { 084 if (structures == null) findStructures(); 085 return structures; 086 } 087 088 /** 089 * Get the wavelet coefficient value at the given position and for the given {@link WObject}, zero otherwise. 090 * Precondition : 0 ≥ <code>index</code> ≤ size(). 091 * 092 * @param position must be within the wavelet coefficients of this Scale 093 * @param wObjectIndex WObject index 094 * @return the wavelet coefficient value at the given position 095 */ 096 097 public float getValue(int position, int wObjectIndex) { 098 099 // TODO : 100 /* 101 Structure structure = getStructure(position); 102 if (structure != null && structure.wObject == index) 103 return getValue(position); 104 else 105 return 0f; 106 */ 107 return getValue(position); // XXX: incorrect 108 } 109 110 /** 111 * If this scale contains Structures which belong to a given WObject then 112 * add those wavelet coefficients to a given signal and return results in that signal. 113 * Precondition: signal has the same size 114 * 115 * @param signal the signal to be added to this scale 116 * @param index the object index to 117 */ 118 public void add(SimpleSignal signal, int index) { 119 for (int i = 0; i < size(); i++) 120 signal.setValue(i, getValue(i) + signal.getValue(i)); 121 } 122 123 /** 124 * Get the scale number. Higher numbers indicate smoother scales. 125 * Useful for checking purposes, such as verifying that a Structure 126 * is related to another structure plus or minus a scale number etc... 127 * 128 * @return the scale number (starts at 0) 129 */ 130 public int getScaleNumber() { 131 return scaleNumber; 132 } 133 134 }