00001 /*!@file Neuro/InferotemporalCortexService.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 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/NeovisionII/InferotemporalCortexService.C $ 00035 // $Id: InferotemporalCortexService.C 14522 2011-02-17 01:52:47Z dparks $ 00036 // 00037 00038 #include "NeovisionII/InferotemporalCortexService.H" 00039 #include "Image/ColorOps.H" 00040 #include "Image/DrawOps.H" 00041 #include "Util/sformat.H" 00042 00043 InferotemporalCortexI::InferotemporalCortexI(OptionManager& mgr, 00044 nub::ref<OutputFrameSeries> ofs, 00045 const std::string& descrName, 00046 const std::string& tagName ) : 00047 ModelComponent(mgr, descrName, tagName), 00048 itsOfs(ofs) 00049 { 00050 //Subscribe to the various topics 00051 IceStorm::TopicPrx topicPrx; 00052 itsTopicsSubscriptions.push_back(TopicInfo("PrefrontalCortexTopic", topicPrx)); 00053 initVDB(); 00054 } 00055 00056 InferotemporalCortexI::~InferotemporalCortexI() 00057 { 00058 LINFO("Un suscribe"); 00059 unsubscribeSimEvents(); 00060 } 00061 00062 void InferotemporalCortexI::initSimEvents(Ice::CommunicatorPtr icPtr, Ice::ObjectPrx objectPrx) 00063 { 00064 //Get the IceStorm object 00065 Ice::ObjectPrx obj = icPtr->stringToProxy("SimEvents/TopicManager:tcp -p 11111"); 00066 IceStorm::TopicManagerPrx topicManager = 00067 IceStorm::TopicManagerPrx::checkedCast(obj); 00068 00069 //Create a InferotemporalCortex Topic 00070 IceStorm::TopicPrx topic; 00071 try { 00072 topic = topicManager->retrieve("InferotemporalCortexTopic"); //check if the Retina topic exists 00073 } catch (const IceStorm::NoSuchTopic&) { 00074 topic = topicManager->create("InferotemporalCortexTopic"); //The retina topic does not exists, create 00075 } 00076 //Make a one way visualCortex message publisher for efficency 00077 Ice::ObjectPrx pub = topic->getPublisher()->ice_oneway(); 00078 itsEventsPub = SimEvents::EventsPrx::uncheckedCast(pub); 00079 00080 //Subscribe the SimulationViewer to theTopics 00081 itsObjectPrx = objectPrx; 00082 //subscribe to the topics 00083 for(uint i=0; i<itsTopicsSubscriptions.size(); i++) 00084 { 00085 try { 00086 IceStorm::QoS qos; 00087 itsTopicsSubscriptions[i].topicPrx = 00088 topicManager->retrieve(itsTopicsSubscriptions[i].name.c_str()); //Get the 00089 itsTopicsSubscriptions[i].topicPrx->subscribeAndGetPublisher(qos, itsObjectPrx); //Subscribe to the retina topic 00090 } catch (const IceStorm::NoSuchTopic&) { 00091 LFATAL("Error! No %s topic found!", itsTopicsSubscriptions[i].name.c_str()); 00092 } catch (const char* msg) { 00093 LINFO("Error %s", msg); 00094 } 00095 } 00096 } 00097 00098 void InferotemporalCortexI::unsubscribeSimEvents() 00099 { 00100 //Unsubscribe from all the topics we are registerd to 00101 for(uint i=0; i<itsTopicsSubscriptions.size(); i++) 00102 { 00103 itsTopicsSubscriptions[i].topicPrx->unsubscribe(itsObjectPrx); 00104 } 00105 } 00106 00107 00108 bool InferotemporalCortexI::initVDB() 00109 { 00110 itsUseColor = false; 00111 itsTrainingMode = true; 00112 itsVDBFile = "objects.vdb"; 00113 itsMaxLabelHistory = 1; 00114 itsVDB.loadFrom(itsVDBFile); 00115 00116 return true; 00117 } 00118 00119 //The VC excepts a retina image and posts a saliency map 00120 void InferotemporalCortexI::evolve(const SimEvents::EventMessagePtr& eMsg, 00121 const Ice::Current&) 00122 { 00123 if (eMsg->ice_isA("::SimEvents::InfrotemporalCortexBiasMessage")){ 00124 SimEvents::InfrotemporalCortexBiasMessagePtr msg = SimEvents::InfrotemporalCortexBiasMessagePtr::dynamicCast(eMsg); 00125 Image<PixRGB<byte> > objImg = Ice2Image<PixRGB<byte> >(msg->img); 00126 00127 //Recognize the image 00128 float score; 00129 float rotation = 0; 00130 std::string objName = matchObject(objImg, score, rotation); 00131 00132 if (objName == "nomatch") 00133 { 00134 itsRecentLabels.resize(0); 00135 00136 if (itsTrainingMode) 00137 { 00138 LINFO("Enter a label for this object:\n"); 00139 std::getline(std::cin, objName); 00140 LINFO("You typed '%s'", objName.c_str()); 00141 00142 if (objName != "" && objName != "exit") 00143 { 00144 rutz::shared_ptr<VisualObject> 00145 vo(new VisualObject(objName.c_str(), "NULL", objImg, 00146 Point2D<int>(-1,-1), 00147 std::vector<float>(), 00148 std::vector< rutz::shared_ptr<Keypoint> >(), 00149 itsUseColor)); 00150 itsVDB.addObject(vo, false); 00151 itsVDB.saveTo(itsVDBFile); 00152 } else { 00153 objName = "nomatch"; 00154 } 00155 00156 SimEvents::InfrotemporalCortexMessagePtr itMsg = new SimEvents::InfrotemporalCortexMessage; 00157 itMsg->objectName = objName; 00158 itMsg->confidence = -1; 00159 itMsg->rotation = rotation; 00160 LINFO("Sending message"); 00161 itsEventsPub->evolve(itMsg); 00162 00163 } 00164 LINFO("NO match"); 00165 } else { 00166 const std::string bestObjName = objName; 00167 00168 //itsRecentLabels.push_back(objName); 00169 //while (itsRecentLabels.size() > 1) 00170 // itsRecentLabels.pop_front(); 00171 00172 //const std::string bestObjName = 00173 // getBestLabel(itsRecentLabels, 1); 00174 00175 LINFO("Found object %s rot=%f", bestObjName.c_str(), rotation); 00176 if (bestObjName.size() > 0) 00177 { 00178 SimEvents::InfrotemporalCortexMessagePtr itMsg = new SimEvents::InfrotemporalCortexMessage; 00179 itMsg->objectName = bestObjName; 00180 itMsg->confidence = score; 00181 itMsg->rotation = rotation; 00182 itsEventsPub->evolve(itMsg); 00183 00184 } 00185 } 00186 LINFO("Done."); 00187 } 00188 } 00189 00190 std::string InferotemporalCortexI::getBestLabel(const size_t mincount) 00191 { 00192 if (itsRecentLabels.size() == 0) 00193 return std::string(); 00194 00195 std::map<std::string, size_t> counts; 00196 00197 size_t bestcount = 0; 00198 size_t bestpos = 0; 00199 00200 for (size_t i = 0; i < itsRecentLabels.size(); ++i) 00201 { 00202 const size_t c = ++(counts[itsRecentLabels[i]]); 00203 00204 if (c >= bestcount) 00205 { 00206 bestcount = c; 00207 bestpos = i; 00208 } 00209 } 00210 00211 if (bestcount >= mincount) 00212 return itsRecentLabels[bestpos]; 00213 00214 return std::string(); 00215 } 00216 00217 std::string InferotemporalCortexI::matchObject(Image<PixRGB<byte> > &ima, float &score, float &rotation) 00218 { 00219 //find object in the database 00220 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches; 00221 rutz::shared_ptr<VisualObject> 00222 vo(new VisualObject("PIC", "NULL", ima, 00223 Point2D<int>(-1,-1), 00224 std::vector<float>(), 00225 std::vector< rutz::shared_ptr<Keypoint> >(), 00226 itsUseColor)); 00227 00228 Image<PixRGB<byte> > siftImg = vo->getKeypointImage(); 00229 itsOfs->writeRGB(siftImg, "SIFTKeypoints", FrameInfo("SiftKeypoints", SRC_POS)); 00230 itsOfs->updateNext(); 00231 usleep(10000); 00232 00233 const uint nmatches = itsVDB.getObjectMatches(vo, matches, VOMA_SIMPLE, 00234 10000U, //max objs to return 00235 0.5F, //keypoint distance score default 0.5F 00236 0.5F, //affine distance score default 0.5F 00237 1.0F, //minscore default 1.0F 00238 3U, //min # of keypoint match 00239 100U, //keypoint selection thershold 00240 false //sort by preattentive 00241 ); 00242 00243 score = 0; 00244 //float avgScore = 0, affineAvgDist = 0; 00245 int nkeyp = 0; 00246 int objId = -1; 00247 if (nmatches > 0) 00248 { 00249 rutz::shared_ptr<VisualObject> obj; //so we will have a ref to the last matches obj 00250 rutz::shared_ptr<VisualObjectMatch> vom; 00251 //for(unsigned int i=0; i< nmatches; i++){ 00252 for (unsigned int i = 0; i < 1; ++i) 00253 { 00254 vom = matches[i]; 00255 obj = vom->getVoTest(); 00256 score = vom->getScore(); 00257 nkeyp = vom->size(); 00258 //avgScore = vom->getKeypointAvgDist(); 00259 //affineAvgDist = vom->getAffineAvgDist(); 00260 00261 objId = atoi(obj->getName().c_str()+3); 00262 00263 //Get the rotation 00264 float theta, sx, sy, str; 00265 SIFTaffine aff = vom->getSIFTaffine(); 00266 aff.decompose(theta, sx, sy, str); 00267 rotation = theta; 00268 00269 00270 return obj->getName(); 00271 LINFO("### Object match with '%s' score=%f ID:%i", 00272 obj->getName().c_str(), vom->getScore(), objId); 00273 00274 //calculate the actual distance (location of keypoints) between 00275 //keypoints. If the same patch was found, then the distance should 00276 //be close to 0 00277 double dist = 0; 00278 for (int keyp=0; keyp<nkeyp; keyp++) 00279 { 00280 const KeypointMatch kpm = vom->getKeypointMatch(keyp); 00281 00282 float refX = kpm.refkp->getX(); 00283 float refY = kpm.refkp->getY(); 00284 00285 float tstX = kpm.tstkp->getX(); 00286 float tstY = kpm.tstkp->getY(); 00287 dist += (refX-tstX) * (refX-tstX); 00288 dist += (refY-tstY) * (refY-tstY); 00289 } 00290 00291 // printf("%i:%s %i %f %i %f %f %f\n", objNum, obj->getName().c_str(), 00292 // nmatches, score, nkeyp, avgScore, affineAvgDist, sqrt(dist)); 00293 00294 //analizeImage(); 00295 } 00296 00297 } 00298 00299 return std::string("nomatch"); 00300 } 00301 00302 00303 00304 /////////////////////////// The VC Service to init the retina and start as a deamon /////////////// 00305 class InferotemporalCortexService : public Ice::Service { 00306 protected: 00307 virtual bool start(int, char* argv[]); 00308 virtual bool stop() { 00309 if (itsMgr) 00310 delete itsMgr; 00311 return true; 00312 } 00313 00314 private: 00315 Ice::ObjectAdapterPtr itsAdapter; 00316 ModelManager *itsMgr; 00317 }; 00318 00319 bool InferotemporalCortexService::start(int argc, char* argv[]) 00320 { 00321 00322 itsMgr = new ModelManager("InferotemporalCortexService"); 00323 00324 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(*itsMgr)); 00325 itsMgr->addSubComponent(ofs); 00326 00327 nub::ref<InferotemporalCortexI> itc(new InferotemporalCortexI(*itsMgr, ofs)); 00328 itsMgr->addSubComponent(itc); 00329 00330 itsMgr->parseCommandLine((const int)argc, (const char**)argv, "", 0, 0); 00331 00332 char adapterStr[255]; 00333 sprintf(adapterStr, "default -p %i", BrainObjects::InferoTemporalPort); 00334 itsAdapter = communicator()->createObjectAdapterWithEndpoints("InferotemporalCortexAdapter", 00335 adapterStr); 00336 00337 Ice::ObjectPtr object = itc.get(); 00338 Ice::ObjectPrx objectPrx = itsAdapter->add(object, communicator()->stringToIdentity("InferotemporalCortex")); 00339 itc->initSimEvents(communicator(), objectPrx); 00340 itsAdapter->activate(); 00341 00342 itsMgr->start(); 00343 00344 return true; 00345 } 00346 00347 // ###################################################################### 00348 int main(int argc, char** argv) { 00349 00350 InferotemporalCortexService svc; 00351 return svc.main(argc, argv); 00352 } 00353 00354