00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00051 IceStorm::TopicPrx topicPrx;
00052 itsTopicsSubscriptions.push_back(TopicInfo("SegmenterTopic", topicPrx));
00053
00054 itsDBCon = new mysqlpp::Connection(false);
00055
00056
00057 const char* db = "ObjRec", *server = "localhost", *user = "neobrain", *pass = "12341234";
00058 if (!itsDBCon->connect(db, server, user, pass))
00059 LFATAL("DB connection failed: ");
00060
00061 }
00062
00063 InferotemporalCortexI::~InferotemporalCortexI()
00064 {
00065 unsubscribeSimEvents();
00066 }
00067
00068 void InferotemporalCortexI::initSimEvents(Ice::CommunicatorPtr icPtr, Ice::ObjectPrx objectPrx)
00069 {
00070
00071 Ice::ObjectPrx obj = icPtr->stringToProxy("SimEvents/TopicManager:tcp -h ilab21 -p 11111");
00072 IceStorm::TopicManagerPrx topicManager =
00073 IceStorm::TopicManagerPrx::checkedCast(obj);
00074
00075
00076 IceStorm::TopicPrx topic;
00077 try {
00078 topic = topicManager->retrieve("InferotemporalCortexTopic");
00079 } catch (const IceStorm::NoSuchTopic&) {
00080 topic = topicManager->create("InferotemporalCortexTopic");
00081 }
00082
00083 Ice::ObjectPrx pub = topic->getPublisher()->ice_oneway();
00084 itsEventsPub = SimEvents::EventsPrx::uncheckedCast(pub);
00085
00086
00087 itsObjectPrx = objectPrx;
00088
00089 for(uint i=0; i<itsTopicsSubscriptions.size(); i++)
00090 {
00091 try {
00092 IceStorm::QoS qos;
00093 itsTopicsSubscriptions[i].topicPrx =
00094 topicManager->retrieve(itsTopicsSubscriptions[i].name.c_str());
00095 itsTopicsSubscriptions[i].topicPrx->subscribeAndGetPublisher(qos, itsObjectPrx);
00096 } catch (const IceStorm::NoSuchTopic&) {
00097 LFATAL("Error! No %s topic found!", itsTopicsSubscriptions[i].name.c_str());
00098 }
00099 }
00100 }
00101
00102 void InferotemporalCortexI::unsubscribeSimEvents()
00103 {
00104
00105 for(uint i=0; i<itsTopicsSubscriptions.size(); i++)
00106 {
00107 itsTopicsSubscriptions[i].topicPrx->unsubscribe(itsObjectPrx);
00108 }
00109 }
00110
00111
00112 bool InferotemporalCortexI::initVDB()
00113 {
00114 itsUseColor = false;
00115 itsTrainingMode = false;
00116 itsVDBFile = "objects.vdb";
00117 itsMaxLabelHistory = 1;
00118 itsVDB.loadFrom(itsVDBFile);
00119
00120 return true;
00121 }
00122
00123
00124 void InferotemporalCortexI::evolve(const SimEvents::EventMessagePtr& eMsg,
00125 const Ice::Current&)
00126 {
00127 if (eMsg->ice_isA("::SimEvents::SegmenterMessage")){
00128 SimEvents::SegmenterMessagePtr msg = SimEvents::SegmenterMessagePtr::dynamicCast(eMsg);
00129 for(uint i=0; i<msg->segLocs.size(); i++)
00130 {
00131 SimEvents::SegInfo segInfo = msg->segLocs[i];
00132 Image<PixRGB<byte> > segImg = Ice2Image<PixRGB<byte> >(segInfo.img);
00133 Rectangle segRect(Point2D<int>(segInfo.rect.tl.i, segInfo.rect.tl.j),
00134 Dims(segInfo.rect.br.i - segInfo.rect.tl.i,
00135 segInfo.rect.br.j - segInfo.rect.tl.j));
00136
00137
00138
00139
00140 itsImgMutex.lock();
00141 itsCurrentImg = segImg;
00142 itsImgMutex.unlock();
00143 }
00144 }
00145 }
00146
00147 void InferotemporalCortexI::run()
00148 {
00149
00150 while(1)
00151 {
00152 itsImgMutex.lock();
00153 Image<PixRGB<byte> > img = itsCurrentImg;
00154 itsImgMutex.unlock();
00155 if (!img.initialized())
00156 continue;
00157
00158 itsTimer.reset();
00159 rutz::shared_ptr<VisualObject>
00160 vo(new VisualObject("PIC", "PIC", img,
00161 Point2D<int>(-1,-1),
00162 std::vector<double>(),
00163 std::vector< rutz::shared_ptr<Keypoint> >(),
00164 itsUseColor));
00165 itsTimer.mark();
00166 LINFO("Keypoint extraction took %f seconds for %i keypoints (%ix%i)",
00167 itsTimer.user_secs(),
00168 vo->numKeypoints(),
00169 img.getWidth(), img.getHeight());
00170
00171
00172 mysqlpp::Query query = itsDBCon->query();
00173
00174 const uint nkp = vo->numKeypoints();
00175 for(uint kpIdx=0; kpIdx<nkp; kpIdx++)
00176 {
00177 LINFO("Searching for keypoint %i of %i", kpIdx, nkp);
00178
00179 char fv[128];
00180 rutz::shared_ptr<Keypoint> keyPoint = vo->getKeypoint(kpIdx);
00181 for(uint i=0; i<keyPoint->getFVlength(); i++)
00182 {
00183 fv[i] = keyPoint->getFVelement(i);
00184
00185 }
00186
00187
00188 LINFO("Check NN");
00189 itsTimer.reset();
00190
00191 bool foundKeypoint = false;
00192 double foundDist = -1;
00193 int foundMatchCount = -1;
00194 int foundIdx = -1;
00195
00196 string fill(fv, 128);
00197 ostringstream strbuf;
00198 strbuf << "SELECT kid, matchCount, kp_dist(value, \"" << mysqlpp::escape << fill <<"\") as dist from SiftKeypoints order by dist limit 1" << ends;
00199 query << strbuf.str();
00200
00201 mysqlpp::Result res = query.store();
00202 if (res)
00203 {
00204 mysqlpp::Row row;
00205 mysqlpp::Row::size_type rowIdx;
00206 for (rowIdx = 0; row = res.at(rowIdx); ++rowIdx) {
00207 foundIdx = row["kid"];
00208 foundDist = row["dist"];
00209 foundMatchCount = row["matchCount"];
00210
00211 if (foundDist < 100000)
00212 foundKeypoint = true;
00213 }
00214 }
00215 itsTimer.mark();
00216 LINFO("NN Searched (idx=%i matchCount=%i dist=%f) took %f seconds (found=%i)",
00217 foundIdx,
00218 foundMatchCount,
00219 foundDist,
00220 itsTimer.user_secs(),
00221 foundKeypoint);
00222
00223 LINFO("Service Keypoint");
00224 itsTimer.reset();
00225 if (!foundKeypoint)
00226 {
00227 LINFO("Keypoint not found adding");
00228 std::string kpv(fv, 128);
00229 std::ostringstream strbuf;
00230 strbuf << "INSERT INTO SiftKeypoints (value) VALUES (\"" << mysqlpp::escape << kpv <<"\")" << ends;
00231 query.exec(strbuf.str());
00232 printf("Insert keypoint\n");
00233 } else {
00234
00235 std::ostringstream strbuf;
00236 foundMatchCount++;
00237 strbuf << "UPDATE SiftKeypoints set matchCount = " << foundMatchCount << " WHERE kid = " << foundIdx << ends;
00238 query.exec(strbuf.str());
00239 printf("Update keypoint\n");
00240 }
00241 itsTimer.mark();
00242 LINFO("Service keypoint took %f seconds",
00243 itsTimer.user_secs());
00244
00245
00246 PixRGB<byte> color;
00247 if(foundKeypoint)
00248 color = PixRGB<byte>(0,255,0);
00249 else
00250 color = PixRGB<byte>(255,0,0);
00251
00252 float x = keyPoint->getX();
00253 float y = keyPoint->getY();
00254 float s = keyPoint->getS();
00255 float o = keyPoint->getO();
00256
00257 Point2D<int> keypLoc(int(x + 0.5F), int(y + 0.5F));
00258
00259 drawDisk(img, keypLoc, 2, color);
00260 if (s > 0.0f)
00261 drawLine(img, keypLoc,
00262 Point2D<int>(int(x + s * cosf(o) + 0.5F),
00263 int(y + s * sinf(o) + 0.5F)),
00264 color);
00265
00266 itsOfs->writeRGB(img, "KeyPoints", FrameInfo("KeyPoints", SRC_POS));
00267 }
00268 LINFO("Continue");
00269
00270
00271 LINFO("Done.");
00272 }
00273 }
00274
00275 std::string InferotemporalCortexI::getBestLabel(const size_t mincount)
00276 {
00277 if (itsRecentLabels.size() == 0)
00278 return std::string();
00279
00280 std::map<std::string, size_t> counts;
00281
00282 size_t bestcount = 0;
00283 size_t bestpos = 0;
00284
00285 for (size_t i = 0; i < itsRecentLabels.size(); ++i)
00286 {
00287 const size_t c = ++(counts[itsRecentLabels[i]]);
00288
00289 if (c >= bestcount)
00290 {
00291 bestcount = c;
00292 bestpos = i;
00293 }
00294 }
00295
00296 if (bestcount >= mincount)
00297 return itsRecentLabels[bestpos];
00298
00299 return std::string();
00300 }
00301
00302 std::string InferotemporalCortexI::matchObject(Image<PixRGB<byte> > &ima, float &score)
00303 {
00304
00305 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches;
00306 rutz::shared_ptr<VisualObject>
00307 vo(new VisualObject("PIC", "PIC", ima,
00308 Point2D<int>(-1,-1),
00309 std::vector<double>(),
00310 std::vector< rutz::shared_ptr<Keypoint> >(),
00311 itsUseColor));
00312
00313 const uint nmatches = itsVDB.getObjectMatches(vo, matches, VOMA_SIMPLE,
00314 100U,
00315 0.5F,
00316 0.5F,
00317 1.0F,
00318 3U,
00319 100U,
00320 false
00321 );
00322
00323 score = 0;
00324 float avgScore = 0, affineAvgDist = 0;
00325 int nkeyp = 0;
00326 int objId = -1;
00327 if (nmatches > 0)
00328 {
00329 rutz::shared_ptr<VisualObject> obj;
00330 rutz::shared_ptr<VisualObjectMatch> vom;
00331
00332 for (unsigned int i = 0; i < 1; ++i)
00333 {
00334 vom = matches[i];
00335 obj = vom->getVoTest();
00336 score = vom->getScore();
00337 nkeyp = vom->size();
00338 avgScore = vom->getKeypointAvgDist();
00339 affineAvgDist = vom->getAffineAvgDist();
00340
00341 objId = atoi(obj->getName().c_str()+3);
00342
00343 return obj->getName();
00344 LINFO("### Object match with '%s' score=%f ID:%i",
00345 obj->getName().c_str(), vom->getScore(), objId);
00346
00347
00348
00349
00350 double dist = 0;
00351 for (int keyp=0; keyp<nkeyp; keyp++)
00352 {
00353 const KeypointMatch kpm = vom->getKeypointMatch(keyp);
00354
00355 float refX = kpm.refkp->getX();
00356 float refY = kpm.refkp->getY();
00357
00358 float tstX = kpm.tstkp->getX();
00359 float tstY = kpm.tstkp->getY();
00360 dist += (refX-tstX) * (refX-tstX);
00361 dist += (refY-tstY) * (refY-tstY);
00362 }
00363
00364
00365
00366
00367
00368 }
00369
00370 }
00371
00372 return std::string("nomatch");
00373 }
00374
00375
00376
00377
00378 class InferotemporalCortexService : public Ice::Service {
00379 protected:
00380 virtual bool start(int, char* argv[]);
00381 virtual bool stop() {
00382 if (itsMgr)
00383 delete itsMgr;
00384 return true;
00385 }
00386
00387 private:
00388 Ice::ObjectAdapterPtr itsAdapter;
00389 ModelManager *itsMgr;
00390 };
00391
00392 bool InferotemporalCortexService::start(int argc, char* argv[])
00393 {
00394
00395 itsMgr = new ModelManager("InferotemporalCortexService");
00396
00397 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(*itsMgr));
00398 itsMgr->addSubComponent(ofs);
00399
00400 nub::ref<InferotemporalCortexI> itc(new InferotemporalCortexI(*itsMgr, ofs));
00401 itsMgr->addSubComponent(itc);
00402
00403 itsMgr->parseCommandLine((const int)argc, (const char**)argv, "", 0, 0);
00404
00405 char adapterStr[255];
00406 sprintf(adapterStr, "default -p %i", BrainObjects::InferoTemporalPort);
00407 itsAdapter = communicator()->createObjectAdapterWithEndpoints("InferotemporalCortexAdapter",
00408 adapterStr);
00409
00410 Ice::ObjectPtr object = itc.get();
00411 Ice::ObjectPrx objectPrx = itsAdapter->add(object, communicator()->stringToIdentity("InferotemporalCortex"));
00412 itc->initSimEvents(communicator(), objectPrx);
00413 itsAdapter->activate();
00414
00415 itsMgr->start();
00416
00417 IceUtil::ThreadPtr itcThread = itc.get();
00418 itcThread->start();
00419
00420
00421 return true;
00422 }
00423
00424
00425 int main(int argc, char** argv) {
00426
00427 InferotemporalCortexService svc;
00428 return svc.main(argc, argv);
00429 }
00430
00431