00001 /*!@file Media/TestImages.C Test Images */ 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 <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/TestImages.C $ 00035 // $Id: TestImages.C 12357 2009-12-21 19:49:24Z lior $ 00036 // 00037 00038 #include "Media/TestImages.H" 00039 00040 #include "GUI/DebugWin.H" 00041 #include "Image/CutPaste.H" 00042 #include "Image/DrawOps.H" 00043 #include "Image/ShapeOps.H" 00044 #include "Image/Transforms.H" 00045 #include "Raster/Raster.H" 00046 #include "Util/FileUtil.H" // for isDirectory() 00047 #include "Util/sformat.H" 00048 #include <dirent.h> 00049 #include <list> 00050 #include <algorithm> 00051 00052 //init the objects def for the ALOI lib 00053 const char* TestImages::ALOI_LUM[] = { 00054 "i110", "i120", "i130", "i140", "i150", "i160", "i170", "i180", 00055 "i190", "i210", "i230", "i250" 00056 }; 00057 00058 const char *TestImages::ALOI_COL[] = { 00059 "l1c1", "l1c2", "l1c3", "l2c1", "l2c2", "l2c3", "l3c1", "l3c2", 00060 "l3c3", "l4c1", "l4c2", "l4c3", "l5c1", "l5c2", "l5c3", "l6c1", 00061 "l6c2", "l6c3", "l7c1", "l7c2", "l7c3", "l8c1", "l8c2", "l8c3" 00062 }; 00063 00064 const char *TestImages::ALOI_ROT[] = { 00065 "r0", "r5", "r10", "r15", "r20", "r25", "r30", "r35", "r40", "r45", "r50", 00066 "r55", "r60", "r65", "r70", "r75", "r80", "r85", "r90", "r95", "r100", 00067 "r105", "r110", "r115", "r120", "r125", "r130", "r135", "r140", "r145", 00068 "r150", "r155", "r160", "r165", "r170", "r175", "r180", "r185", "r190", 00069 "r195", "r200", "r205", "r210", "r215", "r220", "r225", "r230", "r235", 00070 "r240", "r245", "r250", "r255", "r260", "r265", "r270", "r275", "r280", 00071 "r285", "r290", "r295", "r300", "r305", "r310", "r315", "r320", "r325", 00072 "r330", "r335", "r340", "r345", "r350", "r355" 00073 }; 00074 00075 // ####################################################################### 00076 TestImages::TestImages(const char* imagesPath, LIBRARY lib, 00077 const int numTraining, 00078 const int numTesting, 00079 const int numObjects) : 00080 itsImagesPath(imagesPath), itsLibType(lib), 00081 itsObjPolygon(0,std::vector<Point2D<int> >(0)), itsObjNames(0), 00082 itsSceneFilenames(0), itsObjects(0), 00083 itsScenes(0), 00084 itsTrainScenes(0), 00085 itsTestScenes(0), 00086 itsNumTraining(numTraining), 00087 itsNumTesting(numTesting), 00088 itsNumObjects(numObjects) 00089 { 00090 switch (itsLibType) { 00091 case ALOI: 00092 itsMaxLum = sizeof(ALOI_LUM)/4; 00093 itsMaxCol = sizeof(ALOI_COL)/4; 00094 itsMaxRot = sizeof(ALOI_ROT)/4; 00095 break; 00096 00097 case CSAIL: 00098 break; 00099 00100 case COIL: 00101 break; 00102 00103 case MIT_LABELME: 00104 readDir(itsImagesPath); 00105 break; 00106 00107 case CSCLAB: 00108 itsSceneId = -1; 00109 readDir(itsImagesPath); 00110 break; 00111 00112 case CALTECH256: 00113 itsSceneId = -1; 00114 readCalTech256Dir(itsImagesPath, itsNumTraining, itsNumTesting); 00115 break; 00116 00117 case IMG_DIR: 00118 readDir(itsImagesPath); 00119 break; 00120 00121 case XMLFILE: 00122 readObjXML(itsImagesPath); 00123 break; 00124 00125 default: 00126 LERROR("Unknown lib type"); 00127 } 00128 } 00129 00130 // ###################################################################### 00131 TestImages::~TestImages() 00132 { } 00133 00134 // ###################################################################### 00135 uint TestImages::getNumObj(uint scene) 00136 { 00137 switch (itsLibType) { 00138 case ALOI: 00139 break; 00140 00141 case CSAIL: 00142 break; 00143 00144 case COIL: 00145 break; 00146 00147 case MIT_LABELME: 00148 return itsObjNames.size(); 00149 break; 00150 00151 case CSCLAB: 00152 return itsObjNames.size(); 00153 break; 00154 00155 case IMG_DIR: 00156 return itsSceneFilenames.size(); 00157 break; 00158 00159 case XMLFILE: 00160 ASSERT(scene < itsScenes.size()); 00161 return itsScenes[scene].objects.size(); 00162 break; 00163 00164 default: 00165 LERROR("Unknown lib type"); 00166 } 00167 00168 return 0; 00169 } 00170 00171 // ####################################################################### 00172 void TestImages::readDir(const char *path) 00173 { 00174 DIR *dp = opendir(path); 00175 if (dp != NULL) { 00176 dirent *dirp; 00177 while ((dirp = readdir(dp)) != NULL ) { 00178 if (dirp->d_name[0] != '.' && 00179 isDirectory(dirp) == false) 00180 { 00181 std::string filePath = std::string(path) + '/' + 00182 std::string(dirp->d_name); 00183 if (Raster::fileExists(filePath,RASFMT_AUTO, true)) 00184 itsSceneFilenames.push_back(filePath); 00185 } 00186 } 00187 LDEBUG("%"ZU" files in the directory\n", itsSceneFilenames.size()); 00188 } else LFATAL("%s is not a directory", path); 00189 } 00190 00191 // ####################################################################### 00192 void TestImages::readCalTech256Dir(const char *path, const int trainingSize, 00193 const int testingSize, bool shuffle) 00194 { 00195 DIR *dp = opendir(path); 00196 int i = 0; 00197 if (dp != NULL) 00198 { 00199 dirent *dirp; 00200 while ((dirp = readdir(dp)) != NULL ) { 00201 if (dirp->d_name[0] != '.' && 00202 isDirectory(dirp) == true) 00203 { 00204 std::string filePath = std::string(path) + '/' + 00205 std::string(dirp->d_name); 00206 00207 // get the individual files 00208 itsSceneFilenames.clear(); 00209 readDir(filePath.c_str()); 00210 00211 // if (shuffle) 00212 // std::random_shuffle(itsSceneFilenames.begin(), 00213 // itsSceneFilenames.end()); 00214 00215 int training = trainingSize; 00216 int testing = testingSize; 00217 if (training == -1) 00218 training = itsSceneFilenames.size()/2; 00219 00220 int scene = 0; 00221 00222 for(; scene < training && scene < (int)itsSceneFilenames.size(); 00223 scene++) 00224 { 00225 SceneData sceneData; 00226 sceneData.description = std::string(dirp->d_name); 00227 sceneData.filename = itsSceneFilenames[scene]; 00228 sceneData.useType = TRAIN; 00229 itsTrainScenes.push_back(sceneData); 00230 } 00231 00232 if (testing == -1) 00233 testing = itsSceneFilenames.size()/2; 00234 00235 testing += scene; 00236 00237 for(; scene<testing && scene<(int)itsSceneFilenames.size(); scene++) 00238 { 00239 SceneData sceneData; 00240 sceneData.description = std::string(dirp->d_name); 00241 sceneData.filename = itsSceneFilenames[scene]; 00242 sceneData.useType = TEST; 00243 itsTestScenes.push_back(sceneData); 00244 } 00245 } 00246 00247 //only train on num of objects 00248 if (itsNumObjects != -1 && i++ > itsNumObjects) 00249 break; 00250 } 00251 LDEBUG("%"ZU" scenes in the directory\n", itsSceneFilenames.size()); 00252 } else LFATAL("%s is not a directory", path); 00253 } 00254 00255 // ###################################################################### 00256 Image<PixRGB<byte> > TestImages::getObject(int id, int lum, int col, int rot) 00257 { 00258 std::string filename; 00259 00260 switch (itsLibType) { 00261 case ALOI: 00262 { 00263 static int idNumber = 0; 00264 static int lumNumber = 0; 00265 static int colNumber = 0; 00266 static int rotNumber = 0; 00267 00268 if (id == -1) id = idNumber++; 00269 id = (id % 1000) + 1; //only 1000 objects are avilable 00270 00271 if (lum == -1) lum = lumNumber++; 00272 if (col == -1) col = colNumber++; 00273 if (rot == -1) rot = rotNumber++; 00274 00275 if (lum > -1) { 00276 lum = lum%itsMaxLum; //dont overflow 00277 filename = sformat("%s/%i/%i_%s.png", itsImagesPath, 00278 id, id,ALOI_LUM[lum]); 00279 } else if (col > -1) { 00280 col = col%itsMaxCol; //dont overflow 00281 filename = sformat("%s/%i/%i_%s.png", itsImagesPath, 00282 id, id,ALOI_COL[col]); 00283 } else if (rot > -1) { 00284 rot = rot%itsMaxRot; //dont overflow 00285 filename = sformat("%s/%i/%i_%s.png", itsImagesPath, 00286 id, id,ALOI_ROT[rot]); 00287 } 00288 } 00289 break; 00290 00291 case CSAIL: 00292 break; 00293 00294 case COIL: 00295 { 00296 static int idNumber = 0; 00297 static int rotNumber = 0; 00298 00299 if (id == -1) id = idNumber++; 00300 id = id % 100 + 1; //only 100 objects are avilable 00301 00302 if (rot == -1) rot = rotNumber += 5; 00303 else rot *= 5; 00304 00305 rot = rot % 360; 00306 00307 filename = sformat("%s/obj%i__%i.png", itsImagesPath, id, rot); 00308 } 00309 break; 00310 00311 case CSCLAB: 00312 return getCscLabObj(id); 00313 break; 00314 00315 case IMG_DIR: 00316 { 00317 static int idNumber = 0; 00318 00319 if (id == -1) id = idNumber++; 00320 id = id % itsSceneFilenames.size(); 00321 00322 filename = sformat("%s/%s", itsImagesPath, itsSceneFilenames[id].c_str()); 00323 } 00324 break; 00325 00326 case MIT_LABELME: 00327 return getLabelMeObj(id); 00328 break; 00329 00330 default: 00331 LERROR("Unknown lib type"); 00332 } 00333 00334 return Raster::ReadRGB(filename); 00335 } 00336 00337 00338 // ###################################################################### 00339 TestImages::ObjData TestImages::getObjectData(uint scene, uint obj, 00340 bool getImage) 00341 { 00342 ASSERT(scene < itsScenes.size() && obj < itsScenes[scene].objects.size()); 00343 00344 ObjData objData = itsScenes[scene].objects[obj]; 00345 00346 if (getImage) { 00347 // find the object dimention from the polygon: 00348 00349 // tranform the outline (becuase of the crop) 00350 std::vector<Point2D<int> > newObjOutline; 00351 00352 if (objData.polygon.size() > 0) 00353 { 00354 Point2D<int> upperLeft = objData.polygon[0]; 00355 Point2D<int> lowerRight = objData.polygon[0]; 00356 for(uint i=0; i<objData.polygon.size(); i++) 00357 { 00358 // find the bounds for the crop 00359 if (objData.polygon[i].i < upperLeft.i) 00360 upperLeft.i = objData.polygon[i].i; 00361 if (objData.polygon[i].j < upperLeft.j) 00362 upperLeft.j = objData.polygon[i].j; 00363 if (objData.polygon[i].i > lowerRight.i) 00364 lowerRight.i = objData.polygon[i].i; 00365 if (objData.polygon[i].j > lowerRight.j) 00366 lowerRight.j = objData.polygon[i].j; 00367 } 00368 00369 // getting object from the scene 00370 objData.img = Raster::ReadRGB(itsScenes[scene].filename); 00371 // check for out of bounds and fix 00372 if (upperLeft.i < 0) upperLeft.i = 0; 00373 if (upperLeft.j < 0) upperLeft.j = 0; 00374 if (lowerRight.i < 0) lowerRight.i = 0; 00375 if (lowerRight.j < 0) lowerRight.j = 0; 00376 if (lowerRight.i > objData.img.getWidth()) 00377 lowerRight.i = objData.img.getWidth(); 00378 if (lowerRight.j > objData.img.getHeight()) 00379 lowerRight.j = objData.img.getHeight(); 00380 00381 objData.dims = Dims(lowerRight.i-upperLeft.i-1, 00382 lowerRight.j-upperLeft.j-1); 00383 00384 for (uint i=0; i<objData.polygon.size(); i++) 00385 newObjOutline.push_back(Point2D<int>(objData.polygon[i].i - 00386 upperLeft.i, 00387 objData.polygon[i].j - 00388 upperLeft.j)); 00389 00390 // LINFO("Cropping %ix%i, size: %ix%i\n", 00391 // upperLeft.i, upperLeft.j, 00392 // objData.dims.h(), objData.dims.w()); 00393 objData.img = crop(objData.img, upperLeft, objData.dims); 00394 } 00395 00396 if (!objData.filename.empty()) 00397 objData.img = Raster::ReadRGB(objData.filename); 00398 } 00399 return objData; 00400 } 00401 00402 // ###################################################################### 00403 TestImages::SceneData TestImages::getSceneData(uint scene, USETYPE useType) 00404 { 00405 switch (useType) { 00406 case TRAIN: 00407 ASSERT(scene < itsTrainScenes.size()); 00408 return itsTrainScenes[scene]; 00409 break; 00410 00411 case TEST: 00412 ASSERT(scene < itsTestScenes.size()); 00413 return itsTestScenes[scene]; 00414 break; 00415 00416 default: 00417 ASSERT(scene < itsScenes.size()); 00418 return itsScenes[scene]; 00419 break; 00420 } 00421 } 00422 00423 // ###################################################################### 00424 TestImages::ObjData TestImages::getObjFromPos(uint scene, 00425 const Point2D<int> &pt) 00426 { 00427 ASSERT(scene < itsScenes.size()); 00428 00429 ObjData objData; 00430 for(uint obj=0; obj<itsScenes[scene].objects.size(); obj++) 00431 { 00432 objData = itsScenes[scene].objects[obj]; 00433 00434 // find the object dimention from the polygon 00435 if (objData.polygon.size() > 0) 00436 { 00437 Point2D<int> upperLeft = objData.polygon[0]; 00438 Point2D<int> lowerRight = objData.polygon[0]; 00439 00440 for(uint i=0; i<objData.polygon.size(); i++) 00441 { 00442 // find the bounds for the crop 00443 if (objData.polygon[i].i < upperLeft.i) 00444 upperLeft.i = objData.polygon[i].i; 00445 if (objData.polygon[i].j < upperLeft.j) 00446 upperLeft.j = objData.polygon[i].j; 00447 if (objData.polygon[i].i > lowerRight.i) 00448 lowerRight.i = objData.polygon[i].i; 00449 if (objData.polygon[i].j > lowerRight.j) 00450 lowerRight.j = objData.polygon[i].j; 00451 } 00452 00453 // check if point is within the polygon 00454 for (int y = upperLeft.j; y < lowerRight.j; y++) 00455 for (int x = upperLeft.i; x < lowerRight.i; x++) 00456 if(pnpoly(objData.polygon, pt)) return objData; 00457 return objData; 00458 } 00459 } 00460 00461 return objData; 00462 } 00463 00464 // ###################################################################### 00465 Image<PixRGB<byte> > TestImages::generateScene(uint scene) 00466 { 00467 ASSERT(scene < itsScenes.size()); 00468 00469 Image<PixRGB<byte> > sceneImg; 00470 if (itsScenes[scene].filename.empty()) 00471 sceneImg = Image<PixRGB<byte> >(itsScenes[scene].dims, NO_INIT); 00472 else 00473 { 00474 sceneImg = Raster::ReadRGB(itsScenes[scene].filename); 00475 sceneImg = rescale(sceneImg, itsScenes[scene].dims); //resize the image 00476 } 00477 00478 for(uint obj=0; obj<itsScenes[scene].objects.size(); obj++) 00479 { 00480 ObjData objData = getObjectData(scene,obj); 00481 if (objData.dims.w() > 0 && objData.dims.h() > 0) 00482 // use the first point to place the object 00483 if (objData.polygon.size() > 0) 00484 { 00485 if (itsScenes[scene].filename.empty()) { 00486 // this is a generated background 00487 inplacePaste(sceneImg, objData.img, objData.polygon[0]); 00488 } else 00489 pasteImage(sceneImg, objData.img, PixRGB<byte>(0,0,0), 00490 objData.polygon[0], 0.5F); 00491 } 00492 } 00493 return sceneImg; 00494 } 00495 00496 // ###################################################################### 00497 Image<PixRGB<byte> > TestImages::getCscLabObj(int id) 00498 { 00499 std::vector<Point2D<int> > objOutline = getObjPolygon(id); 00500 00501 std::string filename = std::string(itsImagesPath) + "/images/" + 00502 itsSceneFilenames[itsSceneId]; 00503 filename.replace(filename.size()-4, 4, "-R.png"); //change extention to xml 00504 Image<PixRGB<byte> > objImg = Raster::ReadRGB(filename); 00505 00506 // crop the object in the scene 00507 Point2D<int> upperLeft = objOutline[0]; 00508 Dims size(objOutline[2].i-objOutline[0].i, 00509 objOutline[2].j-objOutline[0].j); 00510 00511 return(crop(objImg, upperLeft, size)); 00512 } 00513 00514 // ###################################################################### 00515 Image<PixRGB<byte> > TestImages::getLabelMeObj(int id) 00516 { 00517 std::vector<Point2D<int> > objOutline = getObjPolygon(id); 00518 00519 Image<PixRGB<byte> > objImg = 00520 Raster::ReadRGB(std::string(itsImagesPath) + '/' + 00521 itsSceneFilenames[itsSceneId]); 00522 00523 // crop the object in the scene 00524 Point2D<int> upperLeft = objOutline[0]; 00525 Point2D<int> lowerRight = objOutline[0]; 00526 for(uint i=0; i<objOutline.size(); i++) 00527 { 00528 // find the bounds for the crop 00529 if (objOutline[i].i < upperLeft.i) upperLeft.i = objOutline[i].i; 00530 if (objOutline[i].j < upperLeft.j) upperLeft.j = objOutline[i].j; 00531 00532 if (objOutline[i].i > lowerRight.i) lowerRight.i = objOutline[i].i; 00533 if (objOutline[i].j > lowerRight.j) lowerRight.j = objOutline[i].j; 00534 00535 } 00536 00537 // tranforme the outline (becuase of the crop) 00538 std::vector<Point2D<int> > newObjOutline; 00539 for(uint i=0; i<objOutline.size(); i++) 00540 newObjOutline.push_back(Point2D<int>(objOutline[i].i - upperLeft.i, 00541 objOutline[i].j - upperLeft.j)); 00542 00543 Dims size(lowerRight.i-upperLeft.i, lowerRight.j - upperLeft.j); 00544 objImg = crop(objImg, upperLeft, size); 00545 00546 //clear all pixels outsize the polygon 00547 for(int y=0; y<objImg.getHeight(); y++) 00548 for(int x=0; x<objImg.getWidth(); x++) 00549 { 00550 if (!pnpoly(newObjOutline, Point2D<int>(x, y))) 00551 objImg.setVal(x,y,PixRGB<byte>(0,0,0)); //clear the pixel 00552 } 00553 00554 return(objImg); 00555 } 00556 00557 // ###################################################################### 00558 uint TestImages::getMaxLum() 00559 { 00560 return itsMaxLum; 00561 } 00562 00563 // ###################################################################### 00564 uint TestImages::getMaxCol() 00565 { 00566 return itsMaxCol; 00567 } 00568 00569 // ###################################################################### 00570 uint TestImages::getMaxRot() 00571 { 00572 switch (itsLibType){ 00573 case ALOI: 00574 return itsMaxRot; 00575 case CSAIL: 00576 break; 00577 case COIL: 00578 return 360/5; 00579 default: 00580 LERROR("Unknown lib type"); 00581 } 00582 return 0; 00583 } 00584 00585 // ###################################################################### 00586 uint TestImages::getNumScenes(USETYPE useType) 00587 { 00588 switch (itsLibType){ 00589 case MIT_LABELME: 00590 return itsSceneFilenames.size(); 00591 case CALTECH256: 00592 switch (useType) 00593 { 00594 case TRAIN: 00595 return itsTrainScenes.size(); 00596 break; 00597 case TEST: 00598 return itsTestScenes.size(); 00599 break; 00600 default: 00601 return itsScenes.size(); 00602 break; 00603 } 00604 case XMLFILE: 00605 return itsScenes.size(); 00606 default: 00607 LERROR("Unknown lib type"); 00608 } 00609 return 0; 00610 } 00611 00612 // ###################################################################### 00613 Image<PixRGB<byte> > TestImages::getScene(uint sceneId, USETYPE useType) 00614 { 00615 switch (itsLibType){ 00616 case ALOI: 00617 break; 00618 case CSAIL: 00619 break; 00620 case COIL: 00621 break; 00622 case MIT_LABELME: 00623 return getLabelMeScene(sceneId); 00624 case CSCLAB: 00625 return getCscLabScene(sceneId); 00626 case XMLFILE: 00627 ASSERT(sceneId < itsScenes.size()); 00628 if ((int)itsScenes[sceneId].type.find("Embed") != -1 || 00629 (int)itsScenes[sceneId].type.find("Array") != -1) 00630 { 00631 LDEBUG("Generating scene from objects"); 00632 return generateScene(sceneId); 00633 } else { 00634 return Raster::ReadRGB(itsScenes[sceneId].filename); 00635 } 00636 case CALTECH256: 00637 switch (useType) 00638 { 00639 case TRAIN: 00640 ASSERT(sceneId < itsTrainScenes.size()); 00641 return Raster::ReadRGB(itsTrainScenes[sceneId].filename); 00642 break; 00643 case TEST: 00644 ASSERT(sceneId < itsTestScenes.size()); 00645 return Raster::ReadRGB(itsTestScenes[sceneId].filename); 00646 break; 00647 default: 00648 ASSERT(sceneId < itsScenes.size()); 00649 return Raster::ReadRGB(itsScenes[sceneId].filename); 00650 break; 00651 } 00652 default: 00653 LERROR("Unknown lib type"); 00654 } 00655 00656 return Image<PixRGB<byte> >(); 00657 } 00658 00659 // ###################################################################### 00660 std::string TestImages::getSceneFilename(uint sceneId) 00661 { 00662 switch (itsLibType){ 00663 case ALOI: 00664 break; 00665 case CSAIL: 00666 break; 00667 case COIL: 00668 break; 00669 case MIT_LABELME: 00670 return itsSceneFilenames[sceneId]; 00671 case CSCLAB: 00672 return itsSceneFilenames[sceneId]; 00673 break; 00674 case XMLFILE: 00675 return itsSceneFilenames[sceneId]; 00676 break; 00677 default: 00678 LERROR("Unknown lib type"); 00679 } 00680 00681 return std::string(); 00682 } 00683 00684 // ###################################################################### 00685 Image<PixRGB<byte> > TestImages::getLabelMeScene(uint sceneId) 00686 { 00687 #ifdef HAVE_LIBXML 00688 ASSERT(sceneId < itsSceneFilenames.size()); 00689 00690 xmlDocPtr doc; 00691 00692 //Get the xml file for the given scene 00693 std::string xmlFile = std::string(itsImagesPath); 00694 xmlFile.insert(xmlFile.rfind("/"), "/Annotations"); //set the Annotations dir 00695 xmlFile += "/" + itsSceneFilenames[sceneId]; 00696 xmlFile.replace(xmlFile.size()-4, 4, ".xml"); //change extention to xml 00697 00698 itsCurrentScene = Raster::ReadRGB(std::string(itsImagesPath) + '/' + 00699 itsSceneFilenames[sceneId]); 00700 00701 //clear the objname and polygons 00702 itsObjNames.clear(); 00703 itsObjPolygon.clear(); 00704 00705 //check if the file exists 00706 doc = xmlReadFile(xmlFile.c_str(), NULL, 0); 00707 if (doc == NULL) 00708 { 00709 LINFO("Failed to parse %s", xmlFile.c_str()); 00710 return itsCurrentScene; 00711 } 00712 00713 /*Get the root element node */ 00714 xmlNode *root_element = xmlDocGetRootElement(doc); 00715 00716 //look for object annotations 00717 xmlNodePtr cur = root_element->xmlChildrenNode; //dont care about toop level 00718 while (cur != NULL) { 00719 if ((!xmlStrcmp(cur->name, (const xmlChar *)"object"))) { 00720 00721 xmlNodePtr object = cur->xmlChildrenNode; 00722 while(object != NULL) //read the attributes and polygons 00723 { 00724 //Name 00725 if ((!xmlStrcmp(object->name, (const xmlChar *)"name"))) { 00726 xmlChar* name = xmlNodeListGetString(doc, object->xmlChildrenNode, 1); 00727 if (name != NULL) 00728 { 00729 itsObjNames.push_back(std::string((const char*)name)); 00730 xmlFree(name); 00731 } 00732 } 00733 00734 //Polygon 00735 //Read the points 00736 if ((!xmlStrcmp(object->name, (const xmlChar *)"polygon"))) { 00737 xmlNodePtr poly = object->xmlChildrenNode; 00738 00739 std::vector<Point2D<int> > points; 00740 while(poly != NULL) //read the attributes and polygons 00741 { 00742 //Get a point 00743 if ((!xmlStrcmp(poly->name, (const xmlChar *)"pt"))) { 00744 00745 //get Point x and Point y 00746 00747 int x = -1, y = -1; 00748 xmlNodePtr point = poly->xmlChildrenNode; 00749 while (point != NULL) 00750 { 00751 if ((!xmlStrcmp(point->name, (const xmlChar *)"x"))) { 00752 xmlChar* xLoc = 00753 xmlNodeListGetString(doc, point->xmlChildrenNode, 1); 00754 x = atoi((const char*)xLoc); 00755 xmlFree(xLoc); 00756 } 00757 00758 if ((!xmlStrcmp(point->name, (const xmlChar *)"y"))) { 00759 xmlChar* yLoc = 00760 xmlNodeListGetString(doc, point->xmlChildrenNode, 1); 00761 y = atoi((const char*)yLoc); 00762 xmlFree(yLoc); 00763 } 00764 point = point->next; //next 00765 } 00766 points.push_back(Point2D<int>(x,y)); 00767 } 00768 poly = poly->next; //next point 00769 } 00770 itsObjPolygon.push_back(points); 00771 } 00772 object = object->next; //next object 00773 } 00774 } 00775 cur = cur->next; 00776 } 00777 xmlFreeDoc(doc); 00778 xmlCleanupParser(); 00779 00780 #else 00781 LFATAL("Need xmllib to parse scene files"); 00782 #endif 00783 00784 return itsCurrentScene; 00785 } 00786 00787 // ###################################################################### 00788 // get only the right images 00789 Image<PixRGB<byte> > TestImages::getCscLabScene(uint sceneId) 00790 { 00791 #ifdef HAVE_LIBXML 00792 ASSERT(sceneId < itsSceneFilenames.size()); 00793 00794 xmlDocPtr doc; 00795 00796 //Get the xml file for the given scene 00797 std::string xmlFile = std::string(itsImagesPath) + "/" + 00798 itsSceneFilenames[sceneId]; 00799 00800 doc = xmlReadFile(xmlFile.c_str(), NULL, 0); 00801 if (doc == NULL) 00802 LFATAL("Failed to parse %s", xmlFile.c_str()); 00803 00804 //clear the objname and polygons 00805 itsObjNames.clear(); 00806 itsObjPolygon.clear(); 00807 00808 /*Get the root element node */ 00809 xmlNode *root_element = xmlDocGetRootElement(doc); 00810 00811 //look for object annotations 00812 xmlNodePtr cur = root_element->xmlChildrenNode; //dont care about toop level 00813 while (cur != NULL) { 00814 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Object"))) { 00815 00816 xmlChar* name = xmlGetProp(cur, (const xmlChar*)"id"); 00817 itsObjNames.push_back(std::string((const char*)name)); 00818 xmlFree(name); 00819 00820 xmlNodePtr object = cur->xmlChildrenNode; 00821 while(object != NULL) //read the attributes and polygons 00822 { 00823 //Get right Polygon 00824 if ((!xmlStrcmp(object->name, (const xmlChar *)"Box")) && 00825 !xmlStrcmp(xmlGetProp(object, (const xmlChar*)"side"), 00826 (const xmlChar*)"right")) 00827 { 00828 int left, top, width, height; 00829 xmlChar* data; 00830 00831 data = xmlGetProp(object, (const xmlChar*)"left"); 00832 left = atoi((const char*)data); 00833 xmlFree(data); 00834 00835 data = xmlGetProp(object, (const xmlChar*)"top"); 00836 top = atoi((const char*)data); 00837 xmlFree(data); 00838 00839 data = xmlGetProp(object, (const xmlChar*)"width"); 00840 width = atoi((const char*)data); 00841 xmlFree(data); 00842 00843 data = xmlGetProp(object, (const xmlChar*)"height"); 00844 height = atoi((const char*)data); 00845 xmlFree(data); 00846 00847 //make a polygon 00848 std::vector<Point2D<int> > points; 00849 points.push_back(Point2D<int>(left, top)); 00850 points.push_back(Point2D<int>(left+width, top)); 00851 points.push_back(Point2D<int>(left+width, top+height)); 00852 points.push_back(Point2D<int>(left, top+height)); 00853 itsObjPolygon.push_back(points); 00854 } 00855 object = object->next; //next object 00856 } 00857 } 00858 cur = cur->next; 00859 } 00860 xmlFreeDoc(doc); 00861 xmlCleanupParser(); 00862 00863 #else 00864 LFATAL("Need xmllib to parse scene files"); 00865 #endif 00866 00867 itsSceneId = sceneId; 00868 std::string filename = std::string(itsImagesPath) + "/images/" + 00869 itsSceneFilenames[sceneId]; 00870 filename.replace(filename.size()-4, 4, "-R.png"); //change extention to xml 00871 return Raster::ReadRGB(filename); 00872 } 00873 00874 // ###################################################################### 00875 const char* TestImages::getObjName(uint id) 00876 { 00877 ASSERT(id < itsObjNames.size()); 00878 return itsObjNames[id].c_str(); 00879 } 00880 00881 // ###################################################################### 00882 std::vector<Point2D<int> > TestImages::getObjPolygon(uint id) 00883 { 00884 ASSERT(id < itsObjPolygon.size()); 00885 return itsObjPolygon[id]; 00886 } 00887 00888 // ###################################################################### 00889 Image<byte> TestImages::getObjMask(uint obj) 00890 { 00891 std::vector<Point2D<int> > objOutline = getObjPolygon(obj); 00892 Image<byte> objMask(itsCurrentScene.getDims(), ZEROS); 00893 drawFilledPolygon(objMask, objOutline, byte(255)); 00894 00895 return objMask; 00896 } 00897 00898 // ###################################################################### 00899 Image<byte> TestImages::getObjMask(uint scene, uint obj) 00900 { 00901 ASSERT(scene < itsScenes.size() && obj < itsScenes[scene].objects.size()); 00902 00903 SceneData sceneData = itsScenes[scene]; 00904 ObjData objData = itsScenes[scene].objects[obj]; 00905 std::vector<Point2D<int> > objOutline = objData.polygon; 00906 00907 Image<byte> objMask(sceneData.dims, ZEROS); 00908 LDEBUG("Mask %ix%i\n", objMask.getWidth(), objMask.getHeight()); 00909 drawFilledPolygon(objMask, objOutline, byte(255)); 00910 00911 return objMask; 00912 } 00913 00914 // ###################################################################### 00915 Image<byte> TestImages::getObjMask(uint scene, uint obj, const Dims& sceneDims) 00916 { 00917 ASSERT(scene < itsScenes.size() && obj < itsScenes[scene].objects.size()); 00918 00919 ObjData objData = itsScenes[scene].objects[obj]; 00920 std::vector<Point2D<int> > objOutline = objData.polygon; 00921 00922 Image<byte> objMask(sceneDims, ZEROS); 00923 LDEBUG("Mask %ix%i\n", objMask.getWidth(), objMask.getHeight()); 00924 drawFilledPolygon(objMask, objOutline, byte(255)); 00925 00926 return objMask; 00927 } 00928 00929 // ###################################################################### 00930 Image<byte> TestImages::getAllObjMask() 00931 { 00932 Image<byte> objMask(2560, 1920, ZEROS); 00933 00934 //clear all pixels outsize the polygon 00935 for (int y = 0; y < objMask.getHeight(); y++) 00936 for (int x = 0; x < objMask.getWidth(); x++) 00937 { 00938 for(uint obj = 0; obj < getNumObj(); obj++) 00939 { 00940 std::vector<Point2D<int> > objOutline = getObjPolygon(obj); 00941 if (pnpoly(objOutline, Point2D<int>(x, y))) 00942 { 00943 objMask.setVal(x, y, byte(255)); 00944 break; //no need to check other objects. 00945 } 00946 } 00947 } 00948 00949 return(objMask); 00950 } 00951 00952 // ###################################################################### 00953 void TestImages::readObjXML(const char *filename) 00954 { 00955 #ifdef HAVE_LIBXML 00956 xmlDocPtr doc; 00957 00958 // Get the xml file for the given scene: 00959 std::string xmlFile; 00960 00961 if (itsCurrentPath.empty()) 00962 { 00963 xmlFile = std::string(filename); 00964 itsCurrentPath = xmlFile.substr(0, xmlFile.rfind('/')); 00965 } else { 00966 xmlFile = itsCurrentPath + '/' + std::string(filename); 00967 } 00968 00969 //Get the root dir 00970 LDEBUG("Reading %s", xmlFile.c_str()); 00971 00972 // check if the file exists: 00973 doc = xmlReadFile(xmlFile.c_str(), NULL, 0); 00974 if (doc == NULL) { 00975 LINFO("Failed to parse %s", xmlFile.c_str()); 00976 return; 00977 } 00978 00979 /* Get the root element node */ 00980 xmlNode *root_element = xmlDocGetRootElement(doc); 00981 00982 // look for object annotations 00983 xmlNodePtr cur = root_element; //->xmlChildrenNode; //dont care about top level 00984 00985 //Skip the top level if scenes is in the name 00986 if ((!xmlStrcmp(cur->name, (const xmlChar *)"scenes"))) 00987 cur = root_element->xmlChildrenNode; //dont care about top level 00988 00989 while (cur != NULL) { 00990 // check for dir paths 00991 if ((!xmlStrcmp(cur->name, (const xmlChar *)"dir"))) { 00992 xmlChar* incPath = xmlGetProp(cur, (const xmlChar*)"path"); 00993 LDEBUG("Setting Path to %s", (const char *)incPath); 00994 itsCurrentPath = std::string((const char *)incPath); 00995 xmlFree(incPath); 00996 } 00997 00998 // check for include directives: 00999 if ((!xmlStrcmp(cur->name, (const xmlChar *)"include"))) { 01000 xmlChar* incFileName = xmlGetProp(cur, (const xmlChar*)"filename"); 01001 LDEBUG("Including file %s", (const char *)incFileName); 01002 readObjXML((const char *)incFileName); 01003 xmlFree(incFileName); 01004 } 01005 01006 // get the objects from the scene: 01007 if ((!xmlStrcmp(cur->name, (const xmlChar *)"annotation"))) { 01008 // get the scene data: 01009 xmlNodePtr scenePtr = cur->xmlChildrenNode; 01010 01011 std::string sceneFilename, sceneFolder, sceneDescription, sceneType; 01012 Dims sceneDims; 01013 std::vector<ObjData> objects; 01014 01015 // new scene: 01016 while(scenePtr != NULL) { // read the attributes and polygons 01017 getNodeMatchText(doc, scenePtr, "filename", sceneFilename); 01018 getNodeMatchText(doc, scenePtr, "folder", sceneFolder); 01019 getNodeMatchText(doc, scenePtr, "description", sceneDescription); 01020 01021 // get the scene size: 01022 if ((!xmlStrcmp(scenePtr->name, (const xmlChar *)"specs"))) { 01023 LDEBUG("Specs %s", sceneDescription.c_str()); 01024 xmlChar* width = xmlGetProp(scenePtr, (const xmlChar*)"width"); 01025 xmlChar* height = xmlGetProp(scenePtr, (const xmlChar*)"height"); 01026 xmlChar* type = xmlGetProp(scenePtr, (const xmlChar*)"type"); 01027 LDEBUG("Dims set %s %s", (char*)width, (char*)height); 01028 if (width != NULL && height != NULL) 01029 sceneDims = Dims(atoi((char *)width), atoi((char *)height)); 01030 if (type != NULL) 01031 sceneType = std::string((const char *)type); 01032 xmlFree(width); 01033 xmlFree(height); 01034 xmlFree(type); 01035 } 01036 01037 // get the object details from the scene: 01038 if ((!xmlStrcmp(scenePtr->name, (const xmlChar *)"object"))) { 01039 std::string objId, objName, objDescription, objFilename, objFolder; 01040 std::vector<Point2D<int> > objPolygon; 01041 Dims objDims(0,0); Image<byte> objMask; 01042 01043 xmlNodePtr objectPtr = scenePtr->xmlChildrenNode; 01044 while(objectPtr != NULL) { // read the attributes and polygons 01045 getNodeMatchText(doc, objectPtr, "id", objId); 01046 getNodeMatchText(doc, objectPtr, "description", objDescription); 01047 getNodeMatchText(doc, objectPtr, "name", objName); 01048 getNodeMatchText(doc, objectPtr, "filename", objFilename); 01049 getNodeMatchText(doc, objectPtr, "folder", objFolder); 01050 01051 01052 // Polygon: Read the points 01053 if ((!xmlStrcmp(objectPtr->name, (const xmlChar *)"polygon"))) { 01054 xmlNodePtr poly = objectPtr->xmlChildrenNode; 01055 01056 while(poly != NULL) { // read the attributes and polygons 01057 // Get a point 01058 if ((!xmlStrcmp(poly->name, (const xmlChar *)"pt"))) { 01059 // get Point x and Point y: 01060 std::string xStr,yStr; 01061 xmlNodePtr point = poly->xmlChildrenNode; 01062 while (point != NULL) { 01063 getNodeMatchText(doc, point, "x", xStr); 01064 getNodeMatchText(doc, point, "y", yStr); 01065 point = point->next; //next 01066 } 01067 objPolygon.push_back(Point2D<int>(atoi(xStr.c_str()), 01068 atoi(yStr.c_str()))); 01069 } 01070 poly = poly->next; //next point 01071 } 01072 } 01073 01074 //Read the bounding box 01075 if ((!xmlStrcmp(objectPtr->name, (const xmlChar *)"bndbox"))) { 01076 xmlNodePtr bboxPtr = objectPtr->xmlChildrenNode; 01077 std::string xmin, xmax, ymin, ymax; 01078 while(bboxPtr != NULL) { // read the box size 01079 getNodeMatchText(doc, bboxPtr, "xmin", xmin); 01080 getNodeMatchText(doc, bboxPtr, "xmax", xmax); 01081 getNodeMatchText(doc, bboxPtr, "ymin", ymin); 01082 getNodeMatchText(doc, bboxPtr, "ymax", ymax); 01083 bboxPtr = bboxPtr->next; //next point 01084 } 01085 objPolygon.push_back(Point2D<int>(atoi(xmin.c_str()), 01086 atoi(ymin.c_str()))); 01087 objPolygon.push_back(Point2D<int>(atoi(xmax.c_str()), 01088 atoi(ymin.c_str()))); 01089 objPolygon.push_back(Point2D<int>(atoi(xmax.c_str()), 01090 atoi(ymax.c_str()))); 01091 objPolygon.push_back(Point2D<int>(atoi(xmin.c_str()), 01092 atoi(ymax.c_str()))); 01093 } 01094 01095 // object mask file? 01096 std::string objmaskfile; 01097 getNodeMatchText(doc, objectPtr, "objectmask", objmaskfile); 01098 if (objmaskfile.empty() == false) { 01099 if (objFolder.empty() == false) 01100 objmaskfile = objFolder+"/"+objmaskfile; 01101 Image<byte> timg = Raster::ReadGray(objmaskfile); 01102 if (objMask.initialized()) objMask += timg; // will clamp to 255 01103 else objMask = timg; 01104 } 01105 01106 // next object data: 01107 objectPtr = objectPtr->next; 01108 } 01109 01110 // LINFO("Read object %s (id %s) in %s",objName.c_str(), 01111 // objId.c_str(),sceneFilename.c_str()); 01112 01113 // assign the object data to array: 01114 if (objPolygon.size() < 3 && objMask.initialized() == false) 01115 LINFO("Error: insufficent points in the polygon (%s)", xmlFile.c_str()); 01116 else { 01117 ObjData objData; 01118 01119 01120 if (!objFilename.empty()) { 01121 if (itsCurrentPath.empty()) 01122 objData.filename = objFolder + '/' + objFilename; 01123 else 01124 objData.filename = itsCurrentPath + '/' + objFolder + 01125 '/' + objFilename; 01126 } 01127 objData.id = atoi(objId.c_str()); 01128 01129 // Replace spaces in objname with _ 01130 for (std::string::iterator i = objName.begin(); 01131 i != objName.end(); i++) 01132 if (std::isspace(*i)) *i = '_'; 01133 01134 objData.name = objName; 01135 objData.description = objDescription; 01136 objData.dims = objDims; 01137 objData.polygon = objPolygon; 01138 objData.objmask = objMask; 01139 objects.push_back(objData); 01140 } 01141 } 01142 scenePtr = scenePtr->next; //next scene data 01143 } 01144 SceneData sceneData; 01145 01146 //Hack for PASCAL dataset since the folder points to VOC2009/JPEGImages 01147 if (sceneFolder == "VOC2009") 01148 sceneFolder += "/JPEGImages"; 01149 01150 if (!sceneFilename.empty()) { 01151 if (itsCurrentPath.empty()) 01152 sceneData.filename = sceneFolder + '/' + sceneFilename; 01153 else 01154 sceneData.filename = itsCurrentPath + '/' + sceneFolder + 01155 '/' + sceneFilename; 01156 } 01157 01158 LDEBUG("Scene %s", sceneData.filename.c_str()); 01159 sceneData.description = sceneDescription; 01160 sceneData.dims = sceneDims; 01161 sceneData.type = sceneType; 01162 sceneData.objects = objects; 01163 01164 itsScenes.push_back(sceneData); 01165 } 01166 cur = cur->next; 01167 } 01168 01169 xmlFreeDoc(doc); 01170 xmlCleanupParser(); 01171 01172 #else 01173 LFATAL("Need xmllib to parse scene files"); 01174 #endif 01175 01176 return; 01177 01178 } 01179 01180 // ###################################################################### 01181 #ifdef HAVE_LIBXML 01182 void TestImages::getNodeMatchText(xmlDocPtr doc, xmlNodePtr nodePtr, 01183 const char* nodeName, std::string &result) 01184 { 01185 xmlChar *tmp = NULL; 01186 if (!xmlStrcmp(nodePtr->name, (const xmlChar *)nodeName)) 01187 tmp = xmlNodeListGetString(doc, nodePtr->xmlChildrenNode, 1); 01188 01189 if (tmp != NULL) { 01190 result = std::string((const char*)tmp); 01191 xmlFree(tmp); 01192 } 01193 } 01194 #endif // HAVE_LIBXML 01195 01196 // ###################################################################### 01197 int TestImages::labelScene(uint scene, Image<PixRGB<byte> > &sceneImg) 01198 { 01199 //draw an outline of the object in the scene 01200 int lineWidth = int(sceneImg.getWidth()*0.005); 01201 01202 for (uint obj=0; obj<getNumObj(scene); obj++) //look at all the objects in the scene 01203 { 01204 01205 ObjData objData = getObjectData(scene, obj); 01206 01207 std::vector<Point2D<int> > objPoly = objData.polygon; 01208 Point2D<int> p1 = objPoly[0]; 01209 Point2D<int> centerLoc = p1; 01210 for(uint i=1; i<objPoly.size(); i++) 01211 { 01212 drawLine(sceneImg, p1, objPoly[i], PixRGB<byte>(255, 0, 0), lineWidth); 01213 p1 = objPoly[i]; 01214 centerLoc.i += p1.i; centerLoc.j += p1.j; 01215 } 01216 drawLine(sceneImg, p1, objPoly[0], PixRGB<byte>(255, 0, 0), lineWidth); //close the polygon 01217 01218 centerLoc.i /= objPoly.size(); 01219 centerLoc.j /= objPoly.size(); 01220 writeText(sceneImg, centerLoc, objData.description.c_str(), PixRGB<byte>(255), PixRGB<byte>(0)); 01221 } 01222 01223 return 1; 01224 01225 } 01226 01227 // ###################################################################### 01228 /* So things look consistent in everyone's emacs... */ 01229 /* Local Variables: */ 01230 /* indent-tabs-mode: nil */ 01231 /* End: */