00001 /*!@file MBARI/MbariResultViewer.C class that manages the results viewing and 00002 saving for the MBARI programs */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00006 // by the University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Dirk Walther <walther@caltech.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/MBARI/MbariResultViewer.C $ 00036 // $Id: MbariResultViewer.C 9412 2008-03-10 23:10:15Z farhan $ 00037 // 00038 00039 #include "MBARI/MbariResultViewer.H" 00040 00041 #include "Component/ModelManager.H" 00042 #include "Component/ModelOptionDef.H" 00043 #include "GUI/XWinManaged.H" 00044 #include "Image/CutPaste.H" // for crop() 00045 #include "Image/Image.H" 00046 #include "Image/ShapeOps.H" // for rescale() 00047 #include "Image/colorDefs.H" 00048 #include "MBARI/MbariFrameSeries.H" 00049 #include "MBARI/VisualEvent.H" 00050 #include "Media/FrameSeries.H" 00051 #include "Util/Assert.H" 00052 #include "Util/log.H" 00053 00054 #include <cstdio> 00055 #include <fstream> 00056 00057 // Format here is: 00058 // 00059 // { MODOPT_TYPE, "name", &MOC_CATEG, OPTEXP_CORE, 00060 // "description of what option does", 00061 // "long option name", 'short option name', "valid values", "default value" } 00062 // 00063 00064 // alternatively, for MODOPT_ALIAS option types, format is: 00065 // 00066 // { MODOPT_ALIAS, "", &MOC_ALIAS, OPTEXP_CORE, 00067 // "description of what alias does", 00068 // "long option name", 'short option name', "", "list of options" } 00069 // 00070 00071 // NOTE: do not change the default value of any existing option unless 00072 // you really know what you are doing! Many components will determine 00073 // their default behavior from that default value, so you may break 00074 // lots of executables if you change it. 00075 00076 // #################### MbariResultViewer options: 00077 // Used by: MbariResultViewer 00078 const ModelOptionDef OPT_MRVsaveEvents = 00079 { MODOPT_ARG_STRING, "MRVsaveEvents", &MOC_MBARIRV, OPTEXP_MRV, 00080 "Save the event structure to a text file", 00081 "mbari-save-events", '\0', "fileName", "" }; 00082 00083 // Used by: MbariResultViewer 00084 const ModelOptionDef OPT_MRVloadEvents = 00085 { MODOPT_ARG_STRING, "MRVloadEvents", &MOC_MBARIRV, OPTEXP_MRV, 00086 "Load the event structure from a text file " 00087 "instead of computing it from the frames", 00088 "mbari-load-events", '\0', "fileName", "" }; 00089 00090 // Used by: MbariResultViewer 00091 const ModelOptionDef OPT_MRVsaveProperties = 00092 { MODOPT_ARG_STRING, "MRVsaveProperties", &MOC_MBARIRV, OPTEXP_MRV, 00093 "Save the event property vector to a text file", 00094 "mbari-save-properties", '\0', "fileName", "" }; 00095 00096 // Used by: MbariResultViewer 00097 const ModelOptionDef OPT_MRVloadProperties = 00098 { MODOPT_ARG_STRING, "MRVloadProperties", &MOC_MBARIRV, OPTEXP_MRV, 00099 "Load the event property vector from a text file", 00100 "mbari-load-properties", '\0', "fileName", "" }; 00101 00102 // Used by: MbariResultViewer 00103 const ModelOptionDef OPT_MRVsavePositions = 00104 { MODOPT_ARG_STRING, "MRVsavePositions", &MOC_MBARIRV, OPTEXP_MRV, 00105 "Save the positions of events to a text file", 00106 "mbari-save-positions", '\0', "fileName", "" }; 00107 00108 // Used by: MbariResultViewer 00109 const ModelOptionDef OPT_MRVmarkInteresting = 00110 { MODOPT_ARG(BitObjectDrawMode), "MRVmarkInteresting", &MOC_MBARIRV, OPTEXP_MRV, 00111 "Way to mark interesting events in output frames of MBARI programs", 00112 "mbari-mark-interesting", '\0', "<None|Shape|Outline|BoundingBox>", 00113 "BoundingBox" }; 00114 00115 // Used by: MbariResultViewer 00116 const ModelOptionDef OPT_MRVopacity = 00117 { MODOPT_ARG(float), "MRVopacity", &MOC_MBARIRV, OPTEXP_MRV, 00118 "Opacity of shape or outline markings of events", 00119 "mbari-opacity", '\0', "<0.0 ... 1.0>", "1.0" }; 00120 00121 // Used by: MbariResultViewer 00122 const ModelOptionDef OPT_MRVmarkCandidate = 00123 { MODOPT_FLAG, "MRVmarkCandidate", &MOC_MBARIRV, OPTEXP_MRV, 00124 "Mark candidates for interesting events in output frames of MBARI programs", 00125 "mbari-mark-candidate", '\0', "", "true" }; 00126 00127 // Used by: MbariResultViewer 00128 const ModelOptionDef OPT_MRVmarkPrediction = 00129 { MODOPT_FLAG, "MRVmarkPrediction", &MOC_MBARIRV, OPTEXP_MRV, 00130 "Mark the Kalman Filter's prediction for the location of an object " 00131 "in output frames of MBARI programs", 00132 "mbari-mark-prediction", '\0', "", "false" }; 00133 00134 // Used by: MbariResultViewer 00135 const ModelOptionDef OPT_MRVmarkFOE = 00136 { MODOPT_FLAG, "MRVmarkFOE", &MOC_MBARIRV, OPTEXP_MRV, 00137 "Mark the focus of expansion in the output frames of MBARI programs", 00138 "mbari-mark-foe", '\0', "", "false" }; 00139 00140 // Used by: MbariResultViewer 00141 const ModelOptionDef OPT_MRVsaveResults = 00142 { MODOPT_FLAG, "MRVsaveResults", &MOC_MBARIRV, OPTEXP_MRV, 00143 "Save intermediate results in MBARI programs to disc", 00144 "mbari-save-results", '\0', "", "false" }; 00145 00146 // Used by: MbariResultViewer 00147 const ModelOptionDef OPT_MRVdisplayResults = 00148 { MODOPT_FLAG, "MRVdisplayResults", &MOC_MBARIRV, OPTEXP_MRV, 00149 "Display intermediate results in MBARI programs", 00150 "mbari-display-results", '\0', "", "false" }; 00151 00152 // Used by: MbariResultViewer 00153 const ModelOptionDef OPT_MRVsaveOutput = 00154 { MODOPT_FLAG, "MRVsaveOutput", &MOC_MBARIRV, OPTEXP_MRV, 00155 "Save output frames in MBARI programs", 00156 "mbari-save-output", '\0', "", "true" }; 00157 00158 // Used by: MbariResultViewer 00159 const ModelOptionDef OPT_MRVdisplayOutput = 00160 { MODOPT_FLAG, "MRVdisplayOutput", &MOC_MBARIRV, OPTEXP_MRV, 00161 "Display output frames in MBARI programs", 00162 "mbari-display-output", '\0', "", "false" }; 00163 00164 // Used by: MbariResultViewer 00165 const ModelOptionDef OPT_MRVshowEventLabels = 00166 { MODOPT_FLAG, "MRVshowEventLabels", &MOC_MBARIRV, OPTEXP_MRV, 00167 "Write event labels into the output frames", 00168 "mbari-label-events", '\0', "", "true" }; 00169 00170 // Used by: MbariResultViewer 00171 const ModelOptionDef OPT_MRVrescaleDisplay = 00172 { MODOPT_ARG(Dims), "MRVrescaleDisplay", &MOC_MBARIRV, OPTEXP_MRV, 00173 "Rescale displays to <width>x<height>, or 0x0 for no rescaling", 00174 "mbari-rescale-display", '\0', "<width>x<height>", "0x0" }; 00175 00176 // Used by: MbariResultViewer 00177 const ModelOptionDef OPT_MRVsaveEventNums = 00178 { MODOPT_ARG_STRING, "MRVsaveEventNums", &MOC_MBARIRV, OPTEXP_MRV, 00179 "Save video clips showing specific events", 00180 "mbari-save-event-clip", '\0', "ev1,ev1,...,evN; or: all", "" }; 00181 00182 // Used by: MbariResultViewer 00183 const ModelOptionDef OPT_MRVsizeAvgCache = 00184 { MODOPT_ARG(int), "MRVsizeAvgCache", &MOC_MBARIRV, OPTEXP_MRV, 00185 "The number of frames used to compute the running average", 00186 "mbari-cache-size", '\0', "<int>", "10" }; 00187 00188 00189 // ############################################################################# 00190 MbariResultViewer::MbariResultViewer(ModelManager& mgr, 00191 nub::soft_ref<OutputMbariFrameSeries> ofs) 00192 : ModelComponent(mgr, std::string("MbariResultViewer"), 00193 std::string("MbariResultViewer")), 00194 itsSaveResults(&OPT_MRVsaveResults, this), 00195 itsDisplayResults(&OPT_MRVdisplayResults, this), 00196 itsMarkInteresting(&OPT_MRVmarkInteresting, this), 00197 itsOpacity(&OPT_MRVopacity, this), 00198 itsMarkCandidate(&OPT_MRVmarkCandidate, this), 00199 itsMarkPrediction(&OPT_MRVmarkPrediction, this), 00200 itsMarkFOE(&OPT_MRVmarkFOE, this), 00201 itsSaveOutput(&OPT_MRVsaveOutput, this), 00202 itsDisplayOutput(&OPT_MRVdisplayOutput, this), 00203 itsShowEventLabels(&OPT_MRVshowEventLabels, this), 00204 itsRescaleDisplay(&OPT_MRVrescaleDisplay, this), 00205 itsSizeAvgCache(&OPT_MRVsizeAvgCache, this), 00206 itsSaveEventsName(&OPT_MRVsaveEvents, this), 00207 itsLoadEventsName(&OPT_MRVloadEvents, this), 00208 itsSavePropertiesName(&OPT_MRVsaveProperties, this), 00209 itsLoadPropertiesName(&OPT_MRVloadProperties, this), 00210 itsSavePositionsName(&OPT_MRVsavePositions, this), 00211 itsSaveEventNumString(&OPT_MRVsaveEventNums, this), 00212 resFrameWindow(NULL), 00213 itsOfs(ofs), 00214 colInteresting(COL_INTERESTING), 00215 colCandidate(COL_CANDIDATE), 00216 colPrediction(COL_PREDICTION), 00217 colFOE(COL_FOE) 00218 { 00219 // need to register the OutputMbariFrameSeries with the ModelManager? 00220 if (!mgr.hasSubComponent(ofs)) mgr.addSubComponent(ofs); 00221 } 00222 00223 // ############################################################################# 00224 MbariResultViewer::~MbariResultViewer() 00225 { 00226 // destroy everything 00227 freeMem(); 00228 } 00229 00230 // ###################################################################### 00231 void MbariResultViewer::paramChanged(ModelParamBase* const param, 00232 const bool valueChanged, 00233 ParamClient::ChangeStatus* status) 00234 { 00235 ModelComponent::paramChanged(param, valueChanged, status); 00236 00237 // if the param is out itsMarkInteresting set the color accordingly 00238 //if (param == &itsMarkInteresting) 00239 //{ 00240 // if (itsMarkInteresting.getVal()) colInteresting = COL_INTERESTING; 00241 // else colInteresting = COL_TRANSPARENT; 00242 //} 00243 00244 // if the param is out itsMarkCandidate set the color accordingly 00245 if (param == &itsMarkCandidate) 00246 { 00247 if (itsMarkCandidate.getVal()) colCandidate = COL_CANDIDATE; 00248 else colCandidate = COL_TRANSPARENT; 00249 } 00250 00251 // if the param is out itsMarkSkip set the color accordingly 00252 else if (param == &itsMarkPrediction) 00253 { 00254 if (itsMarkPrediction.getVal()) colPrediction = COL_PREDICTION; 00255 else colPrediction = COL_TRANSPARENT; 00256 } 00257 00258 // if the param is out itsMarkSkip set the color accordingly 00259 else if (param == &itsMarkFOE) 00260 { 00261 if (itsMarkFOE.getVal()) colFOE = COL_FOE; 00262 else colFOE = COL_TRANSPARENT; 00263 } 00264 00265 // if the param is itsSaveEventNum, parse the string and fill the vector 00266 else if (param == &itsSaveEventNumString) 00267 parseSaveEventNums(itsSaveEventNumString.getVal()); 00268 } 00269 00270 // ###################################################################### 00271 void MbariResultViewer::reset1() 00272 { 00273 // destroy our stuff 00274 freeMem(); 00275 00276 // propagate to our base class: 00277 ModelComponent::reset1(); 00278 } 00279 00280 // ###################################################################### 00281 void MbariResultViewer::freeMem() 00282 { 00283 for (uint i = 0; i < itsResultWindows.size(); ++i) 00284 if (itsResultWindows[i] != NULL) delete itsResultWindows[i]; 00285 00286 if (resFrameWindow != NULL) delete resFrameWindow; 00287 00288 itsResultNames.clear(); 00289 itsResultWindows.clear(); 00290 00291 itsSaveEventsName.setVal(""); 00292 itsLoadEventsName.setVal(""); 00293 itsSavePropertiesName.setVal(""); 00294 itsLoadPropertiesName.setVal(""); 00295 } 00296 00297 // ############################################################################# 00298 template <class T> 00299 void MbariResultViewer::output(const Image<T>& img, const uint frameNum, 00300 const std::string& resultName, const int resNum) 00301 { 00302 if (itsDisplayResults.getVal()) display(img, frameNum, resultName, resNum); 00303 if (itsSaveResults.getVal()) save(img, frameNum, resultName, resNum); 00304 } 00305 00306 // ############################################################################# 00307 template <class T> 00308 void MbariResultViewer::display(const Image<T>& img, const uint frameNum, 00309 const std::string& resultName, const int resNum) 00310 { 00311 uint num = getNumFromString(resultName); 00312 itsResultWindows[num] = displayImage(img, itsResultWindows[num], 00313 getLabel(num, frameNum, resNum).c_str()); 00314 } 00315 00316 // ############################################################################# 00317 void MbariResultViewer::save(const Image< PixRGB<byte> >& img, 00318 const uint frameNum, 00319 const std::string& resultName, 00320 const int resNum) 00321 { 00322 //uint num = getNumFromString(resultName); 00323 itsOfs->writeMbariRGB(img,getFileStem(resultName, resNum),frameNum); 00324 } 00325 00326 // ############################################################################# 00327 void MbariResultViewer::save(const Image<byte>& img, 00328 const uint frameNum, 00329 const std::string& resultName, 00330 const int resNum) 00331 { 00332 //uint num = getNumFromString(resultName); 00333 itsOfs->writeMbariGray(img,getFileStem(resultName, resNum),frameNum); 00334 } 00335 00336 // ############################################################################# 00337 void MbariResultViewer::save(const Image<float>& img, 00338 const uint frameNum, 00339 const std::string& resultName, 00340 const int resNum) 00341 { 00342 //uint num = getNumFromString(resultName); 00343 itsOfs->writeMbariFloat(img,getFileStem(resultName, resNum), 00344 FLOAT_NORM_0_255,frameNum); 00345 } 00346 00347 // ############################################################################# 00348 void MbariResultViewer::outputResultFrame(const Image< PixRGB<byte> >& resultImg, 00349 const std::string& frameStem, 00350 const uint frameNum, 00351 VisualEventSet& evts, 00352 PropertyVectorSet& pvs, 00353 const int circleRadius) 00354 { 00355 Image< PixRGB<byte> > img = resultImg; 00356 00357 if (itsDisplayOutput.getVal() || itsSaveOutput.getVal()) 00358 evts.drawTokens(img, frameNum, pvs, circleRadius, 00359 itsMarkInteresting.getVal(), itsOpacity.getVal(), 00360 colInteresting, colCandidate, colPrediction, 00361 colFOE, itsShowEventLabels.getVal()); 00362 00363 // display the frame? 00364 if (itsDisplayOutput.getVal()) 00365 { 00366 // make the label 00367 char label[2048]; 00368 sprintf(label,"%s%06d",itsOfs->getFileStem().c_str(),frameNum); 00369 00370 resFrameWindow = displayImage(img,resFrameWindow,label); 00371 } 00372 00373 // save the resulting frame to disk ? 00374 if (itsSaveOutput.getVal()) itsOfs->writeMbariRGB(img,frameStem,frameNum); 00375 } 00376 00377 // ############################################################################# 00378 bool MbariResultViewer::isLoadEventsNameSet() const 00379 { 00380 return (itsLoadEventsName.getVal().length() > 0); 00381 } 00382 00383 00384 // ############################################################################# 00385 void MbariResultViewer::loadVisualEventSet(VisualEventSet& ves) const 00386 { 00387 std::ifstream ifs(itsLoadEventsName.getVal().c_str()); 00388 ves.readFromStream(ifs); 00389 ifs.close(); 00390 } 00391 // ############################################################################# 00392 bool MbariResultViewer::isLoadPropertiesNameSet() const 00393 { 00394 return (itsLoadPropertiesName.getVal().length() > 0); 00395 } 00396 00397 // ############################################################################# 00398 void MbariResultViewer::loadProperties(PropertyVectorSet& pvs) const 00399 { 00400 std::ifstream ifs(itsLoadPropertiesName.getVal().c_str()); 00401 pvs.readFromStream(ifs); 00402 ifs.close(); 00403 } 00404 00405 // ############################################################################# 00406 bool MbariResultViewer::isSaveEventsNameSet() const 00407 { 00408 return (itsSaveEventsName.getVal().length() > 0); 00409 } 00410 00411 // ############################################################################# 00412 void MbariResultViewer::saveVisualEventSet(const VisualEventSet& ves) const 00413 { 00414 std::ofstream ofs(itsSaveEventsName.getVal().c_str()); 00415 ves.writeToStream(ofs); 00416 ofs.close(); 00417 } 00418 00419 // ############################################################################# 00420 bool MbariResultViewer::isSavePropertiesNameSet() const 00421 { 00422 return (itsSavePropertiesName.getVal().length() > 0); 00423 } 00424 00425 // ############################################################################# 00426 void MbariResultViewer::saveProperties(const PropertyVectorSet& pvs) const 00427 { 00428 std::ofstream ofs(itsSavePropertiesName.getVal().c_str()); 00429 pvs.writeToStream(ofs); 00430 ofs.close(); 00431 } 00432 00433 // ############################################################################# 00434 bool MbariResultViewer::isSavePositionsNameSet() const 00435 { 00436 return (itsSavePositionsName.getVal().length() > 0); 00437 } 00438 00439 // ############################################################################# 00440 void MbariResultViewer::savePositions(const VisualEventSet& ves) const 00441 { 00442 std::ofstream ofs(itsSavePositionsName.getVal().c_str()); 00443 ves.writePositions(ofs); 00444 ofs.close(); 00445 } 00446 00447 // ############################################################################# 00448 bool MbariResultViewer::needFrames() const 00449 { 00450 bool needOutput = itsSaveOutput.getVal() || itsDisplayOutput.getVal(); 00451 bool needInput = !isLoadEventsNameSet() || isSaveEventClip(); 00452 return (needInput || needOutput); 00453 } 00454 00455 // ############################################################################# 00456 uint MbariResultViewer::getAvgCacheSize() const 00457 { 00458 return itsSizeAvgCache.getVal(); 00459 } 00460 00461 // ############################################################################# 00462 bool MbariResultViewer::isSaveEventClip() const 00463 { 00464 return (itsSaveEventNums.size() > 0); 00465 } 00466 00467 // ############################################################################# 00468 uint MbariResultViewer::numSaveEventClips() const 00469 { 00470 return itsSaveEventNums.size(); 00471 } 00472 00473 // ############################################################################# 00474 uint MbariResultViewer::getSaveEventClipNum(uint idx) const 00475 { 00476 ASSERT(idx < itsSaveEventNums.size()); 00477 return itsSaveEventNums[idx]; 00478 } 00479 00480 // ############################################################################# 00481 uint MbariResultViewer::getNumFromString(const std::string& resultName) 00482 { 00483 // see if we can find this guy in our list 00484 for (uint i = 0; i < itsResultNames.size(); ++i) 00485 if (itsResultNames[i].compare(resultName) == 0) 00486 return i; 00487 00488 // didn't find it -> make a new entry and return index of this new entry 00489 itsResultNames.push_back(resultName); 00490 itsResultWindows.push_back(NULL); 00491 00492 return (itsResultNames.size() - 1); 00493 } 00494 00495 // ############################################################################# 00496 std::string MbariResultViewer::getLabel(const uint num, const uint frameNum, 00497 const int resNum) 00498 { 00499 ASSERT(num < itsResultNames.size()); 00500 char fnum[7]; 00501 sprintf(fnum,"%06d",frameNum); 00502 return (getFileStem(itsResultNames[num], resNum) + std::string(fnum)); 00503 } 00504 00505 // ############################################################################# 00506 std::string MbariResultViewer::getFileStem(const std::string& resultName, 00507 const int resNum) 00508 { 00509 char rnum[4]; 00510 if (resNum >= 0) sprintf(rnum,"%02d_",resNum); 00511 else sprintf(rnum,"_"); 00512 00513 return(itsOfs->getFileStem() + std::string("_") 00514 + resultName + std::string(rnum)); 00515 } 00516 00517 // ############################################################################# 00518 template <class T> 00519 XWinManaged* MbariResultViewer::displayImage(const Image<T>& img, 00520 XWinManaged* win, 00521 const char* label) 00522 { 00523 // need to rescale? 00524 Dims dims = itsRescaleDisplay.getVal(); 00525 if (dims.isEmpty()) dims = img.getDims(); 00526 bool doRescale = (dims != img.getDims()); 00527 00528 // does the window have to be re-constructed? 00529 if (win != NULL) 00530 { 00531 if (win->getDims() != dims) delete win; 00532 } 00533 00534 if (win == NULL) 00535 { 00536 if (doRescale) 00537 win = new XWinManaged(rescale(img, dims),label); 00538 else 00539 win = new XWinManaged(img,label); 00540 } 00541 else 00542 { 00543 if (doRescale) 00544 win->drawImage(rescale(img,dims)); 00545 else 00546 win->drawImage(img); 00547 00548 win->setTitle(label); 00549 } 00550 00551 return win; 00552 } 00553 00554 // ############################################################################# 00555 void MbariResultViewer::saveSingleEventFrame(const Image< PixRGB<byte> >& img, 00556 int frameNum, 00557 const VisualEvent& event) 00558 { 00559 ASSERT(event.isFrameOk(frameNum)); 00560 00561 // create the file stem 00562 char evnum[10]; 00563 sprintf(evnum,"_evt%04d_",event.getEventNum()); 00564 std::string filestem = itsOfs->getFileStem() + std::string(evnum); 00565 00566 const int pad = 10; 00567 Dims maxDims = event.getMaxObjectDims(); 00568 Dims d(maxDims.w() + 2 * pad, maxDims.h() + 2 * pad); 00569 00570 // compute the correct bounding box and cut it out 00571 Rectangle bbox = event.getToken(frameNum).bitObject.getBoundingBox(); 00572 //Point2D<int> cen = event.getToken(frameNum).bitObject.getCentroid(); 00573 00574 // first the horizontal direction 00575 int wpad = (d.w() - bbox.width()) / 2; 00576 int ll = bbox.left() - wpad; 00577 //int ll = cen.i - d.w() / 2; 00578 int rr = ll + d.w(); 00579 if (ll < 0) { rr -= ll; ll = 0; } 00580 if (rr >= img.getWidth()) { rr = img.getWidth() - 1; ll = rr - d.w(); } 00581 00582 // now the same thing with the vertical direction 00583 int hpad = (d.h() - bbox.height()) / 2; 00584 int tt = bbox.top() - hpad; 00585 //int tt = cen.j - d.h() / 2; 00586 int bb = tt + d.h(); 00587 if (tt < 0) { bb -= tt; tt = 0; } 00588 if (bb >= img.getHeight()) { bb = img.getHeight() - 1; tt = bb - d.h(); } 00589 00590 // cut out the rectangle and save it 00591 Image< PixRGB<byte> > cut = crop(img, Rectangle::tlbrI(tt,ll,bb,rr)); 00592 itsOfs->writeMbariRGB(cut, filestem, frameNum); 00593 } 00594 00595 // ############################################################################# 00596 void MbariResultViewer::parseSaveEventNums(const std::string& value) 00597 { 00598 itsSaveEventNums.clear(); 00599 00600 // format here is "c,...,c" 00601 int curpos = 0, len = value.length(); 00602 while (curpos < len) 00603 { 00604 // get end of next number 00605 int nextpos = value.find_first_not_of("-.0123456789eE",curpos); 00606 if (nextpos == -1) nextpos = len; 00607 00608 // no number characters found -> bummer 00609 if (nextpos == curpos) 00610 LFATAL("Error parsing the SaveEventNum string '%s' - found '%c' " 00611 "instead of a number.",value.c_str(),value[curpos]); 00612 00613 // now let's see - can we get a number here? 00614 uint evNum; 00615 int rep = sscanf(value.substr(curpos,nextpos-curpos).c_str(),"%i",&evNum); 00616 00617 // couldn't read a number -> bummer 00618 if (rep != 1) 00619 LFATAL("Error parsing SaveEventNum string '%s' - found '%s' instead of " 00620 "a number.", value.c_str(), 00621 value.substr(curpos,nextpos-curpos).c_str()); 00622 00623 // yeah! found a number -> store it 00624 itsSaveEventNums.push_back(evNum); 00625 00626 LDEBUG("evNum = %i; value[nextpos] = '%c'",evNum,value[nextpos]); 00627 00628 // not a comma -> bummer 00629 if ((nextpos < len) && (value[nextpos] != ',')) 00630 LFATAL("Error parsing the SaveEventNum string '%s' - found '%c' " 00631 "instead of ','.",value.c_str(),value[nextpos]); 00632 00633 // the character right after the comma should be a number again 00634 curpos = nextpos + 1; 00635 } 00636 00637 // end of string, done 00638 return; 00639 } 00640 // ############################################################################# 00641 // Instantiations 00642 #define INSTANTIATE(T) \ 00643 template void MbariResultViewer::output(const Image< T >& img, \ 00644 const uint frameNum, \ 00645 const std::string& resultName, \ 00646 const int resNum); \ 00647 template void MbariResultViewer::display(const Image< T >& img, \ 00648 const uint frameNum, \ 00649 const std::string& resultName, \ 00650 const int resNum); \ 00651 template XWinManaged* MbariResultViewer::displayImage(const Image< T >& img, \ 00652 XWinManaged* win, \ 00653 const char* label); 00654 00655 INSTANTIATE(PixRGB<byte>); 00656 INSTANTIATE(byte); 00657 INSTANTIATE(float); 00658 00659 00660 // ############################################################################# 00661 /* So things look consistent in everyone's emacs... */ 00662 /* Local Variables: */ 00663 /* indent-tabs-mode: nil */ 00664 /* End: */