001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.sift.scalespace;
011
012import ij.IJ;
013
014public abstract class HierarchicalScaleSpace {
015        
016        final int P;    // number of octaves
017        final int Q;    // number of levels per octave
018        final double sigma_s;   // absolute scale of original image
019        final double sigma_0;   // absolute base scale of first octave (level 0,0)
020        final int botLevel, topLevel;  // bottom and top level index in each octave
021        final ScaleOctave[] octaves;
022
023        HierarchicalScaleSpace(int P, int Q, double sigma_s, double sigma_0, int botLevel, int topLevel) {
024                this.Q = Q;
025                this.P = P;
026                this.sigma_s = sigma_s;
027                this.sigma_0 = sigma_0;
028                this.botLevel = botLevel;
029                this.topLevel = topLevel;
030                octaves = new ScaleOctave[P];   
031        }
032        
033        public int getP() {
034                return P;
035        }
036        
037        public int getQ() {
038                return Q;
039        }
040        
041        public double getSigma_s() {
042                return sigma_s;
043        }
044        
045        public double getSigma_0() {
046                return sigma_0;
047        }
048        
049        public ScaleOctave getOctave(int p) {
050                return octaves[p];
051        }
052        
053        public ScaleLevel getScaleLevel(int p, int q) {
054                return getOctave(p).getLevel(q);
055        }
056        
057//      public float getValue(int p, int q, int u, int v) {
058//              ScaleLevel level = getLevel(p,q);
059//              return level.getf(u, v);
060//      }
061        
062        public int getScaleIndex(int p, int q) {
063                int m = Q * p + q; 
064                return m;
065        }
066        
067        public float getScaleIndexFloat(float p, float q) {
068                float m = Q * p + q; 
069                return m;
070        }
071        
072        public double getAbsoluteScale(int p, float q) {
073                double m = Q * p + q;
074                return sigma_0 * Math.pow(2, m/Q);
075        }
076        
077        public double getRelativeScale(double scaleA, double scaleB) {  // scaleA <= scaleB
078                if (scaleA > scaleB) {
079                        throw new IllegalArgumentException("getRelativeScale(): scaleA > scaleB");
080                }
081                return Math.sqrt(scaleB*scaleB - scaleA*scaleA);
082        }
083        
084        public double getRealX(int p, double xp) {
085                return Math.pow(2, p) * xp;     // TODO: optimize (precalculate Math.pow(p, 2))
086        }
087        
088        public double getRealY(int p, double yp) {
089                return Math.pow(2, p) * yp;
090        }
091        
092        public void show() {
093                show("");
094        }
095        
096        public void show(String title) {
097                if (!title.isEmpty()) {
098                        title = title + ": ";
099                }
100                for (int p = 0; p < P; p++) {
101                        octaves[p].showAsStack(title + "Octave " + p);
102                }
103        }
104        
105        public void print() {
106                IJ.log("Hierarchical Scale Space (" + this.getClass().toString() + ")");
107                for (ScaleOctave oct : octaves) {
108                        oct.print();
109                }
110                
111        }
112}