00001 /*! @file SceneUnderstanding/trainHough.C train the hough transform */ 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: svn://isvn.usc.edu/software/invt/trunk/saliency/src/plugins/SceneUnderstanding/trainHough.C $ 00035 // $Id: trainHough.C 13765 2010-08-06 18:56:17Z lior $ 00036 // 00037 00038 //#include "Image/OpenCVUtil.H" // must be first to avoid conflicting defs of int64, uint64 00039 00040 #include "Component/JobServerConfigurator.H" 00041 #include "Component/ModelManager.H" 00042 #include "Image/Image.H" 00043 #include "Image/Pixels.H" 00044 #include "Image/DrawOps.H" 00045 #include "Image/MatrixOps.H" 00046 #include "Image/Point2D.H" 00047 #include "Media/SimFrameSeries.H" 00048 #include "Neuro/NeuroOpts.H" 00049 #include "Raster/Raster.H" 00050 #include "Simulation/SimEventQueueConfigurator.H" 00051 #include "Simulation/SimEventQueue.H" 00052 #include "Util/AllocAux.H" 00053 #include "Util/Pause.H" 00054 #include "Util/Types.H" 00055 #include "Util/csignals.H" 00056 #include "Util/log.H" 00057 #include "Util/sformat.H" 00058 #include "rutz/trace.h" 00059 #include "plugins/SceneUnderstanding/Geons3D.H" 00060 #include "plugins/SceneUnderstanding/SMap.H" 00061 #include "plugins/SceneUnderstanding/CornersFeatures.H" 00062 #include "plugins/SceneUnderstanding/V2.H" 00063 #include "GUI/DebugWin.H" 00064 #include "GUI/ViewPort3D.H" 00065 #include "Component/ModelManager.H" 00066 #include "Raster/GenericFrame.H" 00067 #include "Media/FrameSeries.H" 00068 #include "Transport/FrameInfo.H" 00069 #include "GUI/XWinManaged.H" 00070 #include "GUI/ImageDisplayStream.H" 00071 00072 #include <signal.h> 00073 #include <sys/types.h> 00074 00075 std::vector<CornersFeatures::CornerState> getCorners(std::vector<V2::LineSegment>& lines) 00076 { 00077 std::vector<CornersFeatures::CornerState> corners; 00078 float minDist = 5; 00079 float minDistSq = minDist*minDist; 00080 00081 //Image<float> edges(320, 240, ZEROS); 00082 //for(uint i=0; i<lines.size(); i++) 00083 //{ 00084 // V2::LineSegment& ls1 = itsLines[i]; 00085 // drawLine(edges, Point2D<int>(ls1.p1), Point2D<int>(ls1.p2), 255.0F); 00086 //} 00087 00088 00089 for(uint i=0; i<lines.size(); i++) 00090 { 00091 V2::LineSegment& ls1 = lines[i]; 00092 00093 //Image<PixRGB<byte> > tmp(320,240,ZEROS); // = edges; 00094 //drawLine(tmp, Point2D<int>(ls1.p1), Point2D<int>(ls1.p2), PixRGB<byte>(255,0,0)); 00095 00096 std::vector<float> angles1; //The angles from p1 prospective 00097 std::vector<float> angles2; //the angles from p2 prospective 00098 double dx = ls1.p2.i - ls1.p1.i; 00099 double dy = ls1.p2.j - ls1.p1.j; 00100 double ang = atan2(dx, dy) + M_PI/2; 00101 angles1.push_back(ang); 00102 angles2.push_back(ang+M_PI); 00103 00104 for(uint j=i+1; j<lines.size(); j++) 00105 { 00106 if (i == j) 00107 continue; 00108 V2::LineSegment& ls2 = lines[j]; 00109 00110 //Find if line segment i p1 intesect line segment j, and find the angle betwwen this 00111 //point and the reset of the ends 00112 if (ls1.p1.distanceToSegment(ls2.p1, ls2.p2) < minDist) 00113 { 00114 double dx1 = ls2.p1.i - ls1.p1.i; 00115 double dy1 = ls2.p1.j - ls1.p1.j; 00116 00117 double dx2 = ls2.p2.i - ls1.p1.i; 00118 double dy2 = ls2.p2.j - ls1.p1.j; 00119 00120 //If we intresected on a line then add both ends 00121 if ( (dx1*dx1 + dy1*dy1) > minDistSq) //p1 is further 00122 angles1.push_back(atan2(dx1, dy1) + M_PI/2); 00123 00124 if ( (dx2*dx2 + dy2*dy2) > minDistSq) //p2 is further 00125 angles1.push_back(atan2(dx2, dy2) + M_PI/2); 00126 } 00127 00128 00129 //Do the same for p2 in line segment i 00130 if (ls1.p2.distanceToSegment(ls2.p1, ls2.p2) < minDist) 00131 { 00132 double dx1 = ls2.p1.i - ls1.p2.i; 00133 double dy1 = ls2.p1.j - ls1.p2.j; 00134 00135 double dx2 = ls2.p2.i - ls1.p2.i; 00136 double dy2 = ls2.p2.j - ls1.p2.j; 00137 00138 //If we intresected on a line then add both ends 00139 if ( (dx1*dx1 + dy1*dy1) > minDistSq) //p1 is further 00140 angles2.push_back(atan2(dx1, dy1) + M_PI/2); 00141 00142 if ( (dx2*dx2 + dy2*dy2) > minDistSq) //p2 is further 00143 angles2.push_back(atan2(dx2, dy2) + M_PI/2); 00144 00145 } 00146 } 00147 00148 //Add the two corners 00149 00150 CornersFeatures::CornerState c1; 00151 c1.center = ls1.p1; 00152 c1.angles = angles1; 00153 corners.push_back(c1); 00154 00155 CornersFeatures::CornerState c2; 00156 c2.center = ls1.p2; 00157 c2.angles = angles2; 00158 corners.push_back(c2); 00159 00160 } 00161 //SHOWIMG(tmp); 00162 00163 //for(uint i=0; i<corners.size(); i++) 00164 //{ 00165 // Image<PixRGB<byte> > tmp(320, 240, ZEROS); 00166 // for(uint ai=0; ai<corners[i].angles.size(); ai++) 00167 // { 00168 // int x1 = int(cos(corners[i].angles[ai])*30.0/2.0); 00169 // int y1 = int(sin(corners[i].angles[ai])*30.0/2.0); 00170 // Point2D<float> p1(corners[i].center.i-x1, corners[i].center.j+y1); 00171 00172 // drawLine(tmp, Point2D<int>(corners[i].center), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 00173 // } 00174 // SHOWIMG(tmp); 00175 //} 00176 00177 00178 return corners; 00179 00180 } 00181 00182 00183 std::vector<V2::LineSegment> getLineSegments(ViewPort3D& vp, 00184 Point3D<float>& objPos, Point3D<float>& objRot, Geons3D::GeonType type) 00185 { 00186 vp.setWireframeMode(false); 00187 vp.setLightsMode(true); 00188 vp.setFeedbackMode(false); 00189 00190 vp.initFrame(); 00191 00192 switch(type) 00193 { 00194 case Geons3D::BOX: 00195 { 00196 vp.drawBox( 00197 objPos, 00198 objRot, 00199 Point3D<float>(30,30,30), 00200 PixRGB<byte>(0,256,0)); 00201 } 00202 break; 00203 case Geons3D::SPHERE: 00204 break; 00205 case Geons3D::CYLINDER: 00206 vp.drawCylinder( 00207 objPos, 00208 objRot, 00209 15, 32.5, 00210 PixRGB<byte>(0,256,0)); 00211 break; 00212 00213 } 00214 00215 Image<PixRGB<byte> > frame = flipVertic(vp.getFrame()); 00216 Image<float> surface = luminance(frame); 00217 00218 Image<float> edgesMag, edgesOri; 00219 gradientSobel(surface, edgesMag, edgesOri); 00220 00221 vp.setWireframeMode(true); 00222 vp.setLightsMode(false); 00223 vp.setFeedbackMode(true); 00224 00225 vp.initFrame(); 00226 00227 switch(type) 00228 { 00229 case Geons3D::BOX: 00230 { 00231 vp.drawBox( 00232 objPos, 00233 objRot, 00234 Point3D<float>(30,30,30), 00235 PixRGB<byte>(0,256,0)); 00236 } 00237 break; 00238 case Geons3D::SPHERE: 00239 break; 00240 case Geons3D::CYLINDER: 00241 vp.drawCylinder( 00242 objPos, 00243 objRot, 00244 15, 32.5, 00245 PixRGB<byte>(0,256,0)); 00246 break; 00247 00248 } 00249 00250 std::vector<ViewPort3D::Line> lines = vp.getFrameLines(); 00251 00252 Image<float> mag(vp.getDims(),ZEROS); 00253 Image<float> ori(vp.getDims(),ZEROS); 00254 00255 inplaceNormalize(edgesMag, 0.0F, 100.0F); 00256 std::vector<V2::LineSegment> lineSegments; 00257 for(uint i=0; i<lines.size(); i++) 00258 { 00259 00260 double dx = lines[i].p2.i - lines[i].p1.i; 00261 double dy = lines[i].p2.j - lines[i].p1.j; 00262 double ang = atan2(dx,dy) + M_PI/2; 00263 //Change orientation from 0 to M_PI 00264 if (ang < 0) ang += M_PI; 00265 if (ang >= M_PI) ang -= M_PI; 00266 00267 //Get the center of the line 00268 Point2D<float> center = lines[i].p1 + Point2D<float>(dx/2,dy/2); 00269 00270 if (edgesMag.coordsOk(Point2D<int>(lines[i].p1)) && 00271 edgesMag.coordsOk(Point2D<int>(lines[i].p2)) && 00272 edgesMag.getVal(Point2D<int>(lines[i].p1)) > 10 && 00273 edgesMag.getVal(Point2D<int>(lines[i].p2)) > 10 && 00274 edgesMag.getVal(Point2D<int>(center)) > 10) 00275 { 00276 double length = sqrt(dx*dx + dy*dy); 00277 00278 V2::LineSegment ls; 00279 ls.p1 = lines[i].p1; 00280 ls.p2 = lines[i].p2; 00281 ls.length = length; 00282 ls.ori = ang; 00283 ls.center = center; 00284 00285 lineSegments.push_back(ls); 00286 } 00287 } 00288 00289 return lineSegments; 00290 00291 } 00292 00293 Image<float> getSmap(ViewPort3D& vp, std::vector<V2::LineSegment>& lines) 00294 { 00295 00296 Image<float> smap(vp.getDims(), ZEROS); 00297 00298 if (lines.size() <= 0) 00299 return smap; 00300 00301 //Calculate the bounding box and center 00302 Point2D<int> center(0,0); 00303 Point2D<int> tl(0,0); 00304 Point2D<int> br(vp.getDims().w(),vp.getDims().h()); 00305 00306 for(uint i=0; i<lines.size(); i++) 00307 { 00308 center.i += int(lines[i].center.i); 00309 center.j += int(lines[i].center.j); 00310 00311 if (lines[i].p1 > tl) 00312 tl = (Point2D<int>)lines[i].p1; 00313 if (lines[i].p2 > tl) 00314 tl = (Point2D<int>)lines[i].p2; 00315 00316 if (lines[i].p1 < br) 00317 tl = (Point2D<int>)lines[i].p1; 00318 if (lines[i].p2 > tl) 00319 tl = (Point2D<int>)lines[i].p2; 00320 00321 // drawLine(smap, (Point2D<int>)lines[i].p1, (Point2D<int>)lines[i].p2, 255.0F); 00322 } 00323 center /= lines.size(); 00324 00325 drawDisk(smap, center, 3, 255.0F); 00326 // drawCircle(smap, tl, 3, 255.0F); 00327 // drawCircle(smap, br, 3, 255.0F); 00328 00329 return smap; 00330 00331 } 00332 00333 00334 00335 int main(const int argc, const char **argv) 00336 { 00337 00338 MYLOGVERB = LOG_INFO; 00339 ModelManager manager("Train Hough"); 00340 00341 nub::ref<SimEventQueueConfigurator> 00342 seqc(new SimEventQueueConfigurator(manager)); 00343 manager.addSubComponent(seqc); 00344 00345 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00346 manager.addSubComponent(ofs); 00347 00348 nub::ref<Geons3D> geons3D(new Geons3D(manager)); 00349 manager.addSubComponent(geons3D); 00350 00351 // Request a bunch of option aliases (shortcuts to lists of options): 00352 REQUEST_OPTIONALIAS_NEURO(manager); 00353 00354 00355 if (manager.parseCommandLine( 00356 (const int)argc, (const char**)argv, "", 0, 0) == false) 00357 return 1; 00358 00359 nub::ref<SimEventQueue> seq = seqc->getQ(); 00360 00361 manager.start(); 00362 00363 GHough ghough; 00364 00365 00366 ViewPort3D vp(320,240, true, false, true); 00367 //double trans[3][4] = { 00368 // {-0.996624, 0.070027, 0.042869, -16.907477}, 00369 // {-0.004359, 0.476245, -0.879302, 9.913470}, 00370 // {-0.081990, -0.876520, -0.474332, 276.648010}}; 00371 00372 double trans[3][4] = { 00373 {-0.999143, -0.041185, -0.004131, -1.142130}, 00374 {-0.017002, 0.499358, -0.866229, 17.284269}, 00375 {0.037739, -0.865416, -0.499630, 220.977236}}; 00376 00377 vp.setCamera(trans); 00378 00379 Point3D<float> objPos(0,0,16/2); 00380 Point3D<float> objRot(0,0,0); 00381 00382 00383 // temporary, for debugging... 00384 seq->printCallbacks(); 00385 00386 PauseWaiter p; 00387 //int retval = 0; 00388 SimStatus status = SIM_CONTINUE; 00389 00390 for(int obj=0; obj<3; obj++) 00391 for(float x=-150; x<150; x+=5) 00392 for(float y=40; y>-150; y-=5) 00393 for(float z=0; z<90; z+=5) 00394 { 00395 00396 int objType = 0; 00397 00398 switch (obj) 00399 { 00400 case 0: 00401 objType = 0; 00402 objPos.x = x; 00403 objPos.y = y; 00404 objRot.z = z; 00405 break; 00406 case 1: 00407 objType = 1; 00408 objPos.x = x; 00409 objPos.y = y; 00410 objRot.z = 0; 00411 z+= 90; //No rotation for object 1 00412 break; 00413 case 2: 00414 objType = 1; 00415 objPos.x = x; 00416 objPos.y = y; 00417 00418 objRot.x = 90; 00419 objRot.y = z; 00420 objRot.z = 0; 00421 break; 00422 } 00423 00424 //float x = 26.80; 00425 //float y = -44.90; 00426 //float z = 52; 00427 printf("%i %f %f %f\n",obj, x, y, z); 00428 00429 00430 std::vector<V2::LineSegment> lines = getLineSegments(vp, objPos, objRot, (Geons3D::GeonType)objType); 00431 00432 std::vector<CornersFeatures::CornerState> corners = getCorners(lines); 00433 00434 00435 //for(uint i=0; i<corners.size(); i++) 00436 //{ 00437 // Image<PixRGB<byte> > tmp(320, 240, ZEROS); 00438 // for(uint ai=0; ai<corners[i].angles.size(); ai++) 00439 // { 00440 // int x1 = int(cos(corners[i].angles[ai])*30.0/2.0); 00441 // int y1 = int(sin(corners[i].angles[ai])*30.0/2.0); 00442 // Point2D<float> p1(corners[i].center.i-x1, corners[i].center.j+y1); 00443 00444 // drawLine(tmp, Point2D<int>(corners[i].center), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 00445 // } 00446 // SHOWIMG(tmp); 00447 //} 00448 00449 00450 00451 //Send an SMap 00452 Image<byte> smap = getSmap(vp, lines); 00453 std::vector<SMap::SMapState> smapState; 00454 seq->post(rutz::make_shared(new SimEventSMapOutput(geons3D.get(), smapState, smap))); 00455 00456 //Send Corners 00457 seq->post(rutz::make_shared(new SimEventCornersOutput(geons3D.get(), corners))); 00458 00459 //Send metadata 00460 //rutz::shared_ptr<GenericFrame::MetaData> metaData; 00461 rutz::shared_ptr<World3DInput::ObjectsData> objectsData(new World3DInput::ObjectsData); 00462 Point3D<float> color(1,1,1); 00463 Point3D<float> params(30,30,30); 00464 objectsData->objects.push_back( 00465 World3DInput::Object(World3DInput::Object::ObjectType(objType), 00466 objPos, objRot, color, params)); 00467 ImageSet<float> cells; 00468 rutz::shared_ptr<GenericFrame::MetaData> metaData = objectsData; 00469 seq->post(rutz::make_shared(new SimEventLGNOutput(geons3D.get(), cells, metaData))); 00470 seq->post(rutz::make_shared(new SimEventV2Output(geons3D.get(), lines, vp.getDims()))); 00471 00472 // Evolve for one time step and switch to the next one: 00473 status = seq->evolve(); 00474 00475 Layout<PixRGB<byte> > disp = geons3D->getDebugImage(*seq); 00476 ofs->writeRgbLayout(disp, "Geons3D", FrameInfo("Geons3D", SRC_POS)); 00477 00478 00479 } 00480 00481 00482 manager.stop(); 00483 00484 return 0; 00485 } 00486