ncutVis.h

00001 #ifndef NCUT_VIS_H
00002 #define NCUT_VIS_H 1
00003 
00004 #include "ncutCore.h"
00005 #include <math.h>
00006 #include <time.h>
00007 #include <iostream>
00008 
00009 namespace ncut
00010 {
00011 
00012 struct PNG_color_t {
00013   PNG_IMAGE_DATATYPE red;
00014   PNG_IMAGE_DATATYPE green;
00015   PNG_IMAGE_DATATYPE blue;
00016 };
00017 
00022 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE, class VIS_ELM_TYPE>
00023 class Vis
00024 {
00025   public:
00026     
00031     inline const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* seg() const
00032     {return seg_;}
00033 
00034     
00040     virtual void create(Sequence<VIS_ELM_TYPE>& resultSequence, int topFrame = -1);
00041 
00046     Vis(const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* segmentation);
00047 //     Vis(const Vis& clone);
00048 
00049 
00053     virtual ~Vis();
00054 
00055   protected:
00056 
00057     const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* seg_; 
00060 //     Vis& operator=(const Vis&);
00061 };
00062 
00067 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00068 class PNGVis : public Vis<IMG_ELM_TYPE, MSK_ELM_TYPE, PNG_IMAGE_DATATYPE>
00069 {
00070   public:
00071 
00072     inline const std::map<MSK_ELM_TYPE,std::vector<int> >& rememberedPosX() const
00073     { return rememberedPosX_; }
00074     inline const std::map<MSK_ELM_TYPE,std::vector<int> >& rememberedPosY() const
00075     { return rememberedPosY_; }
00076     inline const std::map<MSK_ELM_TYPE,double>& segmentSumArea() const
00077     { return segmentSumArea_; };
00078     int firstFrame(const MSK_ELM_TYPE& segId) const;
00079 
00085     virtual void create(PNGSequence& resultSequence, int topFrame = -1);
00086 
00096     virtual int drawLine(int x1, int y1, int x2, int y2, PNGImage *image);
00097 
00102     PNGVis(const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* segmentation);
00103 
00104     
00108     virtual ~PNGVis();
00109 
00110 
00111   protected:
00112 
00113     int baseFrame_; 
00115     std::vector<PNG_color_t> colors_; 
00116     std::map<MSK_ELM_TYPE, unsigned int> colorMap_; 
00118     std::map<MSK_ELM_TYPE,std::vector<int> > rememberedPosX_; 
00120     std::map<MSK_ELM_TYPE,std::vector<int> > rememberedPosY_;
00122     std::map<MSK_ELM_TYPE,double > segmentSumArea_; 
00125     std::map<MSK_ELM_TYPE, int> firstFrame_; 
00128   private:
00129 
00130     virtual void mode_segmentedObjects(PNGImage* image, int cmp,
00131                                        int pxl, int frm);
00132     virtual void mode_original(PNGImage* image, int cmp, int frm);
00133 
00134     virtual unsigned long calculateElementNr(int x, int y,
00135                                              const PNGImage* image);
00136 
00137 };
00138 
00139 
00140 /* template implementations ---------------------------------------------- */
00141 
00142 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE, class VIS_ELM_TYPE>
00143 void Vis<IMG_ELM_TYPE, MSK_ELM_TYPE, VIS_ELM_TYPE>::
00144     create(Sequence<VIS_ELM_TYPE>& seq, int topFrame)
00145 {
00146   // dummy function
00147 
00148   return;
00149 }
00150 
00151 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE, class VIS_ELM_TYPE>
00152 Vis<IMG_ELM_TYPE, MSK_ELM_TYPE, VIS_ELM_TYPE>::
00153     Vis(const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* _seg)
00154   : seg_(_seg)
00155 {
00156   if (this->seg_ == NULL)
00157     throw ncutException("invalid segmentation (NULL)");
00158 }
00159 
00160 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE, class VIS_ELM_TYPE>
00161 Vis<IMG_ELM_TYPE, MSK_ELM_TYPE, VIS_ELM_TYPE>::~Vis()
00162 {
00163   return;
00164 }
00165 
00166 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00167 int PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::
00168     firstFrame(const MSK_ELM_TYPE& segId) const
00169 {
00170   typename std::map<MSK_ELM_TYPE, int>::const_iterator firstFrame_p;
00171 
00172   firstFrame_p = firstFrame_.find(segId);
00173   if (firstFrame_p == firstFrame_.end())
00174     throw ncutException("segment not found");
00175 
00176   return firstFrame_p->second;
00177 }
00178 
00179 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00180 void PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::create(PNGSequence& seq, int topFrame)
00181 {
00182 #ifdef debugout
00183   clock_t timerStart, timerEnd;
00184 
00185   std::cout << "building the visualization..." << std::flush;
00186   timerStart = clock();
00187 #endif
00188 
00189   // update the frame number
00190   if (topFrame == -1) baseFrame_++;
00191   else                baseFrame_ = topFrame - this->seg()->nFrm() + 1;
00192   if (baseFrame_ < 0)
00193     throw ncutException(
00194         "invalid frame number, must be >= number of frames in frame window" );
00195 
00196   // create new empty PNG image
00197   PNGImage *segmentedImage = new
00198       PNGImage(this->seg_->width(),this->seg_->height(),this->seg_->nChl());
00199 
00200   // create a list of unused colors
00201   std::list<unsigned int> freeColors;
00202   for (unsigned int cIdx = 1; cIdx < colors_.size(); cIdx++)
00203     freeColors.push_back(cIdx);
00204 
00205   typename std::map<MSK_ELM_TYPE, unsigned int>::iterator segColor =
00206       colorMap_.begin();
00207   typename std::map<MSK_ELM_TYPE, unsigned int>::iterator eraseItr;
00208   while (segColor != colorMap_.end()) {
00209     if (this->seg_->indices()->find(segColor->first) ==
00210         this->seg_->indices()->end()) {
00211       // segment inactive
00212       eraseItr = segColor++;
00213       colorMap_.erase(eraseItr);
00214     }
00215     else {
00216       // segment still active
00217       freeColors.remove(segColor->second);
00218       segColor++;
00219     }
00220   }
00221 
00222   // iterator used to iterate through the segment indices map
00223   typename std::map<MSK_ELM_TYPE, unsigned int>::const_iterator segment;
00224 
00225   // assign a color to each segment (black if there aren't enough colors)
00226   for (segment =  this->seg_->indices()->begin();
00227        segment != this->seg_->indices()->end(); segment++) {
00228     if (colorMap_.find(segment->first) == colorMap_.end()) {
00229       if (freeColors.empty()) {
00230         colorMap_[segment->first] = 0;
00231         std::cerr << "not enough colors, using black" << std::endl;
00232       }
00233       else {
00234         colorMap_[segment->first] = freeColors.back();
00235         freeColors.pop_back();
00236       }
00237     }
00238   }
00239 
00240   unsigned long cmp;
00241   for (unsigned int frm = 0; frm < this->seg_->nFrm(); frm++) {
00242 
00243     // draw each pixel of the visualization into the PNG image
00244     for (unsigned int pxl = 0;
00245          pxl < this->seg_->width()*this->seg_->height(); pxl++) {
00246 
00247       cmp = pxl*this->seg_->nChl();
00248 
00249       switch(ncut_Setting.visualisation_mode) {
00250         //case 0: is default
00251         case 1:   mode_original(segmentedImage, cmp, frm);
00252         break;
00253         default:  mode_segmentedObjects(segmentedImage, cmp, pxl, frm);
00254         break;
00255       }
00256     }
00257 
00258 
00259     if (frm == 1) {
00260 
00261       // save the current position of each active segment
00262       for (segment =  this->seg_->indices()->begin();
00263            segment != this->seg_->indices()->end(); segment++) {
00264 
00265         int x = static_cast<int>
00266             (round (this->seg_->locationX(segment->second)));
00267         int y = static_cast<int>
00268             (round (this->seg_->locationY(segment->second)));
00269 #ifdef debugout
00270         std::cout << "seg " << segment->first << " - x " << x
00271             << " - y " << y << std::endl << std::flush;
00272 #endif
00273 
00274         rememberedPosX_[segment->first].push_back(x);
00275         rememberedPosY_[segment->first].push_back(y);
00276 
00277         segmentSumArea_[segment->first] += this->seg_->nPixels(segment->second);
00278 
00279         if (rememberedPosX_[segment->first].size() == 1)
00280           firstFrame_[segment->first] = baseFrame_+this->seg()->nFrm()-1;
00281 
00282         // draw a cross at the current position of each segment
00283         if (ncut_Setting.drawCross == 1) {
00284           int k=-1;
00285           for (int j=-1; j < 2; j++,k++) { // draw cross
00286             segmentedImage->val(calculateElementNr(x+j,y,segmentedImage)) = 0;
00287             segmentedImage->val(calculateElementNr(x+j,y,segmentedImage)+1) = 0;
00288             segmentedImage->val(calculateElementNr(x+j,y,segmentedImage)+2) = 0;
00289 
00290             segmentedImage->val(calculateElementNr(x,y+k,segmentedImage)) = 0;
00291             segmentedImage->val(calculateElementNr(x,y+k,segmentedImage)+1) = 0;
00292             segmentedImage->val(calculateElementNr(x,y+k,segmentedImage)+2) = 0;
00293           }
00294         }
00295       }
00296     }
00297 
00298     // draw the rememberedPosition in Frame #1
00299     if (frm==1 && ncut_Setting.drawTrace==1) { 
00300 
00301       for (segment  = this->seg_->indices()->begin();
00302            segment != this->seg_->indices()->end(); segment++) {
00303 
00304         typename std::vector<int>::reverse_iterator rItrLocationY;
00305         typename std::vector<int>::reverse_iterator rItrLocationX;
00306         int count;
00307         for (rItrLocationY = rememberedPosY_[segment->first].rbegin(),
00308              rItrLocationX = rememberedPosX_[segment->first].rbegin(),
00309              count=0;
00310              rItrLocationY != rememberedPosY_[segment->first].rend() &&
00311              count < ncut_Setting.tracelength;
00312              rItrLocationY++, rItrLocationX++, count++) {
00313 
00314           segmentedImage->val(calculateElementNr(*rItrLocationX,
00315                                                  *rItrLocationY,
00316                                                  segmentedImage)  ) = 0;
00317           segmentedImage->val(calculateElementNr(*rItrLocationX,
00318                                                  *rItrLocationY,
00319                                                  segmentedImage)+1) = 0;
00320           segmentedImage->val(calculateElementNr(*rItrLocationX,
00321                                                  *rItrLocationY,
00322                                                  segmentedImage)+2) = 0;
00323 
00324         }
00325       }
00326     }
00327 
00328     //draw the rememberedPosition in Frame #1
00329     if (frm==1 && ncut_Setting.drawLine==1) {
00330 
00331       for (segment  = this->seg_->indices()->begin();
00332            segment != this->seg_->indices()->end(); segment++) {
00333 
00334         typename std::vector<int>::reverse_iterator rItrLocationY;
00335         typename std::vector<int>::reverse_iterator rItrLocationX;
00336         int count;
00337         for (rItrLocationY = rememberedPosY_[segment->first].rbegin(),
00338              rItrLocationX = rememberedPosX_[segment->first].rbegin(),
00339              count=0;
00340              rItrLocationY != rememberedPosY_[segment->first].rend() &&
00341              count < ncut_Setting.tracelength;
00342              count++) {
00343 
00344           int x1 = *rItrLocationX;
00345           int y2 = *rItrLocationY;
00346           rItrLocationX++;
00347           rItrLocationY++;
00348 
00349           if (rItrLocationX != rememberedPosX_[segment->first].rend()) {
00350             drawLine(x1,y2,*rItrLocationX,*rItrLocationY, segmentedImage);
00351           }
00352         }
00353       }
00354     }
00355 
00356     // save the visualization image in the visualization sequence
00357     seq.pushFrame(*segmentedImage);
00358   }
00359 #ifdef debugout
00360   timerEnd = clock();
00361   std::cout << "done visualisation(" << ((double)(timerEnd - timerStart))/CLOCKS_PER_SEC
00362     << "seconds)" << std::endl << std::flush;
00363 #endif
00364 
00365   // free dynamically allocated memory
00366   if (segmentedImage != NULL) {
00367     delete segmentedImage;
00368     segmentedImage = NULL;
00369   }
00370 }
00371 
00372 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00373 unsigned long PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::calculateElementNr(int x, int
00374 y, const PNGImage* image)
00375 {
00376   if (x<0 || y<0 || image==NULL) return 0;
00377   return image->nChl() * ((image->width() * y) + x);
00378 }
00379 
00380 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00381 int PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::drawLine(int x1, int y1, int x2, int y2,
00382 PNGImage *image)
00383 {
00384 //   std::cout << "drawLine: x1:" << x1 << " y1:" << y1 << " x2:" << x2 << "
00385 // y2:" << y2 << std::endl << std::flush; 
00386   if (x1 == x2 && y1 == y2) return 0;
00387   // bresenham algorithmus
00388 
00389   bool swap=false;
00390 
00391   if(abs(x1-x2)>abs(y1-y2)) {
00392     swap=(x1>x2);
00393   }
00394   else {
00395     swap=(y1>y2);
00396   }
00397 
00398   if(swap) {
00399     int i=x1;
00400     x1=x2;
00401     x2=i;
00402 
00403     i=y1;
00404     y1=y2;
00405     y2=i;
00406   }
00407 
00408   int dx=abs(x2-x1);
00409   int dy=abs(y2-y1);
00410 
00411   if(dx==0) {
00412     for(int y=y1; y<=y2; y++) {
00413 
00414       image->val(calculateElementNr(x1,y,image)) = 0;
00415       image->val(calculateElementNr(x1,y,image)+1) = 0;
00416       image->val(calculateElementNr(x1,y,image)+2) = 0;
00417 
00418     }
00419   }
00420   else if(dy==0) {
00421     for(int x=x1; x<=x2; x++) {
00422       image->val(calculateElementNr(x,y1,image)) = 0;
00423       image->val(calculateElementNr(x,y1,image)+1) = 0;
00424       image->val(calculateElementNr(x,y1,image)+2) = 0;
00425     }
00426   }
00427   else if(dx==dy) {
00428     int xi=(x1<x2 ? +1 : -1);
00429     int yi=(y1<y2 ? +1 : -1);
00430 
00431     for(int i=0,x=x1,y=y1; i<=dx; i++,x+=xi,y+=yi) {
00432       image->val(calculateElementNr(x,y,image)) = 0;
00433       image->val(calculateElementNr(x,y,image)+1) = 0;
00434       image->val(calculateElementNr(x,y,image)+2) = 0;
00435 
00436     }
00437   }
00438   else {
00439     bool horiz=(dx>dy);
00440 
00441     int p =(horiz ? 2*dy-dx : 2*dx-dy);
00442     int h1=(horiz ? 2*dy : 2*dx);
00443     int h2=(horiz ? 2*(dy-dx) : 2*(dx-dy));
00444 
00445     int dir=(horiz ? (y2>y1 ? 1 : -1) : (x2>x1 ? 1 : -1));
00446 
00447     int x=x1,y=y1;
00448 
00449     image->val(calculateElementNr(x,y,image)) = 0;
00450     image->val(calculateElementNr(x,y,image)+1) = 0;
00451     image->val(calculateElementNr(x,y,image)+2) = 0;
00452 
00453     while(horiz ? x<x2 : y<y2) {
00454       if(horiz) {
00455         x++;
00456       }
00457       else {
00458         y++;
00459       }
00460 
00461       if(p<0) {
00462         p+=h1;
00463       }
00464       else {
00465         p+=h2;
00466 
00467         if(horiz) {
00468           y+=dir;
00469         }
00470         else {
00471           x+=dir;
00472         }
00473       }
00474       image->val(calculateElementNr(x,y,image)) = 0;
00475       image->val(calculateElementNr(x,y,image)+1) = 0;
00476       image->val(calculateElementNr(x,y,image)+2) = 0;
00477 
00478     }
00479   }
00480   return 0;
00481 }
00482 
00483 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00484 void PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::
00485     mode_segmentedObjects(PNGImage* segmentedImage, int cmp, int pxl, int frm)
00486 {
00487   PNG_color_t myColor;
00488   MSK_ELM_TYPE segId = this->seg_->segMask(this->seg_->elmMask(frm,pxl));
00489 
00490   if (this->seg_->age(segId) < ncut_Setting.segment_delay)
00491     myColor = colors_[ colorMap_[ this->seg_->simSeg( segId ) ] ];
00492   else
00493     myColor = colors_[ colorMap_[ segId ] ];
00494 
00495   segmentedImage->val(cmp)   = myColor.red;
00496   segmentedImage->val(cmp+1) = myColor.green;
00497   segmentedImage->val(cmp+2) = myColor.blue;
00498 
00499 }
00500 
00501 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00502 void PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::
00503     mode_original(PNGImage* segmentedImage, int cmp, int frm)
00504 {
00505   segmentedImage->val(cmp)   = this->seg_->frameMask(frm,cmp);
00506   segmentedImage->val(cmp+1) = this->seg_->frameMask(frm,cmp+1);
00507   segmentedImage->val(cmp+2) = this->seg_->frameMask(frm,cmp+2);
00508 }
00509 
00510 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00511 PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::
00512     PNGVis(const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* _seg)
00513   : Vis<IMG_ELM_TYPE, MSK_ELM_TYPE, PNG_IMAGE_DATATYPE>(_seg),
00514     baseFrame_(-1),
00515     colors_(),
00516     colorMap_(),
00517     rememberedPosX_(),
00518     rememberedPosY_(),
00519     firstFrame_()
00520 {
00521   if (this->seg_ == NULL)
00522     throw ncutCritical("invalid segmentation (NULL)");
00523 
00524   PNG_color_t color;
00525 
00526   color.red   = 0;
00527   color.green = 0;
00528   color.blue  = 0;
00529   colors_.push_back(color);
00530 
00531   // alles + 1
00532   // 0
00533   color.red   = 255;
00534   color.green = 255;
00535   color.blue  = 255;
00536   colors_.push_back(color);
00537 
00538   // 1
00539   color.red   = 88;
00540   color.green = 88;
00541   color.blue  = 88;
00542   colors_.push_back(color);
00543   // 2
00544   color.red   = 128;
00545   color.green = 0;
00546   color.blue  = 128;
00547   colors_.push_back(color);
00548 
00549   // 3
00550   color.red   = 255;
00551   color.green = 168;
00552   color.blue  = 88;
00553   colors_.push_back(color);
00554   // 4
00555   color.red   = 220;
00556   color.green = 220;
00557   color.blue  = 220;
00558   colors_.push_back(color);
00559   // 5
00560   color.red   = 195;
00561   color.green = 195;
00562   color.blue  = 195;
00563   colors_.push_back(color);
00564   // 6
00565   color.red   = 160;
00566   color.green = 160;
00567   color.blue  = 160;
00568   colors_.push_back(color);
00569 
00570   // 7
00571   color.red   = 128;
00572   color.green = 128;
00573   color.blue  = 128;
00574   colors_.push_back(color);
00575   // 8
00576   color.red   = 128;
00577   color.green = 0;
00578   color.blue  = 0;
00579   colors_.push_back(color);
00580   // 9
00581   color.red   = 192;
00582   color.green = 0;
00583   color.blue  = 0;
00584   colors_.push_back(color);
00585   // 10
00586   color.red   = 0;
00587   color.green = 128;
00588   color.blue  = 0;
00589   colors_.push_back(color);
00590   // 11
00591   color.red   = 255;
00592   color.green = 0;
00593   color.blue  = 0;
00594   colors_.push_back(color);
00595   // 12
00596   color.red   = 255;
00597   color.green = 192;
00598   color.blue  = 192;
00599   colors_.push_back(color);
00600   // 13
00601   color.red   = 0;
00602   color.green = 64;
00603   color.blue  = 0;
00604   colors_.push_back(color);
00605   // 14
00606   color.red   = 0;
00607   color.green = 192;
00608   color.blue  = 0;
00609   colors_.push_back(color);
00610   // 15
00611   color.red   = 0;
00612   color.green = 255;
00613   color.blue  = 0;
00614   colors_.push_back(color);
00615 
00616   // 16
00617   color.red   = 192;
00618   color.green = 255;
00619   color.blue  = 192;
00620   colors_.push_back(color);
00621 
00622   color.red   = 0;
00623   color.green = 0;
00624   color.blue  = 128;
00625   colors_.push_back(color);
00626 
00627   color.red   = 0;
00628   color.green = 0;
00629   color.blue  = 192;
00630   colors_.push_back(color);
00631 
00632   color.red   = 0;
00633   color.green = 0;
00634   color.blue  = 255;
00635   colors_.push_back(color);
00636 
00637   color.red   = 192;
00638   color.green = 192;
00639   color.blue  = 255;
00640   colors_.push_back(color);
00641 
00642   color.red   = 64;
00643   color.green = 64;
00644   color.blue  = 0;
00645   colors_.push_back(color);
00646 
00647   color.red   = 128;
00648   color.green = 128;
00649   color.blue  = 0;
00650   colors_.push_back(color);
00651 
00652   color.red   = 192;
00653   color.green = 192;
00654   color.blue  = 0;
00655   colors_.push_back(color);
00656 
00657   color.red   = 255;
00658   color.green = 255;
00659   color.blue  = 0;
00660   colors_.push_back(color);
00661 
00662   color.red   = 255;
00663   color.green = 255;
00664   color.blue  = 192;
00665   colors_.push_back(color);
00666 
00667   color.red   = 0;
00668   color.green = 128;
00669   color.blue  = 128;
00670   colors_.push_back(color);
00671 
00672   color.red   = 0;
00673   color.green = 192;
00674   color.blue  = 192;
00675   colors_.push_back(color);
00676 
00677   color.red   = 192;
00678   color.green = 255;
00679   color.blue  = 255;
00680   colors_.push_back(color);
00681 
00682   color.red   = 192;
00683   color.green = 0;
00684   color.blue  = 192;
00685   colors_.push_back(color);
00686 
00687   color.red   = 255;
00688   color.green = 0;
00689   color.blue  = 255;
00690   colors_.push_back(color);
00691 
00692   color.red   = 255;
00693   color.green = 192;
00694   color.blue  = 255;
00695   colors_.push_back(color);
00696 
00697   color.red   = 192;
00698   color.green = 88;
00699   color.blue  = 0;
00700   colors_.push_back(color);
00701 
00702   color.red   = 255;
00703   color.green = 128;
00704   color.blue  = 0;
00705   colors_.push_back(color);
00706 
00707   color.red   = 255;
00708   color.green = 220;
00709   color.blue  = 168;
00710   colors_.push_back(color);
00711 }
00712 
00713 template <class IMG_ELM_TYPE, class MSK_ELM_TYPE>
00714 PNGVis<IMG_ELM_TYPE, MSK_ELM_TYPE>::~PNGVis()
00715 {
00716   return;
00717 }
00718 
00719 } // namespace ncut
00720 
00721 #endif // NCUT_VIS_H

Generated on Thu Jun 22 14:47:20 2006 for ncut.kdevelop by  doxygen 1.4.6