BorderWatchQt.qt.C

Go to the documentation of this file.
00001 /*!@file Apps/BorderWatch/BorderWatchQt.qt.C Simple GUI for BorderWatch */
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: Laurent Itti
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Apps/BorderWatch/BorderWatchQt.qt.C $
00035 // $Id: BorderWatchQt.qt.C 13059 2010-03-26 08:14:32Z itti $
00036 //
00037 
00038 #include "Apps/BorderWatch/BorderWatchQt.qt.H"
00039 
00040 #include <QtCore/QTimer>
00041 #include <QtGui/QLabel>
00042 #include <QtGui/QVBoxLayout>
00043 #include <QtGui/QHBoxLayout>
00044 #include <QtGui/QListWidget>
00045 #include <QtGui/QSplitter>
00046 #include <QtGui/QFrame>
00047 #include <QtGui/QProgressBar>
00048 #include <QtGui/QLineEdit>
00049 #include <QtGui/QCheckBox>
00050 
00051 #include "Apps/BorderWatch/BorderWatchData.H"
00052 #include "Image/DrawOps.H"
00053 #include "Image/ShapeOps.H"
00054 #include "QtUtil/ImageConvert4.H"
00055 #include "Raster/GenericFrame.H"
00056 #include "Util/log.H"
00057 #include "Util/sformat.H"
00058 
00059 #include <cstdio>
00060 
00061 // ######################################################################
00062 BorderWatchQt::BorderWatchQt(std::vector<GenericFrame>& frames, std::vector<BorderWatchData>& data, QWidget* parent) :
00063   QWidget(parent), itsThreshold(4.0e-10F), itsFrames(frames), itsLogData(data), itsListIndex(0),
00064   itsMovieFrame(0), itsZoomed(false)
00065 {
00066   QVBoxLayout *main = new QVBoxLayout(this);
00067   main->setSpacing(4);
00068   main->setMargin(2);
00069 
00070   QSplitter* splitter = new QSplitter(Qt::Horizontal, this);
00071   splitter->setChildrenCollapsible(false);
00072 
00073   itsListWidget = new QListWidget(this);
00074   itsListWidget->setMinimumWidth(180);
00075 
00076   splitter->addWidget(itsListWidget);
00077   connect(itsListWidget, SIGNAL(currentRowChanged(int)), this, SLOT(listChanged(int)));
00078 
00079   QFrame *frame = new QFrame(this);
00080   frame->setFrameShape(QFrame::StyledPanel);
00081 
00082   QVBoxLayout *panel = new QVBoxLayout;
00083 
00084   QHBoxLayout *ed = new QHBoxLayout;
00085   ed->addStretch(1);
00086 
00087   QLabel *lbl = new QLabel("Threshold:", this);
00088   ed->addWidget(lbl);
00089 
00090   itsThreshEdit = new QLineEdit(sformat("%g", itsThreshold).c_str(), this);
00091   ed->addWidget(itsThreshEdit);
00092   connect(itsThreshEdit, SIGNAL(editingFinished()), this, SLOT(threshChanged()));
00093 
00094   ed->addStretch(1);
00095 
00096   QLabel *lbl2 = new QLabel("       Zoom X2:", this);
00097   ed->addWidget(lbl2);
00098 
00099   QCheckBox *chk = new QCheckBox(this);
00100   chk->setCheckState(Qt::Checked); itsZoomed = true;
00101   connect(chk, SIGNAL(stateChanged(int)), this, SLOT(zoomChanged(int)));
00102   ed->addWidget(chk);
00103 
00104   ed->addStretch(1);
00105 
00106   panel->addLayout(ed);
00107 
00108   QFrame* hline = new QFrame(this);
00109   hline->setFrameShape(QFrame::HLine);
00110   hline->setFrameShadow(QFrame::Raised);
00111   hline->setLineWidth(2);
00112   panel->addWidget(hline);
00113 
00114   panel->addStretch(1);
00115 
00116   QHBoxLayout* himage = new QHBoxLayout;
00117   himage->addStretch(1);
00118   itsFrameWidget = new QLabel(this);
00119   himage->addWidget(itsFrameWidget);
00120   himage->addStretch(1);
00121 
00122   panel->addLayout(himage);
00123 
00124   panel->addStretch(1);
00125 
00126   itsProgressBar = new QProgressBar(this);
00127   panel->addWidget(itsProgressBar);
00128 
00129   panel->addStretch(1);
00130 
00131   frame->setLayout(panel);
00132   splitter->addWidget(frame);
00133 
00134   splitter->setStretchFactor(0, 1);
00135   splitter->setStretchFactor(1, 7);  // preferentially stretch the image pane over the text list pane
00136 
00137   splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00138   main->addWidget(splitter);
00139 
00140   itsStatusLabel = new QLabel("Status: Idle.", this);
00141   itsStatusLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
00142   main->addWidget(itsStatusLabel);
00143 
00144   this->setLayout(main);
00145 
00146   // populate the list with a bunch of events:
00147   parseEvents();
00148 
00149   // get our timer going:
00150   itsTimer = new QTimer(this);
00151   itsTimer->setInterval(33); // in milliseconds
00152   connect(itsTimer, SIGNAL(timeout()), this, SLOT(timerTick()));
00153   itsTimer->start();
00154 }
00155 
00156 // ######################################################################
00157 BorderWatchQt::~BorderWatchQt()
00158 {
00159   itsTimer->stop();
00160 }
00161 
00162 // ######################################################################
00163 void BorderWatchQt::listChanged(const int idx)
00164 {
00165   itsListIndex = idx;
00166   if (itsEvents.size()) {
00167     const uint estart = itsEvents[idx].start, eend = itsEvents[idx].end;
00168 
00169     itsListWidget->setCurrentRow(itsListIndex);
00170     itsMovieFrame = estart;
00171     itsProgressBar->setRange(estart, eend - 1);
00172     itsProgressBar->setValue(estart);
00173 
00174     // compute max score achieved over this event:
00175     float mscore = 0.0F;
00176     for (uint i = estart; i < eend; ++i) mscore = std::max(mscore, itsLogData[i].score);
00177 
00178     itsStatusLabel->setText(sformat("Event %d || Frames: %06u - %06u || Max Score: %g", idx,
00179                                     estart, eend-1, mscore).c_str());
00180   }
00181 }
00182 
00183 // ######################################################################
00184 void BorderWatchQt::parseEvents()
00185 {
00186   itsEvents.clear(); itsListWidget->clear(); bool inevent = false; const uint margin = 33; uint i = 0;
00187   char buf[100]; uint count = 0;
00188   std::vector<BorderWatchData>::const_iterator itr = itsLogData.begin(), stop = itsLogData.end();
00189   BWevent e;
00190   while (itr != stop) {
00191     // are we above threshold?
00192     if (itr->score >= itsThreshold) {
00193       count = 0; // then continue any ongoing event
00194       // start a new event?
00195       if (inevent == false)
00196         { inevent = true; e.start = i; if (e.start <= margin) e.start = 0; else e.start -= margin; }
00197     }
00198 
00199     // write out a completed event?
00200     if (inevent && count > margin) {
00201       inevent = false; count = 0; e.end = i;
00202       itsEvents.push_back(e);
00203       snprintf(buf, 100, "%04"ZU": %06u-%06u", itsEvents.size(), e.start, e.end);
00204       itsListWidget->addItem(buf);
00205     }
00206     ++itr; ++i; ++count;
00207   }
00208 
00209   // maybe one last event is still open:
00210   if (inevent) {
00211     e.end = itsLogData.size()-1;
00212     itsEvents.push_back(e);
00213     snprintf(buf, 100, "%04"ZU": %06u-%06u", itsEvents.size(), e.start, e.end);
00214     itsListWidget->addItem(buf);
00215   }
00216 
00217   // reset our position in our list:
00218   listChanged(0);
00219 
00220   snprintf(buf, 100, "Extracted %"ZU" events above threshold = %e", itsEvents.size(), itsThreshold);
00221   itsStatusLabel->setText(buf);
00222 }
00223 
00224 // ######################################################################
00225 void BorderWatchQt::timerTick()
00226 {
00227   if (itsEvents.size()) {
00228     // get the current movie frame and log data:
00229     GenericFrame genframe = itsFrames[itsMovieFrame];
00230     Image<PixRGB<byte> > im = genframe.asRgbU8();
00231     if (itsZoomed) im = quickInterpolate(im, 2);
00232     BorderWatchData& d = itsLogData[itsMovieFrame];
00233 
00234     // add some drawings:
00235     Point2D<int> p = d.salpoint; if (itsZoomed) { p.i *= 2; p.j *= 2; }
00236     if (d.score > itsThreshold) drawCircle(im, p, itsZoomed ? 30 : 15, PixRGB<byte>(255,255,0), 2);
00237     else drawCircle(im, p, itsZoomed ? 10 : 5, PixRGB<byte>(0,128,0), 1);
00238     writeText(im, Point2D<int>(10,0), sformat("%s - S=%g %06d", d.itime.c_str(), d.score, d.iframe).c_str(),
00239               PixRGB<byte>(255, 64, 0), PixRGB<byte>(0), SimpleFont::FIXED(6), true);
00240 
00241     // display the image in our widget:
00242     QPixmap pixmap = convertToQPixmap4(im);
00243     itsFrameWidget->setPixmap(pixmap);
00244 
00245     // update progress bar:
00246     itsProgressBar->setValue(itsMovieFrame);
00247 
00248     // roll on to the next frame:
00249     ++itsMovieFrame; if (itsMovieFrame >= itsEvents[itsListIndex].end) itsMovieFrame = itsEvents[itsListIndex].start;
00250   }
00251 }
00252 
00253 // ######################################################################
00254 void BorderWatchQt::threshChanged()
00255 {
00256   QString txt = itsThreshEdit->text(); bool ok;
00257   float t = txt.toFloat(&ok);
00258 
00259   if (ok) { itsThreshold = t; parseEvents(); }
00260   else itsStatusLabel->setText("Invalid threshold value");
00261 }
00262 
00263 // ######################################################################
00264 void BorderWatchQt::zoomChanged(int state)
00265 {
00266   if (state == Qt::Checked) itsZoomed = true; else itsZoomed = false;
00267 }
00268 
00269 // ######################################################################
00270 /* So things look consistent in everyone's emacs... */
00271 /* Local Variables: */
00272 /* mode: c++ */
00273 /* indent-tabs-mode: nil */
00274 /* End: */
Generated on Sun May 8 08:40:11 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3