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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "Beowulf/Beowulf.H"
00050 #include "Component/ModelManager.H"
00051 #include "Devices/BeoChip.H"
00052 #include "Devices/DeviceOpts.H"
00053 #include "Devices/FrameGrabberConfigurator.H"
00054 #include "Image/ColorOps.H"
00055 #include "Image/CutPaste.H"
00056 #include "Image/DrawOps.H"
00057 #include "Image/FilterOps.H"
00058 #include "Image/Image.H"
00059 #include "Image/ImageSet.H"
00060 #include "Image/MathOps.H"
00061 #include "Image/ShapeOps.H"
00062 #include "Neuro/NeuroOpts.H"
00063 #include "Neuro/SaccadeController.H"
00064 #include "Neuro/SaccadeControllerConfigurator.H"
00065 #include "Parallel/pvisionTCP-defs.H"
00066 #include "Simulation/SimEventQueue.H"
00067 #include "Simulation/SimEventQueueConfigurator.H"
00068 #include "Transport/FrameIstream.H"
00069 #ifdef HAVE_SDL_SDL_H
00070 #include "Psycho/PsychoDisplay.H"
00071 #endif
00072 #include "Util/Assert.H"
00073 #include "Util/Timer.H"
00074 #include "Util/sformat.H"
00075 #include "Video/RgbConversion.H"
00076
00077 #include <signal.h>
00078 #include <unistd.h>
00079
00080
00081
00082 #define SERVO_PAN 6
00083
00084
00085 #define SERVO_TILT 7
00086
00087
00088 #define NAVG 20
00089
00090
00091 #define PRESCALE 2
00092
00093 static bool goforever = true;
00094
00095
00096 void terminate(int s)
00097 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); }
00098
00099
00100 void receiveCMAPS(nub::soft_ref<Beowulf>& beo, Image<float> *cmap,
00101 int32 *cmapframe);
00102
00103
00104 extern "C" int main(const int argc, char** argv)
00105 {
00106 #ifndef HAVE_SDL_SDL_H
00107
00108 LFATAL("<SDL/SDL.h> must be installed to use this program");
00109
00110 #else
00111
00112 MYLOGVERB = LOG_INFO;
00113
00114
00115 ModelManager manager("Parallel Vision TCP Version 3");
00116
00117
00118 nub::soft_ref<SimEventQueueConfigurator>
00119 seqc(new SimEventQueueConfigurator(manager));
00120 manager.addSubComponent(seqc);
00121
00122 nub::soft_ref<FrameGrabberConfigurator>
00123 gbc(new FrameGrabberConfigurator(manager));
00124 manager.addSubComponent(gbc);
00125
00126 nub::soft_ref<Beowulf>
00127 beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true));
00128 manager.addSubComponent(beo);
00129
00130 nub::soft_ref<PsychoDisplay>
00131 d(new PsychoDisplay(manager));
00132 manager.addSubComponent(d);
00133
00134 nub::soft_ref<SaccadeControllerEyeConfigurator>
00135 scc(new SaccadeControllerEyeConfigurator(manager));
00136 manager.addSubComponent(scc);
00137
00138 nub::soft_ref<BeoChip>
00139 bc(new BeoChip(manager));
00140 manager.addSubComponent(bc);
00141
00142
00143 manager.exportOptions(MC_RECURSE);
00144 manager.setOptionValString(&OPT_SaccadeControllerEyeType, "Threshfric");
00145 manager.setOptionValString(&OPT_FrameGrabberType, "V4L");
00146 manager.setOptionValString(&OPT_SCeyeMaxIdleSecs, "1000.0");
00147 manager.setOptionValString(&OPT_SCeyeThreshMinOvert, "4.0");
00148 manager.setOptionValString(&OPT_SCeyeThreshMaxCovert, "3.0");
00149
00150 bc->calibrateServo(SERVO_PAN, 128, 0, 255);
00151 bc->calibrateServo(SERVO_TILT, 128, 0, 255);
00152 bc->setServo(SERVO_PAN, 0.0f);
00153 bc->setServo(SERVO_TILT, 0.0f);
00154
00155
00156 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00157
00158
00159 nub::soft_ref<SimEventQueue> seq = seqc->getQ();
00160
00161 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber();
00162 if (gb.isInvalid())
00163 LFATAL("You need to select a frame grabber type via the "
00164 "--fg-type=XX command-line option for this program "
00165 "to be useful");
00166 int w = gb->getWidth(), h = gb->getHeight();
00167
00168 nub::ref<SaccadeController> sc = scc->getSC();
00169
00170 int foa_size = std::min(w, h) / 12;
00171 manager.setModelParamVal("InputFrameDims", Dims(w, h),
00172 MC_RECURSE | MC_IGNORE_MISSING);
00173 manager.setModelParamVal("SCeyeStartAtIP", true,
00174 MC_RECURSE | MC_IGNORE_MISSING);
00175 manager.setModelParamVal("SCeyeInitialPosition",Point2D<int>(w/2,h/2),
00176 MC_RECURSE | MC_IGNORE_MISSING);
00177 manager.setModelParamVal("FOAradius", foa_size,
00178 MC_RECURSE | MC_IGNORE_MISSING);
00179 manager.setModelParamVal("FoveaRadius", foa_size,
00180 MC_RECURSE | MC_IGNORE_MISSING);
00181
00182
00183 signal(SIGHUP, terminate); signal(SIGINT, terminate);
00184 signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00185 signal(SIGALRM, terminate);
00186
00187
00188 int32 frame = 0;
00189 PixRGB<byte> pix(255, 255, 0);
00190 TCPmessage smsg;
00191
00192 uint64 avgtime = 0; int avgn = 0;
00193 float fps = 0.0F;
00194 Timer tim;
00195 Timer masterclock;
00196
00197 Image<float> cmap[NBCMAP2];
00198 int32 cmapframe[NBCMAP2];
00199 for (int i = 0; i < NBCMAP2; i ++) cmapframe[i] = -1;
00200 int sml = 4;
00201 Image<float> sm(w >> sml, h >> sml, ZEROS);
00202 Point2D<int> fixation(-1, -1);
00203
00204
00205 Image<PixRGB<byte> > disp(w * 2, h + 20, ZEROS);
00206 disp += d->getGrey();
00207 int dw = d->getDims().w(), dh = d->getDims().h();
00208 ASSERT(dw == w * 2); ASSERT(dh >= disp.getHeight());
00209 int ovlyoff = (w * 2) * ((dh - disp.getHeight()) / 2);
00210 int ovluvoff = ovlyoff / 4;
00211
00212
00213 manager.start();
00214
00215
00216 bc->lcdClear();
00217 bc->lcdPrintf(0, 0, "pvisionTCP3-nerdcam ");
00218 bc->lcdPrintf(0, 1, "Pan: --- Tilt:---");
00219 bc->lcdPrintf(0, 2, "xFOA:--- yFOA:---");
00220 bc->lcdPrintf(0, 3, "xFOV:--- yFOV:---");
00221
00222
00223 d->clearScreen();
00224 d->displayText("<SPACE> to start - <SPACE> again to quit");
00225 while(d->waitForKey() != ' ') ;
00226 d->clearScreen();
00227
00228
00229 d->createYUVoverlay(SDL_YV12_OVERLAY);
00230
00231
00232 gb->startStream();
00233
00234
00235 tim.reset(); masterclock.reset();
00236
00237
00238 while(goforever)
00239 {
00240
00241 receiveCMAPS(beo, cmap, cmapframe);
00242
00243
00244 Image< PixRGB<byte> > ima = gb->readRGB();
00245
00246
00247 inplacePaste(disp, ima, Point2D<int>(0, 0));
00248 Image<float> dispsm(sm); inplaceNormalize(dispsm, 0.0F, 255.0F);
00249 inplacePaste(disp,
00250 Image<PixRGB<byte> >(toRGB(quickInterpolate(dispsm, 1 << sml))),
00251 Point2D<int>(w, 0));
00252
00253 sc->evolve(*seq);
00254 Point2D<int> eye = sc->getDecision(*seq);
00255 if (eye.i >= 0) fixation = eye;
00256 if (fixation.i >= 0)
00257 {
00258 drawPatch(disp, fixation, 2, pix);
00259 drawCircle(disp, fixation, foa_size, pix, 2);
00260 }
00261 writeText(disp, Point2D<int>(w, 0), sformat("%.1ffps", fps).c_str(),
00262 PixRGB<byte>(255), PixRGB<byte>(0));
00263
00264 SDL_Overlay* ovl = d->lockYUVoverlay();
00265 toVideoYUV422(disp, ovl->pixels[0] + ovlyoff,
00266 ovl->pixels[2] + ovluvoff,
00267 ovl->pixels[1] + ovluvoff);
00268 d->unlockYUVoverlay();
00269 d->displayYUVoverlay(-1, SDLdisplay::NO_WAIT);
00270
00271
00272
00273 if (d->checkForKey() == ' ') goforever = false;
00274
00275
00276 receiveCMAPS(beo, cmap, cmapframe);
00277
00278
00279 if (frame & 1)
00280 {
00281
00282 Image<PixRGB<byte> > ima2 =
00283 decY(lowPass5y(decX(lowPass5x(ima),1<<PRESCALE)),1<<PRESCALE);
00284
00285
00286
00287 Image<byte> lum = luminance(ima2);
00288
00289
00290 smsg.reset(frame, BEO_ORI0); smsg.addImage(lum); beo->send(smsg);
00291 smsg.setAction(BEO_ORI45); beo->send(smsg);
00292 smsg.setAction(BEO_ORI90); beo->send(smsg);
00293 smsg.setAction(BEO_ORI135); beo->send(smsg);
00294
00295
00296 smsg.setAction(BEO_FLICKER); beo->send(smsg);
00297
00298
00299 smsg.setAction(BEO_LUMINANCE); beo->send(smsg);
00300
00301
00302 Image<byte> r, g, b, y; getRGBY(ima2, r, g, b, y, (byte)25);
00303 smsg.reset(frame, BEO_REDGREEN);
00304 smsg.addImage(r); smsg.addImage(g); beo->send(smsg);
00305 smsg.reset(frame, BEO_BLUEYELLOW);
00306 smsg.addImage(b); smsg.addImage(y); beo->send(smsg);
00307 }
00308
00309
00310 receiveCMAPS(beo, cmap, cmapframe);
00311
00312
00313 std::string info = sformat("%06d / ", frame);
00314 Image<float> sminput;
00315 for (int i = 0; i < NBCMAP2; i ++)
00316 if (cmap[i].initialized())
00317 {
00318 if (sminput.initialized()) sminput += cmap[i];
00319 else sminput = cmap[i];
00320 info += sformat("%06d ", cmapframe[i]);
00321 }
00322 else
00323 info += "------ ";
00324 writeText(disp, Point2D<int>(0, h), info.c_str(),
00325 PixRGB<byte>(255), d->getGrey());
00326
00327
00328 if (sminput.initialized()) sm = sm * 0.7F + sminput * 0.3F;
00329
00330
00331 while(seq->now() < masterclock.getSimTime()) seq->evolve();
00332 sc->evolve(*seq);
00333
00334
00335 float maxval; Point2D<int> currwin; findMax(sm, currwin, maxval);
00336 WTAwinner newwin =
00337 WTAwinner::buildFromSMcoords(currwin, sml, true,
00338 masterclock.getSimTime(),
00339 maxval, false);
00340 if (newwin.isValid()) sc->setPercept(newwin, *seq);
00341
00342
00343 receiveCMAPS(beo, cmap, cmapframe);
00344
00345
00346 avgtime += tim.getReset(); avgn ++;
00347 if (avgn == NAVG)
00348 {
00349 fps = 1000.0F / float(avgtime) * float(avgn);
00350 avgtime = 0; avgn = 0;
00351 }
00352
00353
00354 if ((frame & 1) == 0)
00355 {
00356 bc->lcdPrintf(0, 1, "Pan: %03d Tilt:%03d",
00357 bc->getServoRaw(SERVO_PAN),
00358 bc->getServoRaw(SERVO_TILT));
00359 bc->lcdPrintf(0, 2, "xFOA:%03d yFOA:%03d",
00360 newwin.p.i, newwin.p.j);
00361 bc->lcdPrintf(0, 3, "xFOV:%03d yFOV:%03d",
00362 fixation.i, fixation.j);
00363 }
00364
00365
00366 float pan = bc->getServo(SERVO_PAN) +
00367 float(fixation.i)/float(w) - 0.5f;
00368 float tilt = bc->getServo(SERVO_TILT) +
00369 float(fixation.j)/float(h) - 0.5f;
00370 if (pan < -1.0f) pan = -1.0f; else if (pan > 1.0f) pan = 1.0f;
00371 if (tilt < -1.0f) tilt = -1.0f; else if (tilt > 1.0f) tilt = 1.0f;
00372
00373 bc->setServo(SERVO_PAN, pan);
00374 bc->setServo(SERVO_TILT, tilt);
00375
00376
00377 frame++;
00378 while(seq->now() < masterclock.getSimTime()) seq->evolve();
00379 }
00380
00381
00382 d->destroyYUVoverlay();
00383 LINFO("Normal exit");
00384 manager.stop();
00385 return 0;
00386
00387 #endif
00388
00389 }
00390
00391
00392 void receiveCMAPS(nub::soft_ref<Beowulf>& beo, Image<float> *cmap,
00393 int32 *cmapframe)
00394 {
00395 TCPmessage rmsg;
00396 int32 rframe, raction, rnode = -1, recnb=0;
00397 while(beo->receive(rnode, rmsg, rframe, raction))
00398 {
00399
00400
00401 switch(raction & 0xffff)
00402 {
00403 case BEO_CMAP:
00404 {
00405
00406 Image<float> ima = rmsg.getElementFloatIma();
00407
00408
00409
00410 int32 mapn = raction >> 16;
00411 if (mapn < 0 || mapn >= NBCMAP2) {
00412 LERROR("Bogus cmap number ignored");
00413 break;
00414 }
00415
00416
00417
00418
00419
00420 if (cmapframe[mapn] < rframe)
00421 { cmap[mapn] = ima; cmapframe[mapn] = rframe; }
00422 }
00423
00424 break;
00425 default:
00426 LERROR("Bogus action %d -- IGNORING.", raction);
00427 break;
00428 }
00429
00430 recnb ++; if (recnb > NBCMAP2 * 2) break;
00431 }
00432 }
00433
00434
00435
00436
00437
00438