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 }