00001 /*!@file FeatureMatching/OriChamferMatching.H Oriented chamfer matching algs */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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 <elazary@usc.edu> 00034 // $HeadURL: $ 00035 // $Id: $ 00036 // 00037 00038 #ifndef ORICHAMFERMATCHING_H_DEFINED 00039 #define ORICHAMFERMATCHING_H_DEFINED 00040 00041 #include "Image/OpenCVUtil.H" 00042 #include "Util/Types.H" 00043 #include "GUI/DebugWin.H" 00044 #include "Image/Image.H" 00045 #include "Image/Pixels.H" 00046 #include "Image/ImageSet.H" 00047 #include "Image/Point2D.H" 00048 #include "Image/Point3D.H" 00049 #include "FeatureMatching/Polygon.H" 00050 00051 #include <vector> 00052 #include <map> 00053 00054 00055 class OriIntegralImage 00056 { 00057 00058 public: 00059 OriIntegralImage() {} 00060 00061 OriIntegralImage(const Image<float>& img, float dx, float dy); 00062 00063 inline float getCost(Point2D<int> p1, Point2D<int> p2) const 00064 { 00065 int x1 = p1.i; 00066 int y1 = p1.j; 00067 int x2 = p2.i; 00068 int y2 = p2.j; 00069 00070 int qy = -1; 00071 int qx = -1; 00072 int qy1 = -1; 00073 int qx1 = -1; 00074 00075 if (itsXindexed) 00076 { 00077 if (x1 <= x2) 00078 { 00079 qy = y1 + itsIndices[x2] - itsIndices[x1]; 00080 qx = x2; 00081 qy1 = y1 - itsIndices[x1] + itsIndices[x1-1]; 00082 qx1 = x1-1; 00083 } else { 00084 qy = y2+itsIndices[x1]-itsIndices[x2]; 00085 qx = x1; 00086 qy1 = y2-itsIndices[x2]+itsIndices[x2-1]; 00087 qx1 = x2-1; 00088 } 00089 } else { 00090 if (y1 <= y2) 00091 { 00092 qy = y2; 00093 qx =x1+itsIndices[y2]-itsIndices[y1]; 00094 qy1 = y1-1; 00095 qx1 = x1-itsIndices[y1]+itsIndices[y1-1]; 00096 } else { 00097 qy = y1; 00098 qx =x2+itsIndices[y1]-itsIndices[y2]; 00099 qy1 = y2-1; 00100 qx1 = x2-itsIndices[y2]+itsIndices[y2-1]; 00101 } 00102 } 00103 00104 double value = -1; 00105 if (itsIntegralImage.coordsOk(qx,qy) && 00106 itsIntegralImage.coordsOk(qx1,qy1)) 00107 value = + itsIntegralImage.getVal(qx,qy) - itsIntegralImage.getVal(qx1, qy1); 00108 else 00109 value = -1; 00110 00111 return (float)(value*itsFactor); 00112 } 00113 00114 private: 00115 float itsFactor; 00116 float itsDS; 00117 int itsXindexed; 00118 Image<float> itsIntegralImage; 00119 std::vector<int> itsIndices; 00120 00121 }; 00122 00123 class OriChamferMatching 00124 { 00125 00126 public: 00127 OriChamferMatching(); 00128 00129 OriChamferMatching(const std::vector<Line>& inLines, 00130 const int numDirections, 00131 const double oriCost, 00132 const Dims dims); 00133 00134 void setLines(const std::vector<Line>& inLines, 00135 const int numDirections, 00136 const double oriCost, 00137 const Dims dims); 00138 00139 00140 //! Update the costs using the orientation cost 00141 void updateOriCost(const double oriCost); 00142 00143 //! Build integral images from the distance images 00144 void buildIntegralDistances(); 00145 00146 inline float getCostFast(uint oriIdx, const Point2D<int> p1, const Point2D<int> p2) 00147 { 00148 if (oriIdx < itsOriIntDistImages.size()) 00149 return itsOriIntDistImages[oriIdx].getCost(p1,p2); 00150 else 00151 return -1; 00152 } 00153 00154 inline float getCost(uint oriIdx, const Point2D<int> p1, const Point2D<int> p2) 00155 { 00156 00157 if (oriIdx >= itsOriIntDistImages.size()) 00158 return -1; 00159 00160 if (false) 00161 { 00162 LINFO("%ix%i %ix%i ori=%f", p1.i, p1.j, p2.i, p2.j, oriIdx*M_PI/60); 00163 Image<PixRGB<byte> > tmp = itsOriDistImages[oriIdx]; 00164 drawLine(tmp, p1, p2, PixRGB<byte>(255,0,0)); 00165 SHOWIMG(tmp); 00166 SHOWIMG(itsOriDistImages[oriIdx]); 00167 } 00168 00169 00170 float sum = -1; 00171 // from Graphics Gems / Paul Heckbert 00172 int dx = p2.i - p1.i, ax = abs(dx) << 1, sx = signOf(dx); 00173 int dy = p2.j - p1.j, ay = abs(dy) << 1, sy = signOf(dy); 00174 int x = p1.i, y = p1.j; 00175 00176 const int w = itsOriDistImages[oriIdx].getWidth(); 00177 const int h = itsOriDistImages[oriIdx].getHeight(); 00178 00179 float* const sptr = itsOriDistImages[oriIdx].getArrayPtr(); 00180 00181 if (ax > ay) 00182 { 00183 int d = ay - (ax >> 1); 00184 for (;;) 00185 { 00186 if (x >= 0 && x < w && y >= 0 && y < h) 00187 { 00188 if (sum == -1) 00189 sum = sptr[x + w * y]; 00190 else 00191 sum += sptr[x + w * y]; 00192 } 00193 if (x == p2.i) return sum; 00194 if (d >= 0) { y += sy; d -= ax; } 00195 x += sx; d += ay; 00196 } 00197 } 00198 else 00199 { 00200 int d = ax - (ay >> 1); 00201 for (;;) 00202 { 00203 if (x >= 0 && x < w && y >= 0 && y < h) 00204 { 00205 if (sum == -1) 00206 sum = sptr[x + w * y]; 00207 else 00208 sum += sptr[x + w * y]; 00209 } 00210 if (y == p2.j) return sum; 00211 if (d >= 0) { x += sx; d -= ay; } 00212 y += sy; d += ax; 00213 } 00214 } 00215 00216 00217 return sum; 00218 } 00219 00220 00221 private: 00222 std::vector<Line> itsLines; 00223 ImageSet<float> itsOriDistImages; 00224 std::vector<OriIntegralImage> itsOriIntDistImages; 00225 00226 bool itsUseOpenCV; 00227 float itsMaxCost; 00228 00229 00230 }; 00231 00232 00233 00234 // ###################################################################### 00235 /* So things look consistent in everyone's emacs... */ 00236 /* Local Variables: */ 00237 /* indent-tabs-mode: nil */ 00238 /* End: */ 00239 00240 #endif //