00001 /*!@file FeatureMatching/PGH.C Pairwise Geometric Histograms */ 00002 00003 00004 00005 // //////////////////////////////////////////////////////////////////// // 00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00007 // by the University of Southern California (USC) and the iLab at USC. // 00008 // See http://iLab.usc.edu for information about this project. // 00009 // //////////////////////////////////////////////////////////////////// // 00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00012 // in Visual Environments, and Applications'' by Christof Koch and // 00013 // Laurent Itti, California Institute of Technology, 2001 (patent // 00014 // pending; application number 09/912,225 filed July 23, 2001; see // 00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00016 // //////////////////////////////////////////////////////////////////// // 00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00018 // // 00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00020 // redistribute it and/or modify it under the terms of the GNU General // 00021 // Public License as published by the Free Software Foundation; either // 00022 // version 2 of the License, or (at your option) any later version. // 00023 // // 00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00027 // PURPOSE. See the GNU General Public License for more details. // 00028 // // 00029 // You should have received a copy of the GNU General Public License // 00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00032 // Boston, MA 02111-1307 USA. // 00033 // //////////////////////////////////////////////////////////////////// // 00034 // 00035 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/FeatureMatching/PGH.C $ 00037 // $Id: PGH.C 12985 2010-03-09 00:18:49Z lior $ 00038 // 00039 00040 #ifndef PGH_C_DEFINED 00041 #define PGH_C_DEFINED 00042 00043 #include "FeatureMatching/PGH.H" 00044 #include "Image/DrawOps.H" 00045 #include "GUI/DebugWin.H" 00046 #include "Util/FastMathFunctions.H" 00047 #include <fcntl.h> 00048 00049 // ###################################################################### 00050 PGH::PGH() 00051 { 00052 } 00053 00054 // ###################################################################### 00055 PGH::~PGH() 00056 { 00057 00058 } 00059 00060 void PGH::addModel(const std::vector<Line>& lines, int id) 00061 { 00062 ModelInfo model; 00063 model.id = id; 00064 model.lines = lines; 00065 00066 00067 //Create the histogram 00068 model.histogram = getGeometricHistogram(lines); 00069 SHOWIMG(model.histogram); 00070 00071 itsModels.push_back(model); 00072 } 00073 00074 int PGH::matchModel(const std::vector<Line>& lines) 00075 { 00076 00077 Image<float> histogram = getGeometricHistogram(lines); 00078 int id = 0; 00079 for(uint i=0; i<itsModels.size(); i++) 00080 { 00081 SHOWIMG(itsModels[i].histogram); 00082 SHOWIMG(histogram); 00083 double val = cmpHist(itsModels[i].histogram, histogram); 00084 LINFO("%i %f", itsModels[i].id, val); 00085 } 00086 00087 return id; 00088 00089 } 00090 00091 double PGH::cmpHist(const Image<float>& hist1, const Image<float>& hist2) 00092 { 00093 return sum(hist1-hist2); 00094 } 00095 00096 Image<float> PGH::getGeometricHistogram(const std::vector<Line>& lines) 00097 { 00098 00099 Image<float> histogram; 00100 00101 for(uint i=0; i<lines.size(); i++) 00102 for(uint j=0; j<lines.size(); j++) 00103 { 00104 if (i==j) continue; 00105 00106 float x = lines[j].pos.i - lines[i].pos.i; 00107 float y = lines[j].pos.j - lines[i].pos.j; 00108 00109 float rot = lines[i].ori; 00110 00111 Point2D<int> pos; 00112 pos.i = lines[i].pos.i + int(x * cos(rot) - y * sin(rot)); 00113 pos.j = lines[i].pos.j + int(y * cos(rot) + x * sin(rot)); 00114 float ori = lines[j].ori - rot; 00115 00116 int x1 = int(cos(ori)*lines[j].length/2); 00117 int y1 = int(sin(ori)*lines[j].length/2); 00118 00119 Point2D<int> pt1(pos.i-x1, pos.j+y1); 00120 Point2D<int> pt2(pos.i+x1, pos.j-y1); 00121 00122 int d1 = lines[i].pos.j - pos.j+y1; 00123 int d2 = lines[i].pos.j - pos.j-y1; 00124 00125 LINFO("d1 %i d2 %i", d1, d2); 00126 00127 Image<PixRGB<byte> > img(320,240,ZEROS); 00128 drawLine(img,lines[i].pos, 0, lines[i].length, 00129 PixRGB<byte>(255,0,0)); 00130 00131 drawLine(img,pos, ori, lines[j].length, 00132 PixRGB<byte>(0,255,0)); 00133 00134 //drawLine(img, pt1, d1, PixRGB<byte>(0,0,255)); 00135 //drawLine(img, pt2, d2, PixRGB<byte>(0,0,255)); 00136 SHOWIMG(img); 00137 } 00138 00139 return histogram; 00140 00141 } 00142 00143 //Image<float> PGH::getGeometricHistogram(const std::vector<Line>& lines) 00144 //{ 00145 // 00146 // #define DBL_EPSILON 2.2204460492503131e-16 00147 // 00148 // int angleDim = 100; 00149 // int distDim = 100; 00150 // 00151 // 00152 // double angle_scale = (angleDim - 0.51) / fastacos(0); 00153 // double dist_scale = DBL_EPSILON; 00154 // 00155 // Image<float> histogram(angleDim, distDim, ZEROS); 00156 // /* 00157 // do 2 passes. 00158 // First calculates maximal distance. 00159 // Second calculates histogram itself. 00160 // */ 00161 // for(int pass = 1; pass <= 2; pass++ ) 00162 // { 00163 // double dist_coeff = 0, angle_coeff = 0; 00164 // 00165 // /* run external loop */ 00166 // for(uint i = 0; i < lines.size(); i++ ) 00167 // { 00168 // int dist = 0; 00169 // 00170 // int x1 = int(cos(lines[i].ori)*lines[i].length/2); 00171 // int y1 = int(sin(lines[i].ori)*lines[i].length/2); 00172 // 00173 // Point2D<int> pt1(lines[i].pos.i-x1, lines[i].pos.j+y1); 00174 // Point2D<int> pt2(lines[i].pos.i+x1, lines[i].pos.j-y1); 00175 // 00176 // int dx = pt2.i - pt1.i; 00177 // int dy = pt2.j - pt1.j; 00178 // 00179 // if( (dx | dy) != 0 ) 00180 // { 00181 // if( pass == 2 ) 00182 // { 00183 // dist_coeff = (1/lines[i].length) * dist_scale; 00184 // angle_coeff = (1/lines[i].length) * ( ACOS_TABLE_SIZE / 2); 00185 // } 00186 // 00187 // /* run internal loop (for current edge) */ 00188 // for(uint j = 0; j < lines.size(); j++ ) 00189 // { 00190 // int x1 = int(cos(lines[j].ori)*lines[j].length/2); 00191 // int y1 = int(sin(lines[j].ori)*lines[j].length/2); 00192 // 00193 // Point2D<int> pt3(lines[j].pos.i-x1, lines[j].pos.j+y1); 00194 // Point2D<int> pt4(lines[j].pos.i+x1, lines[j].pos.j-y1); 00195 // 00196 // 00197 // if( i != j ) /* process edge pair */ 00198 // { 00199 // 00200 // 00201 // int d1 = (pt3.j - pt1.j) * dx - (pt3.i - pt1.i) * dy; 00202 // int d2 = (pt4.j - pt1.j) * dx - (pt2.i - pt1.i) * dy; 00203 // int cross_flag; 00204 // int hist_row = 0; 00205 // 00206 // if( pass == 2 ) 00207 // { 00208 // 00209 // int dp = (pt4.i - pt3.i) * dx + (pt4.j - pt3.j) * dy; 00210 // 00211 // dp = int( dp * angle_coeff * (1/lines[j].length) ) + (ACOS_TABLE_SIZE / 2); 00212 // dp = std::max( dp, 0 ); 00213 // dp = std::min( dp, ACOS_TABLE_SIZE - 1 ); 00214 // 00215 // hist_row = (int)round( fastacos(dp) * angle_scale ); 00216 // 00217 // Image<PixRGB<byte> > img(320,240,ZEROS); 00218 // drawLine(img, pt1, pt2, PixRGB<byte>(0,255,0)); 00219 // drawLine(img, pt3, pt4, PixRGB<byte>(0,255,0)); 00220 // LINFO("Ang %f", fastacos(dp)*180/M_PI); 00221 // SHOWIMG(img); 00222 // 00223 // d1 = (int)round( d1 * dist_coeff ); 00224 // d2 = (int)round( d2 * dist_coeff ); 00225 // } 00226 // 00227 // cross_flag = (d1 ^ d2) < 0; 00228 // 00229 // d1 = abs( d1 ); 00230 // d2 = abs( d2 ); 00231 // 00232 // if( pass == 2 ) 00233 // { 00234 // if( d1 >= distDim ) 00235 // d1 = distDim - 1; 00236 // if( d2 >= distDim ) 00237 // d2 = distDim - 1; 00238 // 00239 // if( !cross_flag ) 00240 // { 00241 // if( d1 > d2 ) /* make d1 <= d2 */ 00242 // { 00243 // d1 ^= d2; 00244 // d2 ^= d1; 00245 // d1 ^= d2; 00246 // } 00247 // 00248 // for( ; d1 <= d2; d1++ ) 00249 // histogram.setVal(hist_row, d1, histogram.getVal(hist_row, d1)+1); 00250 // } else { 00251 // for( ; d1 >= 0; d1-- ) 00252 // histogram.setVal(hist_row, d1, histogram.getVal(hist_row, d1)+1); 00253 // for( ; d2 >= 0; d2-- ) 00254 // histogram.setVal(hist_row, d2, histogram.getVal(hist_row, d2)+1); 00255 // } 00256 // } 00257 // else /* 1st pass */ 00258 // { 00259 // d1 = std::max( d1, d2 ); 00260 // dist = std::max( dist, d1 ); 00261 // } 00262 // } /* end of processing of edge pair */ 00263 // 00264 // } /* end of internal loop */ 00265 // 00266 // if( pass == 1 ) 00267 // { 00268 // double scale = dist * (1/lines[i].length); 00269 // 00270 // dist_scale = std::max( dist_scale, scale ); 00271 // } 00272 // } 00273 // } /* end of external loop */ 00274 // 00275 // if( pass == 1 ) 00276 // { 00277 // dist_scale = (distDim - 0.51) / dist_scale; 00278 // } 00279 // 00280 // } /* end of pass on loops */ 00281 // 00282 // return histogram; 00283 //} 00284 00285 00286 // ###################################################################### 00287 /* So things look consistent in everyone's emacs... */ 00288 /* Local Variables: */ 00289 /* indent-tabs-mode: nil */ 00290 /* End: */ 00291 00292 #endif 00293