00001 /*!@file MBARI/mbariFunctions.C a few functions used by MBARI programs 00002 */ 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2002 // 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: Dirk Walther <walther@caltech.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/MBARI/mbariFunctions.C $ 00035 // $Id: mbariFunctions.C 10712 2009-02-01 06:22:17Z itti $ 00036 // 00037 00038 00039 #include "MBARI/mbariFunctions.H" 00040 #include "Image/ColorOps.H" 00041 #include "Image/FilterOps.H" 00042 #include "Image/Image.H" 00043 #include "Image/MathOps.H" 00044 #include "Image/Transforms.H" 00045 #include "Media/MediaSimEvents.H" 00046 #include "MBARI/BitObject.H" 00047 #include "Neuro/Brain.H" 00048 #include "Neuro/NeuroSimEvents.H" 00049 #include "Simulation/SimEventQueue.H" 00050 #include "Util/Timer.H" 00051 #include "rutz/shared_ptr.h" 00052 00053 00054 // ###################################################################### 00055 std::list<BitObject> extractBitObjects(const Image<byte>& bImg, 00056 Rectangle region, 00057 int minSize) 00058 { 00059 Timer timer; 00060 Image<byte> bitImg = replaceVals(bImg, byte(0), byte(0), byte(1)); 00061 int tmask = 0, tobj = 0; 00062 std::list<BitObject> bos; 00063 region = region.getOverlap(bitImg.getBounds()); 00064 Image<byte> labelImg(bitImg.getDims(),ZEROS); 00065 00066 for (int ry = region.top(); ry < region.bottomO(); ++ry) 00067 for (int rx = region.left(); rx < region.rightO(); ++rx) 00068 { 00069 // this location doesn't have anything -> never mind 00070 if (bitImg.getVal(rx,ry) == 0) continue; 00071 00072 // got this guy already -> never mind 00073 if (labelImg.getVal(rx,ry) > 0) continue; 00074 00075 //Image<byte> dest(bitImg.getDims(), ZEROS); 00076 00077 //timer.reset(); 00078 //if (floodClean(bitImg,labelImg, Point2D<int>(rx,ry), byte(1), byte(1)) < minSize) 00079 //continue 00080 //int area = floodClean(bitImg,dest, Point2D<int>(rx,ry), byte(1), byte(1)); 00081 //tflood += timer.get(); 00082 //labelImg = takeMax(labelImg, dest); 00083 //if (area < minSize) continue; 00084 00085 timer.reset(); 00086 BitObject obj; 00087 Image<byte> dest = obj.reset(bitImg, Point2D<int>(rx,ry)); 00088 tobj += timer.get(); 00089 00090 timer.reset(); 00091 labelImg = takeMax(labelImg, dest); 00092 tmask += timer.get(); 00093 00094 if (obj.getArea() > minSize) bos.push_back(obj); 00095 //bos.push_back(BitObject(bitImg,Point2D<int>(rx,ry))); 00096 //bos.push_back(BitObject(dest)); 00097 00098 //LINFO("found object of size: %d",bos.back().getArea()); 00099 } 00100 LINFO("tobj = %i; tmask = %i",tobj,tmask); 00101 return bos; 00102 } 00103 00104 // ###################################################################### 00105 std::list<BitObject> getLargestObjects(const Image<byte>& bImg, 00106 Rectangle region, 00107 int numObjects, 00108 int minSize) 00109 { 00110 std::list<BitObject> objs = extractBitObjects(bImg, region, minSize); 00111 std::list<BitObject> result; 00112 00113 for (int i = 0; i < numObjects; ++i) 00114 { 00115 int maxSize = 0; 00116 std::list<BitObject>::iterator mx, cur; 00117 00118 if (objs.empty()) break; 00119 for (cur = objs.begin(); cur != objs.end(); ++cur) 00120 { 00121 if (cur->getArea() > maxSize) 00122 { 00123 maxSize = cur->getArea(); 00124 mx = cur; 00125 } 00126 } 00127 00128 result.push_back(*mx); 00129 objs.erase(mx); 00130 } 00131 return result; 00132 } 00133 00134 // ###################################################################### 00135 std::list<BitObject> getSalRegions(nub::soft_ref<Brain> brain, 00136 nub::soft_ref<SimEventQueue> q, 00137 const Image< PixRGB<byte> >& img, 00138 const Image<byte>& bitImg, 00139 float maxEvolveTime, 00140 int maxNumSalSpots, 00141 int minSize) 00142 { 00143 // this should be 2^(smlev - 1) 00144 const int rectRad = 8; 00145 00146 std::list<BitObject> bos; 00147 brain->reset(MC_RECURSE); 00148 00149 rutz::shared_ptr<SimEventInputFrame> 00150 e(new SimEventInputFrame(brain.get(), GenericFrame(img), 0)); 00151 q->post(e); // post the image to the brain 00152 00153 int numSpots = 0; 00154 while ((q->now().secs() < maxEvolveTime) && (numSpots < maxNumSalSpots)) 00155 { 00156 q->evolve(); 00157 00158 if (SeC<SimEventWTAwinner> e = q->check<SimEventWTAwinner>(0)) 00159 { 00160 const Point2D<int> winner = e->winner().p; 00161 00162 ++numSpots; 00163 00164 // extract all the bitObjects at the salient location 00165 Rectangle region = 00166 Rectangle::tlbrI(winner.j - rectRad, winner.i - rectRad, 00167 winner.j + rectRad, winner.i + rectRad); 00168 region = region.getOverlap(bitImg.getBounds()); 00169 std::list<BitObject> sobjs = extractBitObjects(bitImg,region,minSize); 00170 00171 // loop until we find a new object that doesn't overlap with anything 00172 // that we have found so far, or until we run out of objects 00173 bool keepGoing = true; 00174 while(keepGoing) 00175 { 00176 // no object left -> go to the next salient point 00177 if (sobjs.empty()) break; 00178 00179 std::list<BitObject>::iterator biter, siter, largest; 00180 00181 // find the largest object 00182 largest = sobjs.begin(); 00183 int maxSize = 0; 00184 for (siter = sobjs.begin(); siter != sobjs.end(); ++siter) 00185 if (siter->getArea() > maxSize) 00186 { 00187 maxSize = siter->getArea(); 00188 largest = siter; 00189 } 00190 00191 // does the largest objects intersect with any of the already stored guys? 00192 keepGoing = false; 00193 for (biter = bos.begin(); biter != bos.end(); ++biter) 00194 if (biter->doesIntersect(*largest)) 00195 { 00196 // no need to store intersecting objects -> get rid of largest 00197 // and look for the next largest 00198 sobjs.erase(largest); 00199 keepGoing = true; 00200 break; 00201 } 00202 00203 // so, did we end up finding a BitObject that we can store? 00204 if (!keepGoing) bos.push_back(*largest); 00205 00206 } // end while keepGoing 00207 00208 } // end if we found a winner 00209 00210 } // end while we keep looking for salient points 00211 00212 return bos; 00213 } 00214 00215 // ###################################################################### 00216 Image<byte> showAllObjects(std::list<BitObject>& objs) 00217 { 00218 Image<byte> result; 00219 std::list<BitObject>::iterator currObj; 00220 for (currObj = objs.begin(); currObj != objs.end(); ++currObj) 00221 { 00222 Image<byte> mask = currObj->getObjectMask(byte(255)); 00223 if (result.initialized()) 00224 result = takeMax(result,mask); 00225 else 00226 result = mask; 00227 } 00228 return result; 00229 } 00230 00231 // ###################################################################### 00232 /* So things look consistent in everyone's emacs... */ 00233 /* Local Variables: */ 00234 /* indent-tabs-mode: nil */ 00235 /* End: */