00001 /*!@file plugins/SceneUnderstanding/LineMatching.C */ 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 LineMatching_C_DEFINED 00039 #define LineMatching_C_DEFINED 00040 00041 #include "Image/OpenCVUtil.H" //Needs to be first 00042 00043 #include "plugins/SceneUnderstanding/LineMatching.H" 00044 00045 #include "Image/DrawOps.H" 00046 #include "Raster/Raster.H" 00047 #include "Simulation/SimEventQueue.H" 00048 #include "GUI/DebugWin.H" 00049 #include "plugins/SceneUnderstanding/LMLineMatcher/LMLineMatcher.h" 00050 00051 #include "Media/MediaSimEvents.H" 00052 //#include "Neuro/NeuroSimEvents.H" 00053 #include "Transport/FrameInfo.H" 00054 #include "Transport/FrameOstream.H" 00055 00056 00057 const ModelOptionCateg MOC_LineMatching = { 00058 MOC_SORTPRI_3, "LineMatching-Related Options" }; 00059 00060 // Used by: SimulationViewerEyeMvt 00061 const ModelOptionDef OPT_LineMatchingShowDebug = 00062 { MODOPT_ARG(bool), "LineMatchingShowDebug", &MOC_LineMatching, OPTEXP_CORE, 00063 "Show debug img", 00064 "linematching-debug", '\0', "<true|false>", "false" }; 00065 00066 //Define the inst function name 00067 SIMMODULEINSTFUNC(LineMatching); 00068 00069 00070 // ###################################################################### 00071 LineMatching::LineMatching(OptionManager& mgr, const std::string& descrName, 00072 const std::string& tagName) : 00073 SimModule(mgr, descrName, tagName), 00074 SIMCALLBACK_INIT(SimEventV2Output), 00075 SIMCALLBACK_INIT(SimEventSaveOutput), 00076 itsShowDebug(&OPT_LineMatchingShowDebug, this) 00077 { 00078 } 00079 00080 // ###################################################################### 00081 LineMatching::~LineMatching() 00082 { 00083 } 00084 00085 00086 // ###################################################################### 00087 void LineMatching::onSimEventV2Output(SimEventQueue& q, 00088 rutz::shared_ptr<SimEventV2Output>& e) 00089 { 00090 itsLines = e->getLines(); 00091 00092 if (SeC<SimEventInputFrame> eframe = q.check<SimEventInputFrame>(this)) 00093 { 00094 GenericFrame frame = eframe->frame(); 00095 itsInImage = frame.asRgb(); 00096 } 00097 00098 evolve(q); 00099 00100 q.post(rutz::make_shared(new SimEventLineMatchingOutput(this, itsShapes))); 00101 00102 } 00103 00104 void LineMatching::evolve(SimEventQueue& q) 00105 { 00106 LMLineMatcher lm; 00107 lm.Configure("para_line_matcher.txt"); 00108 lm.Init("template_applelogo.txt"); 00109 lm.GetColorImage(""); //THe image to display 00110 00111 LFLineSegment* lines = new LFLineSegment[itsLines.size()]; 00112 for (uint i=0 ; i<itsLines.size() ; i++) 00113 { 00114 lines[i].sx_ = itsLines[i].p1.i; 00115 lines[i].sy_ = itsLines[i].p1.j; 00116 lines[i].ex_ = itsLines[i].p2.i; 00117 lines[i].ey_ = itsLines[i].p2.j; 00118 } 00119 00120 std::vector<Point2D<int> > maxPoly; 00121 if (0) 00122 { 00123 // std::vector<LMLineMatcher::Rect> matches = lm.Match(itsInImage.getWidth(), itsInImage.getHeight(), itsLines.size(), lines); 00124 // itsShapes.clear(); 00125 // for(uint i=0; i<matches.size(); i++) 00126 // itsShapes.push_back(Shape2D("applelogos", 00127 // matches[i].distance, 00128 // Rectangle(Point2D<int>(matches[i].x, matches[i].y), 00129 // Dims(matches[i].width, matches[i].height)))); 00130 } else { 00131 00132 lm.computeIDT3(itsInImage.getWidth(), 00133 itsInImage.getHeight(), 00134 itsLines.size(), lines); 00135 00136 00137 double scaleParam = 0.5; 00138 EIEdgeImage* dbImages_ = new EIEdgeImage [1]; 00139 dbImages_[0].SetNumDirections(60); 00140 dbImages_[0].Read((char*)"handdrawnApplelogoTemplate.txt"); 00141 dbImages_[0].Scale(scaleParam*1.0); 00142 00143 00144 LFLineSegment dbLine, queryLine; 00145 00146 00147 double ltrans[2]; 00148 00149 double factor = 1.0; 00150 double cost, mincost = 0; 00151 double minx, miny, maxx, maxy; 00152 double scale; 00153 00154 LFLineSegment line; 00155 00156 itsShapes.clear(); 00157 for(double s = -1 ; s< 18 ; s++) 00158 { 00159 scale = pow(1.1,s); 00160 printf("Scale %f\n", scale); 00161 EIEdgeImage tdbImage; 00162 tdbImage = dbImages_[0]; 00163 tdbImage.Scale(scale); 00164 factor = 1.0/dbImages_[0].Length(); 00165 tdbImage.Boundary(minx, miny, maxx, maxy); 00166 tdbImage.SetDirectionIndices(); 00167 00168 int width = itsInImage.getWidth()*scaleParam; 00169 int height = itsInImage.getHeight()*scaleParam; 00170 00171 Image<PixRGB<byte> > tmp = itsInImage; 00172 for (int x=-(int)minx ; x<width-(int)minx ; x += 4) 00173 { 00174 for (int y=-(int)miny; y<height-(int)miny; y += 4) 00175 { 00176 00177 ltrans[0] = (double)x; 00178 ltrans[1] = (double)y; 00179 cost = 0; 00180 00181 if (minx + ltrans[0] <=4 || 00182 minx + ltrans[0] >=width-4 || 00183 maxx + ltrans[0] <=4 || 00184 maxx + ltrans[0] >=width-4 || 00185 miny + ltrans[1] <=4 || 00186 miny + ltrans[1] >=height-4 || 00187 maxy + ltrans[1] <=4 || 00188 maxy + ltrans[1] >=height-4 ) 00189 { 00190 cost = 1e+10; 00191 continue; 00192 } 00193 else 00194 { 00195 00196 int count; 00197 cost = lm.getCost(tdbImage, ltrans, factor, count); 00198 std::vector<Point2D<int> > polygon; 00199 00200 int pixCount = 0; 00201 for (int k=0 ; k<tdbImage.nLines_ ; k++) 00202 { 00203 LFLineSegment line = tdbImage.lines_[k]; 00204 line.Translate(ltrans); 00205 polygon.push_back(Point2D<int>((int)line.sx_/scaleParam,(int)line.sy_/scaleParam)); 00206 polygon.push_back(Point2D<int>((int)line.ex_/scaleParam,(int)line.ey_/scaleParam)); 00207 pixCount += sqrt( squareOf(line.ey_-line.sy_) + 00208 squareOf(line.ex_-line.sx_)); 00209 } 00210 double prob = exp(-cost/ double(pixCount*3)); 00211 //LINFO("Draw Cost %f %i %f \n", cost, pixCount, prob); 00212 //drawOutlinedPolygon(tmp, polygon, PixRGB<byte>(0,255,0)); 00213 //SHOWIMG(tmp); 00214 00215 00216 00217 00218 if (prob>mincost) //mincost*1.0) 00219 { 00220 LINFO("Cost %i %i %f", x, y, prob); 00221 int x = (int)ceil((int)ltrans[0]/scaleParam-0.5); 00222 int y = (int)ceil((int)ltrans[1]/scaleParam-0.5); 00223 int detWindWidth= (int)(dbImages_[0].width_*scale/scaleParam); 00224 int detWindHeight= (int)(dbImages_[0].height_*scale/scaleParam); 00225 00226 itsShapes.push_back(Shape2D("applelogos", 00227 cost, 00228 Rectangle(Point2D<int>(x,y), 00229 Dims(detWindWidth, detWindHeight)), 00230 polygon)); 00231 00232 //if (cost < mincost) 00233 { 00234 mincost = prob; 00235 maxPoly = polygon; 00236 } 00237 00238 } 00239 00240 00241 } 00242 } 00243 00244 } 00245 00246 } 00247 //LINFO("Cost %f\n", mincost); 00248 //drawOutlinedPolygon(itsInImage, maxPoly, PixRGB<byte>(0,255,0)); 00249 //SHOWIMG(itsInImage); 00250 } 00251 00252 00253 //Output results 00254 for(uint i=0; i<itsShapes.size(); i++) 00255 { 00256 printf("Result: %i -1 -1 %i %i %i %i %f 0 0\n", 00257 i, 00258 itsShapes[i].bb.topLeft().i, 00259 itsShapes[i].bb.topLeft().j, 00260 itsShapes[i].bb.bottomRight().i, 00261 itsShapes[i].bb.bottomRight().j, 00262 itsShapes[i].score); 00263 } 00264 00265 } 00266 00267 00268 // ###################################################################### 00269 void LineMatching::onSimEventSaveOutput(SimEventQueue& q, 00270 rutz::shared_ptr<SimEventSaveOutput>& e) 00271 { 00272 if (itsShowDebug.getVal()) 00273 { 00274 // get the OFS to save to, assuming sinfo is of type 00275 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00276 nub::ref<FrameOstream> ofs = 00277 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs; 00278 Layout<PixRGB<byte> > disp = getDebugImage(); 00279 if (disp.initialized()) 00280 ofs->writeRgbLayout(disp, "LineMatching", FrameInfo("LineMatching", SRC_POS)); 00281 } 00282 } 00283 00284 Layout<PixRGB<byte> > LineMatching::getDebugImage() 00285 { 00286 00287 Layout<PixRGB<byte> > disp; 00288 00289 for(uint i=0; i<itsShapes.size() && i < 4; i++) 00290 { 00291 if (itsInImage.rectangleOk(itsShapes[i].bb)) 00292 { 00293 drawRect(itsInImage, itsShapes[i].bb, PixRGB<byte>(0,255,0)); 00294 for(uint j=0; j<itsShapes[j].polygon.size()-1; j++) 00295 { 00296 drawLine(itsInImage, itsShapes[i].polygon[j], 00297 itsShapes[i].polygon[j+1], PixRGB<byte>(0,255,0)); 00298 } 00299 } 00300 } 00301 disp = itsInImage; 00302 00303 usleep(10000); 00304 return disp; 00305 } 00306 00307 #endif