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
00048
00049
00053 virtual ~Vis();
00054
00055 protected:
00056
00057 const Segmentation<IMG_ELM_TYPE, MSK_ELM_TYPE>* seg_;
00060
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
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
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
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
00197 PNGImage *segmentedImage = new
00198 PNGImage(this->seg_->width(),this->seg_->height(),this->seg_->nChl());
00199
00200
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
00212 eraseItr = segColor++;
00213 colorMap_.erase(eraseItr);
00214 }
00215 else {
00216
00217 freeColors.remove(segColor->second);
00218 segColor++;
00219 }
00220 }
00221
00222
00223 typename std::map<MSK_ELM_TYPE, unsigned int>::const_iterator segment;
00224
00225
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
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
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
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
00283 if (ncut_Setting.drawCross == 1) {
00284 int k=-1;
00285 for (int j=-1; j < 2; j++,k++) {
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
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
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
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
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
00385
00386 if (x1 == x2 && y1 == y2) return 0;
00387
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
00532
00533 color.red = 255;
00534 color.green = 255;
00535 color.blue = 255;
00536 colors_.push_back(color);
00537
00538
00539 color.red = 88;
00540 color.green = 88;
00541 color.blue = 88;
00542 colors_.push_back(color);
00543
00544 color.red = 128;
00545 color.green = 0;
00546 color.blue = 128;
00547 colors_.push_back(color);
00548
00549
00550 color.red = 255;
00551 color.green = 168;
00552 color.blue = 88;
00553 colors_.push_back(color);
00554
00555 color.red = 220;
00556 color.green = 220;
00557 color.blue = 220;
00558 colors_.push_back(color);
00559
00560 color.red = 195;
00561 color.green = 195;
00562 color.blue = 195;
00563 colors_.push_back(color);
00564
00565 color.red = 160;
00566 color.green = 160;
00567 color.blue = 160;
00568 colors_.push_back(color);
00569
00570
00571 color.red = 128;
00572 color.green = 128;
00573 color.blue = 128;
00574 colors_.push_back(color);
00575
00576 color.red = 128;
00577 color.green = 0;
00578 color.blue = 0;
00579 colors_.push_back(color);
00580
00581 color.red = 192;
00582 color.green = 0;
00583 color.blue = 0;
00584 colors_.push_back(color);
00585
00586 color.red = 0;
00587 color.green = 128;
00588 color.blue = 0;
00589 colors_.push_back(color);
00590
00591 color.red = 255;
00592 color.green = 0;
00593 color.blue = 0;
00594 colors_.push_back(color);
00595
00596 color.red = 255;
00597 color.green = 192;
00598 color.blue = 192;
00599 colors_.push_back(color);
00600
00601 color.red = 0;
00602 color.green = 64;
00603 color.blue = 0;
00604 colors_.push_back(color);
00605
00606 color.red = 0;
00607 color.green = 192;
00608 color.blue = 0;
00609 colors_.push_back(color);
00610
00611 color.red = 0;
00612 color.green = 255;
00613 color.blue = 0;
00614 colors_.push_back(color);
00615
00616
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 }
00720
00721 #endif // NCUT_VIS_H