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 #ifndef OBJREC_SERVERSIFT_C_DEFINED
00039 #define OBJREC_SERVERSIFT_C_DEFINED
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <signal.h>
00044 #include "Component/ModelManager.H"
00045 #include "Image/Image.H"
00046 #include "Image/ImageSet.H"
00047 #include "Image/ShapeOps.H"
00048 #include "Image/CutPaste.H"
00049 #include "Image/DrawOps.H"
00050 #include "Image/FilterOps.H"
00051 #include "Image/ColorOps.H"
00052 #include "Image/Transforms.H"
00053 #include "Image/MathOps.H"
00054 #include "Learn/Bayes.H"
00055 #include "GUI/DebugWin.H"
00056 #include "SIFT/ScaleSpace.H"
00057 #include "SIFT/VisualObject.H"
00058 #include "SIFT/Keypoint.H"
00059 #include "SIFT/VisualObjectDB.H"
00060 #include "NeovisionII/nv2_common.h"
00061 #include "NeovisionII/nv2_label_server.h"
00062 #include "rutz/fstring.h"
00063 #include "rutz/time.h"
00064 #include "rutz/timeformat.h"
00065
00066 #include <iostream>
00067
00068 const bool USECOLOR = false;
00069
00070 bool terminate = false;
00071
00072 void terminateProc(int s)
00073 {
00074 terminate = true;
00075 }
00076
00077 std::string matchObject(Image<PixRGB<byte> > &ima, VisualObjectDB& vdb, float &score)
00078 {
00079
00080 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches;
00081 rutz::shared_ptr<VisualObject>
00082 vo(new VisualObject("PIC", "PIC", ima,
00083 Point2D<int>(-1,-1),
00084 std::vector<float>(),
00085 std::vector< rutz::shared_ptr<Keypoint> >(),
00086 USECOLOR));
00087
00088 const uint nmatches = vdb.getObjectMatches(vo, matches, VOMA_SIMPLE,
00089 100U,
00090 0.5F,
00091 0.5F,
00092 1.0F,
00093 3U,
00094 100U,
00095 false
00096 );
00097
00098 score = 0;
00099 float avgScore = 0, affineAvgDist = 0;
00100 int nkeyp = 0;
00101 int objId = -1;
00102 if (nmatches > 0)
00103 {
00104 rutz::shared_ptr<VisualObject> obj;
00105 rutz::shared_ptr<VisualObjectMatch> vom;
00106
00107 for (unsigned int i = 0; i < 1; ++i)
00108 {
00109 vom = matches[i];
00110 obj = vom->getVoTest();
00111 score = vom->getScore();
00112 nkeyp = vom->size();
00113 avgScore = vom->getKeypointAvgDist();
00114 affineAvgDist = vom->getAffineAvgDist();
00115
00116 objId = atoi(obj->getName().c_str()+3);
00117
00118 return obj->getName();
00119 LINFO("### Object match with '%s' score=%f ID:%i",
00120 obj->getName().c_str(), vom->getScore(), objId);
00121
00122
00123
00124
00125 double dist = 0;
00126 for (int keyp=0; keyp<nkeyp; keyp++)
00127 {
00128 const KeypointMatch kpm = vom->getKeypointMatch(keyp);
00129
00130 float refX = kpm.refkp->getX();
00131 float refY = kpm.refkp->getY();
00132
00133 float tstX = kpm.tstkp->getX();
00134 float tstY = kpm.tstkp->getY();
00135 dist += (refX-tstX) * (refX-tstX);
00136 dist += (refY-tstY) * (refY-tstY);
00137 }
00138
00139
00140
00141
00142
00143 }
00144
00145 }
00146
00147 return std::string("nomatch");
00148 }
00149
00150 std::string getBestLabel(const std::deque<std::string>& labels,
00151 const size_t mincount)
00152 {
00153 if (labels.size() == 0)
00154 return std::string();
00155
00156 std::map<std::string, size_t> counts;
00157
00158 size_t bestcount = 0;
00159 size_t bestpos = 0;
00160
00161 for (size_t i = 0; i < labels.size(); ++i)
00162 {
00163 const size_t c = ++(counts[labels[i]]);
00164
00165 if (c >= bestcount)
00166 {
00167 bestcount = c;
00168 bestpos = i;
00169 }
00170 }
00171
00172 if (bestcount >= mincount)
00173 return labels[bestpos];
00174
00175 return std::string();
00176 }
00177
00178 namespace
00179 {
00180 void fillRegion(Image<PixRGB<byte> >& img, PixRGB<byte> col,
00181 const int x0, const int x1,
00182 const int y0, const int y1)
00183 {
00184 for (int x = x0; x < x1; ++x)
00185 for (int y = y0; y < y1; ++y)
00186 img.setVal(x, y, col);
00187 }
00188
00189 Image<PixRGB<byte> > makeColorbars(const int w, const int h)
00190 {
00191 Image<PixRGB<byte> > result = Image<PixRGB<byte> >(w, h, ZEROS);
00192
00193 const PixRGB<byte> cols[] =
00194 {
00195 PixRGB<byte>(255, 255, 255),
00196 PixRGB<byte>(255, 255, 0),
00197 PixRGB<byte>(0, 255, 255),
00198 PixRGB<byte>(0, 255, 0),
00199 PixRGB<byte>(255, 0, 255),
00200 PixRGB<byte>(255, 0, 0),
00201 PixRGB<byte>(0, 0, 255)
00202 };
00203
00204 int x1 = 0;
00205 for (int i = 0; i < 7; ++i)
00206 {
00207 const int x0 = x1+1;
00208 x1 = int(double(w)*(i+1)/7.0 + 0.5);
00209 fillRegion(result, cols[i],
00210 x0, x1,
00211 0, int(h*2.0/3.0));
00212 }
00213
00214 x1 = 0;
00215 for (int i = 0; i < 16; ++i)
00216 {
00217 const int x0 = x1;
00218 x1 = int(double(w)*(i+1)/16.0 + 0.5);
00219 const int gray = int(255.0*i/15.0 + 0.5);
00220 fillRegion(result, PixRGB<byte>(gray, gray, gray),
00221 x0, x1,
00222 int(h*2.0/3.0)+1, int(h*5.0/6.0));
00223 }
00224
00225 fillRegion(result, PixRGB<byte>(255, 0, 0),
00226 0, w,
00227 int(h*5.0/6.0)+1, h);
00228
00229 writeText(result, Point2D<int>(1, int(h*5.0/6.0)+2),
00230 "iLab Neuromorphic Vision",
00231 PixRGB<byte>(0, 0, 0), PixRGB<byte>(255, 0, 0),
00232 SimpleFont::FIXED(10));
00233
00234 return result;
00235 }
00236
00237 Image<PixRGB<byte> > addLabels(const Image<PixRGB<byte> >& templ,
00238 const int fnum)
00239 {
00240 Image<PixRGB<byte> > result = templ;
00241
00242 std::string fnumstr = sformat("%06d", fnum);
00243 writeText(result, Point2D<int>(1, 1),
00244 fnumstr.c_str(),
00245 PixRGB<byte>(0, 0, 0), PixRGB<byte>(255, 255, 255),
00246 SimpleFont::FIXED(10));
00247
00248 rutz::time t = rutz::time::wall_clock_now();
00249
00250 writeText(result, Point2D<int>(1, result.getHeight() - 14),
00251 rutz::format_time(t).c_str(),
00252 PixRGB<byte>(32, 32, 32), PixRGB<byte>(255, 0, 0),
00253 SimpleFont::FIXED(6));
00254
00255 return result;
00256 }
00257 }
00258
00259 int main(const int argc, const char **argv)
00260 {
00261
00262 MYLOGVERB = LOG_INFO;
00263 ModelManager mgr("Test ObjRec");
00264
00265 if (mgr.parseCommandLine(argc, argv, "<vdb file> <server ip>", 2, 2) == false)
00266 return 1;
00267
00268 mgr.start();
00269
00270
00271 signal(SIGHUP, terminateProc); signal(SIGINT, terminateProc);
00272 signal(SIGQUIT, terminateProc); signal(SIGTERM, terminateProc);
00273 signal(SIGALRM, terminateProc);
00274
00275
00276 const std::string vdbFile = mgr.getExtraArg(0);
00277 const std::string server_ip = mgr.getExtraArg(1);
00278 bool train = false;
00279
00280 LINFO("Loading db from %s\n", vdbFile.c_str());
00281 VisualObjectDB vdb;
00282 vdb.loadFrom(vdbFile);
00283
00284 XWinManaged xwin(Dims(256,256),
00285 -1, -1, "ILab Robot Head Demo");
00286
00287
00288 struct nv2_label_server* labelServer =
00289 nv2_label_server_create(9930,
00290 server_ip.c_str(),
00291 9931);
00292
00293 nv2_label_server_set_verbosity(labelServer,1);
00294
00295
00296 const size_t max_label_history = 1;
00297 std::deque<std::string> recent_labels;
00298
00299 Image<PixRGB<byte> > colorbars = makeColorbars(256, 256);
00300
00301 while (!terminate)
00302 {
00303 Point2D<int> clickLoc = xwin.getLastMouseClick();
00304 if (clickLoc.isValid())
00305 train = !train;
00306
00307 struct nv2_image_patch p;
00308 const enum nv2_image_patch_result res =
00309 nv2_label_server_get_current_patch(labelServer, &p);
00310
00311 std::string objName;
00312 if (res == NV2_IMAGE_PATCH_END)
00313 {
00314 LINFO("ok, quitting");
00315 break;
00316 }
00317 else if (res == NV2_IMAGE_PATCH_NONE)
00318 {
00319 usleep(10000);
00320 continue;
00321 }
00322 else if (res == NV2_IMAGE_PATCH_VALID)
00323 {
00324 if (p.type != NV2_PIXEL_TYPE_RGB24)
00325 {
00326 LINFO("got a non-rgb24 patch; ignoring %i", p.type);
00327 continue;
00328 }
00329
00330 if (p.width * p.height == 1)
00331 {
00332 xwin.drawImage(addLabels(colorbars, p.id));
00333 continue;
00334 }
00335
00336 Image<PixRGB<byte> > img(p.width, p.height, NO_INIT);
00337 memcpy(img.getArrayPtr(), p.data, p.width*p.height*3);
00338
00339 Image<PixRGB<byte> > inputImg = rescale(img, 256, 256);
00340
00341 xwin.drawImage(inputImg);
00342 float score = 0;
00343 std::string objName = matchObject(inputImg, vdb, score);
00344
00345 if (objName == "nomatch")
00346 {
00347 recent_labels.resize(0);
00348
00349 if (train)
00350 {
00351 LINFO("Enter a label for this object:\n");
00352 std::getline(std::cin, objName);
00353 LINFO("You typed '%s'\n", objName.c_str());
00354
00355 if (objName == "exit")
00356 break;
00357 else if (objName != "")
00358 {
00359 rutz::shared_ptr<VisualObject>
00360 vo(new VisualObject(objName.c_str(), "NULL", inputImg,
00361 Point2D<int>(-1,-1),
00362 std::vector<float>(),
00363 std::vector< rutz::shared_ptr<Keypoint> >(),
00364 USECOLOR));
00365 vdb.addObject(vo);
00366 vdb.saveTo(vdbFile);
00367 }
00368 }
00369 }
00370 else
00371 {
00372 recent_labels.push_back(objName);
00373 while (recent_labels.size() > max_label_history)
00374 recent_labels.pop_front();
00375
00376 const std::string bestObjName =
00377 getBestLabel(recent_labels, 1);
00378
00379 if (bestObjName.size() > 0)
00380 {
00381 struct nv2_patch_label l;
00382 l.protocol_version = NV2_LABEL_PROTOCOL_VERSION;
00383 l.patch_id = p.id;
00384 l.confidence = (int)(score*100.0F);
00385 snprintf(l.source, sizeof(l.source), "%s",
00386 "ObjRec");
00387 snprintf(l.name, sizeof(l.name), "%s",
00388 objName.c_str());
00389 snprintf(l.extra_info, sizeof(l.extra_info),
00390 "%ux%u #%u",
00391 (unsigned int) p.width,
00392 (unsigned int) p.height,
00393 (unsigned int) p.id);
00394
00395 nv2_label_server_send_label(labelServer, &l);
00396
00397 LINFO("sent label '%s (%s)'\n", l.name, l.extra_info);
00398 }
00399 }
00400
00401 nv2_image_patch_destroy(&p);
00402 }
00403
00404 }
00405
00406 if (terminate)
00407 LINFO("Ending application because a signal was caught");
00408
00409 nv2_label_server_destroy(labelServer);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419 #endif