00001 /*!@file Image/TensorOps.H Mathematical Tensor operations */ 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: Lior Elazary 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/TensorOps.H $ 00035 // $Id: TensorOps.H 14490 2011-02-11 19:46:05Z lior $ 00036 // 00037 00038 #ifndef IMAGE_TENSOROPS_H_DEFINED 00039 #define IMAGE_TENSOROPS_H_DEFINED 00040 00041 #include "Image/Image.H" 00042 #include "Image/ImageSet.H" 00043 #include "Image/FilterOps.H" 00044 #include "Util/Promotions.H" 00045 #include <vector> 00046 00047 00048 struct EigenSpace 00049 { 00050 ImageSet<float> e1; 00051 ImageSet<float> e2; 00052 Image<float> l1; 00053 Image<float> l2; 00054 }; 00055 00056 //!Here we represent tensors as an image set with 4 images indexed as: 00057 //| t1 t2 | 00058 //| t3 t4 | 00059 struct TensorField 00060 { 00061 Image<float> t1; 00062 Image<float> t2; 00063 Image<float> t3; 00064 Image<float> t4; 00065 00066 TensorField() 00067 { 00068 } 00069 00070 TensorField(Dims dims, InitPolicy policy) 00071 { 00072 t1 = Image<float>(dims, policy); 00073 t2 = Image<float>(dims, policy); 00074 t3 = Image<float>(dims, policy); 00075 t4 = Image<float>(dims, policy); 00076 } 00077 00078 TensorField operator+(const TensorField& _tf) const 00079 { 00080 TensorField tf(t1.getDims(), NO_INIT); 00081 00082 tf.t1 = t1 + _tf.t1; 00083 tf.t2 = t2 + _tf.t2; 00084 tf.t3 = t3 + _tf.t3; 00085 tf.t4 = t4 + _tf.t4; 00086 00087 return tf; 00088 } 00089 00090 TensorField& operator+=(const TensorField& tf) 00091 { 00092 t1 += tf.t1; 00093 t2 += tf.t2; 00094 t3 += tf.t3; 00095 t4 += tf.t4; 00096 00097 return *this; 00098 } 00099 00100 TensorField& operator/=(const float s) 00101 { 00102 t1 /= s; 00103 t2 /= s; 00104 t3 /= s; 00105 t4 /= s; 00106 00107 return *this; 00108 } 00109 00110 void setVal(const uint i, float val) 00111 { 00112 t1.setVal(i, val); 00113 t2.setVal(i, val); 00114 t3.setVal(i, val); 00115 t4.setVal(i, val); 00116 } 00117 00118 void setVal(const uint i, const uint j, float val) 00119 { 00120 t1.setVal(i,j, val); 00121 t2.setVal(i,j, val); 00122 t3.setVal(i,j, val); 00123 t4.setVal(i,j, val); 00124 } 00125 00126 //! Get another tensor field, and set this tensor field to the max between the two 00127 void setMax(const TensorField& tf) 00128 { 00129 ASSERT(tf.t1.size() == t1.size()); 00130 00131 for(uint i=0; i<tf.t1.size(); i++) 00132 { 00133 //The input feature value 00134 //trace/2 00135 double trace = (tf.t1.getVal(i) + tf.t4.getVal(i))/2; 00136 00137 double a = tf.t1.getVal(i) - trace; 00138 double b = tf.t2.getVal(i); 00139 00140 double ab = sqrt((a*a) + (b*b)); 00141 00142 //The local feature value 00143 //trace/2 00144 double trace2 = (t1.getVal(i) + t4.getVal(i))/2; 00145 00146 double a2 = t1.getVal(i) - trace2; 00147 double b2 = t2.getVal(i); 00148 00149 double ab2 = sqrt((a2*a2) + (b2*b2)); 00150 00151 if (ab+ab > ab2+ab2) 00152 { 00153 t1.setVal(i, tf.t1.getVal(i)); 00154 t2.setVal(i, tf.t2.getVal(i)); 00155 t3.setVal(i, tf.t3.getVal(i)); 00156 t4.setVal(i, tf.t4.getVal(i)); 00157 } 00158 00159 } 00160 00161 } 00162 }; 00163 00164 00165 00166 //! Get the tensor of an image by measuring the gradient 00167 template <class T> 00168 TensorField getTensor(const Image<T>& img, int kernelSize=5); 00169 00170 //! Get the tensor magnitude value 00171 Image<float> getTensorMag(const TensorField& tf); 00172 00173 //! Get the tensor of an image from eigenvectors and eigenvalues 00174 TensorField getTensor(const EigenSpace& eigen); 00175 00176 //! Get the eigenvectors and values from a tensor 00177 EigenSpace getTensorEigen(const TensorField& tf); 00178 00179 //! Perform non maximal surpression 00180 void nonMaxSurp(TensorField& tf, float radius=1.5); 00181 00182 00183 // ###################################################################### 00184 /* So things look consistent in everyone's emacs... */ 00185 /* Local Variables: */ 00186 /* indent-tabs-mode: nil */ 00187 /* End: */ 00188 00189 #endif // !IMAGE_TENSOROPS_H_DEFINED