00001 /*!@file SIFT/SIFThough.C Data structure for SIFT Hough transform */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: James Bonaiuto <bonaiuto@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/SIFT/SIFThough.C $ 00035 // $Id: SIFThough.C 5188 2005-08-02 18:09:34Z rjpeters $ 00036 // 00037 00038 #include "SIFT/SIFThough.H" 00039 #include "Util/Assert.H" 00040 #include "Util/Promotions.H" // for clamped_convert<T>() 00041 #include <cmath> 00042 00043 #define NBINX 8 00044 #define NBINY 8 00045 #define NBINO 8 00046 #define NBINS 8 00047 00048 // ###################################################################### 00049 SIFThough::SIFThough() : 00050 itsData(NBINX * NBINY * NBINO * NBINS, 0.0F) 00051 { } 00052 00053 // ###################################################################### 00054 SIFThough::~SIFThough() 00055 { } 00056 00057 // ######################################################################## 00058 void SIFThough::addValue(const float dx, const float dy, const float doo, 00059 const float ds, const float value) 00060 { 00061 int xi0, xi1, yi0, yi1, oi0, oi1, si0, si1; // bins 00062 float wx0, wy0, wo0, ws0, wx1, wy1, wo1, ws1; // corresponding weights 00063 00064 // if close to bounds then the values go fully into the end bins, 00065 // otherwise they split between two adjacent bins. Note: a value of 00066 // 2.0 should equally split between bins 1 and 2: 00067 if (dx <= 0.5F) 00068 { xi0 = 0; xi1 = 0; wx0 = 0.5F; wx1 = 0.5F; } 00069 else if (dx >= NBINX-0.5F) 00070 { xi0 = 3; xi1 = 3; wx0 = 0.5F; wx1 = 0.5F; } 00071 else 00072 { 00073 const float xx = dx - 0.5F; 00074 xi0 = int(xx); xi1 = xi0 + 1; 00075 wx1 = xx - float(xi0); wx0 = 1.0F - wx1; 00076 } 00077 00078 if (dy <= 0.5F) 00079 { yi0 = 0; yi1 = 0; wy0 = 0.5F; wy1 = 0.5F; } 00080 else if (dy >= NBINY-0.5F) 00081 { yi0 = 3; yi1 = 3; wy0 = 0.5F; wy1 = 0.5F; } 00082 else 00083 { 00084 const float yy = dy - 0.5F; 00085 yi0 = int(yy); yi1 = yi0 + 1; 00086 wy1 = yy - float(yi0); wy0 = 1.0F - wy1; 00087 } 00088 00089 // the situation is different for orientation as we wrap around: 00090 if (doo <= 0.5F) 00091 { 00092 oi0 = 0; oi1 = 7; 00093 wo0 = 0.5F + doo; wo1 = 1.0F - wo0; 00094 } 00095 else if (doo >= NBINO-0.5F) 00096 { 00097 oi0 = 7; oi1 = 0; 00098 wo0 = 8.5F - doo; wo1 = 1.0F - wo0; 00099 } 00100 else 00101 { 00102 const float oo = doo - 0.5F; 00103 oi0 = int(oo); oi1 = oi0 + 1; 00104 wo1 = oo - float(oi0); wo0 = 1.0F - wo1; 00105 } 00106 00107 if (ds <= 0.5F) 00108 { si0 = 0; si1 = 0; ws0 = 0.5F; ws1 = 0.5F; } 00109 else if (ds >= NBINS-0.5F) 00110 { si0 = 3; si1 = 3; ws0 = 0.5F; ws1 = 0.5F; } 00111 else 00112 { 00113 const float ss = ds - 0.5F; 00114 si0 = int(ss); si1 = si0 + 1; 00115 ws1 = ss - float(si0); ws0 = 1.0F - ws1; 00116 } 00117 00118 // convention: we add 1 for each unit of o (our fastest varying 00119 // index), then NBINO for each unit of s, then NBINO*NBINS for each 00120 // unit of y, finally NBINO*NBINS*NBINY for each unit of x. Let's 00121 // populate our 16 bins: 00122 xi0 = xi0 * NBINO*NBINS*NBINY; xi1 = xi1 * NBINO*NBINS*NBINY; 00123 yi0 = yi0 * NBINO*NBINS; yi1 = yi1 * NBINO*NBINS; 00124 si0 = si0 * NBINO; si1 = si1 * NBINO; 00125 00126 itsData[xi0 + yi0 + oi0 + si0] += value * wx0 * wy0 * wo0 * ws0; 00127 itsData[xi1 + yi0 + oi0 + si0] += value * wx1 * wy0 * wo0 * ws0; 00128 itsData[xi0 + yi1 + oi0 + si0] += value * wx0 * wy1 * wo0 * ws0; 00129 itsData[xi1 + yi1 + oi0 + si0] += value * wx1 * wy1 * wo0 * ws0; 00130 itsData[xi0 + yi0 + oi1 + si0] += value * wx0 * wy0 * wo1 * ws0; 00131 itsData[xi1 + yi0 + oi1 + si0] += value * wx1 * wy0 * wo1 * ws0; 00132 itsData[xi0 + yi1 + oi1 + si0] += value * wx0 * wy1 * wo1 * ws0; 00133 itsData[xi1 + yi1 + oi1 + si0] += value * wx1 * wy1 * wo1 * ws0; 00134 itsData[xi0 + yi0 + oi0 + si1] += value * wx0 * wy0 * wo0 * ws1; 00135 itsData[xi1 + yi0 + oi0 + si1] += value * wx1 * wy0 * wo0 * ws1; 00136 itsData[xi0 + yi1 + oi0 + si1] += value * wx0 * wy1 * wo0 * ws1; 00137 itsData[xi1 + yi1 + oi0 + si1] += value * wx1 * wy1 * wo0 * ws1; 00138 itsData[xi0 + yi0 + oi1 + si1] += value * wx0 * wy0 * wo1 * ws1; 00139 itsData[xi1 + yi0 + oi1 + si1] += value * wx1 * wy0 * wo1 * ws1; 00140 itsData[xi0 + yi1 + oi1 + si1] += value * wx0 * wy1 * wo1 * ws1; 00141 itsData[xi1 + yi1 + oi1 + si1] += value * wx1 * wy1 * wo1 * ws1; 00142 } 00143 00144 // ###################################################################### 00145 void SIFThough::getPeak(float& dx, float& dy, float& doo, float& ds) const 00146 { 00147 const uint siz = itsData.size(); 00148 float maxi = -1.0e-30; uint maxindex = 0; 00149 00150 // find index of the max: 00151 for (uint i = 0; i < siz; i ++) 00152 if (itsData[i] > maxi) { maxi = itsData[i]; maxindex = i; } 00153 00154 // get back from maxindex to bin indices in all 4 dimensions: 00155 const uint ix = maxindex / (NBINO*NBINS*NBINY); 00156 maxindex -= ix * NBINO*NBINS*NBINY; 00157 const uint iy = maxindex / (NBINO*NBINS); 00158 maxindex -= iy * NBINO*NBINS; 00159 const uint is = maxindex / NBINO; 00160 maxindex -= is * NBINO; 00161 const uint io = maxindex; 00162 00163 // we could try to do some interpolation or fitting of a 00164 // hyperparabola to the peak, etc. Maybe in the future: 00165 dx = float(ix); dy = float(iy); doo = float(io); ds = float(is); 00166 } 00167 00168 // ###################################################################### 00169 /* So things look consistent in everyone's emacs... */ 00170 /* Local Variables: */ 00171 /* indent-tabs-mode: nil */ 00172 /* End: */