Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

RegionGenerator.cc

Go to the documentation of this file.
00001 #include "RegionGenerator.h"
00002 #include "Events/EventRouter.h"
00003 #include "Wireless/Wireless.h"
00004 #include "Shared/Profiler.h"
00005 #include "SegmentedColorGenerator.h"
00006 
00007 #include "Vision/RLEGenerator.h"
00008 
00009 #include "Shared/debuget.h"
00010 
00011 RegionGenerator::RegionGenerator(unsigned int mysid, RLEGenerator* rleg, EventBase::EventTypeID_t tid)
00012   : FilterBankGenerator("RegionGenerator","RegionGenerator",EventBase::visRegionEGID,mysid,rleg,tid), srcNumColors(0), srcColors(NULL), regions(NULL)
00013 {
00014   if(rleg!=NULL) {
00015     numLayers=numChannels=0; //this is to force setNumImages to override settings provided by FilterBankGenerator
00016     setNumImages(rleg->getNumLayers(),rleg->getNumChannels());
00017     if(const SegmentedColorGenerator* seg=dynamic_cast<const SegmentedColorGenerator*>(rleg->getSourceGenerator())) {
00018       srcNumColors=seg->getNumColors();
00019       srcColors=seg->getColors();
00020     } else {
00021       serr->printf("WARNING: Region generator expects it's source's source to be a SegmentedColorGenerator so that it can access color table information.\n");
00022     }
00023   }
00024 }
00025 
00026 void
00027 RegionGenerator::freeCaches() {
00028   FilterBankGenerator::freeCaches();
00029   for(unsigned int l=0; l<numLayers; l++)
00030     for(unsigned int c=0; c<numChannels; c++) {
00031       delete [] regions[l][c];
00032       regions[l][c]=NULL;
00033     }
00034 }
00035 
00036 void
00037 RegionGenerator::processEvent(const EventBase& event) {
00038   FilterBankGenerator::processEvent(event);
00039   if(event.getGeneratorID()==getListenGeneratorID() && event.getSourceID()==getListenSourceID()) {
00040     const RLEGenerator * rle=dynamic_cast<const RLEGenerator*>(src);
00041     if(NULL==rle) {
00042       serr->printf("RegionGenerator's event %s is not from RLEGenerator\n",event.getName().c_str());
00043       return;
00044     }
00045     const SegmentedColorFilterBankEvent * segev=dynamic_cast<const SegmentedColorFilterBankEvent*>(&event);
00046     if(NULL==segev) {
00047       serr->printf("RegionGenerator's event %s is not SegmentedColorFilterBankEvent\n",event.getName().c_str());
00048       return;
00049     }
00050     if(srcNumColors!=segev->getNumColors())
00051       freeCaches();
00052     srcNumColors=segev->getNumColors();
00053     srcColors=segev->getColors();
00054     SegmentedColorFilterBankEvent fbkev(this,getGeneratorID(),getSourceID(),EventBase::activateETID,*segev);
00055     erouter->postEvent(fbkev);
00056     fbkev.setTypeID(EventBase::statusETID);
00057     erouter->postEvent(fbkev);
00058     fbkev.setTypeID(EventBase::deactivateETID);
00059     erouter->postEvent(fbkev);
00060   }
00061 }
00062 
00063 unsigned int
00064 RegionGenerator::getBinSize() const {
00065   unsigned int used=FilterBankGenerator::getBinSize();
00066   used+=strlen("RegionImage")+LoadSave::stringpad;
00067   used+=sizeof(unsigned int); //srcNumColors
00068   used+=sizeof(unsigned int)*srcNumColors; //stats[i].num (for each color i)
00069   unsigned int xmit_bytes_per_run=5*sizeof(int)+2*sizeof(float)+2*sizeof(int);
00070   if(imageValids[selectedSaveLayer][selectedSaveChannel]) {
00071     unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00072     region_stats * stats=reinterpret_cast<region_stats*>(img);
00073     if(stats==NULL)
00074       return 0;
00075     for(unsigned int i=0; i<srcNumColors; i++)
00076       used+=xmit_bytes_per_run*stats[i].num;
00077   } else {
00078     used+=xmit_bytes_per_run*MAX_REGIONS;
00079   }
00080   used+=sizeof(unsigned int)*srcNumColors; //stats[i].min_area (for each color i)
00081   used+=sizeof(unsigned int)*srcNumColors; //stats[i].total_area (for each color i)
00082   used+=sizeof(float)*srcNumColors; //stats[i].merge_threshold (for each color i)
00083   return used;
00084 }
00085 
00086 unsigned int
00087 RegionGenerator::loadBuffer(const char buf[], unsigned int len) {
00088   unsigned int origlen=len;
00089   if(!checkInc(FilterBankGenerator::loadBuffer(buf,len),buf,len)) return 0;
00090   std::string tmp;
00091   if(!decodeInc(tmp,buf,len)) return 0;
00092   if(tmp!="RegionImage") {
00093     serr->printf("Unhandled image type for RegionGenerator: %s",tmp.c_str());
00094     return 0;
00095   } else {
00096     unsigned int tmpNumClr=0;
00097     if(!decodeInc(tmpNumClr,buf,len)) return 0;
00098     if(tmpNumClr!=srcNumColors)
00099       freeCaches();
00100     srcNumColors=tmpNumClr;
00101     if(images[selectedSaveLayer][selectedSaveChannel]==NULL)
00102       images[selectedSaveLayer][selectedSaveChannel]=createImageCache(selectedSaveLayer,selectedSaveChannel);
00103     region_stats * stats=reinterpret_cast<region_stats*>(images[selectedSaveLayer][selectedSaveChannel]);
00104     if(stats==NULL)
00105       return 0;
00106     for(unsigned int i=0; i<srcNumColors; i++) {
00107       unsigned int tmpNumReg=0;
00108       if(!decodeInc(tmpNumReg,buf,len)) return 0;
00109       if(MAX_REGIONS<=tmpNumReg)
00110         return 0;
00111       for(unsigned int j=0; j<tmpNumReg; j++) {
00112         region * curreg=&regions[selectedSaveLayer][selectedSaveChannel][j];
00113         if(!decodeInc(curreg->color,buf,len)) return 0;
00114         if(!decodeInc(curreg->x1,buf,len)) return 0;
00115         if(!decodeInc(curreg->y1,buf,len)) return 0;
00116         if(!decodeInc(curreg->x2,buf,len)) return 0;
00117         if(!decodeInc(curreg->y2,buf,len)) return 0;
00118         if(!decodeInc(curreg->cen_x,buf,len)) return 0;
00119         if(!decodeInc(curreg->cen_y,buf,len)) return 0;
00120         if(!decodeInc(curreg->area,buf,len)) return 0;
00121         if(!decodeInc(curreg->run_start,buf,len)) return 0;
00122         if(j==tmpNumReg-1)
00123           curreg->next=NULL;
00124         else
00125           curreg->next=&regions[selectedSaveLayer][selectedSaveChannel][j+1];
00126       }
00127       //we're only going to save the region part (not the color info)
00128       if(!decodeInc(stats[i].min_area,buf,len)) return 0;
00129       if(!decodeInc(stats[i].total_area,buf,len)) return 0;
00130       if(!decodeInc(stats[i].merge_threshold,buf,len)) return 0;
00131       stats[i].list=regions[selectedSaveLayer][selectedSaveChannel];
00132       stats[i].num=tmpNumReg;
00133     }
00134     imageValids[selectedSaveLayer][selectedSaveChannel]=true;
00135     return origlen-len; 
00136   }
00137 }
00138 
00139 unsigned int
00140 RegionGenerator::saveBuffer(char buf[], unsigned int len) const {
00141   unsigned int origlen=len;
00142   if(!checkInc(FilterBankGenerator::saveBuffer(buf,len),buf,len)) return 0;
00143   if(!encodeInc("RegionImage",buf,len)) return 0;
00144   
00145   if(images[selectedSaveLayer][selectedSaveChannel]==NULL) {
00146     serr->printf("RegionGenerator::saveBuffer() failed because selected image is NULL -- call selectSaveImage first to make sure it's up to date\n");
00147     return 0;
00148   }
00149   if(!imageValids[selectedSaveLayer][selectedSaveChannel]) {
00150     serr->printf("RegionGenerator::saveBuffer() failed because selected image is invalid -- call selectSaveImage first to make sure it's up to date\n");
00151     return 0;
00152   }
00153   unsigned char* img=images[selectedSaveLayer][selectedSaveChannel];
00154   region_stats * stats=reinterpret_cast<region_stats*>(img);
00155   if(stats==NULL)
00156     return 0;
00157   if(!encodeInc(srcNumColors,buf,len)) return 0;
00158   for(unsigned int i=0; i<srcNumColors; i++) {
00159     if(!encodeInc(stats[i].num,buf,len)) return 0;
00160     region * curreg=stats[i].list;
00161     for(int j=0; j<stats[i].num; j++) {
00162       if(!encodeInc(curreg->color,buf,len)) return 0;
00163       if(!encodeInc(curreg->x1,buf,len)) return 0;
00164       if(!encodeInc(curreg->y1,buf,len)) return 0;
00165       if(!encodeInc(curreg->x2,buf,len)) return 0;
00166       if(!encodeInc(curreg->y2,buf,len)) return 0;
00167       if(!encodeInc(curreg->cen_x,buf,len)) return 0;
00168       if(!encodeInc(curreg->cen_y,buf,len)) return 0;
00169       if(!encodeInc(curreg->area,buf,len)) return 0;
00170       if(!encodeInc(curreg->run_start,buf,len)) return 0;
00171       curreg=curreg->next;
00172     }
00173     //we're only going to save the region part (not the color info)
00174     if(!encodeInc(stats[i].min_area,buf,len)) return 0;
00175     if(!encodeInc(stats[i].total_area,buf,len)) return 0;
00176     if(!encodeInc(stats[i].merge_threshold,buf,len)) return 0;
00177   }
00178   return origlen-len;
00179 }
00180 
00181 void
00182 RegionGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
00183   if(nLayers==numLayers && nChannels==numChannels)
00184     return;
00185   FilterBankGenerator::setNumImages(nLayers,nChannels);
00186   regions = new region**[numLayers];
00187   for(unsigned int i=0; i<numLayers; i++) {
00188     regions[i] = new region*[numChannels];
00189     for(unsigned int j=0; j<numChannels; j++)
00190       regions[i][j]=NULL;
00191   }
00192 }
00193 
00194 unsigned char *
00195 RegionGenerator::createImageCache(unsigned int layer, unsigned int chan) const {
00196   //this is where we'll store the linked list of regions for this image
00197   regions[layer][chan]=new region[MAX_REGIONS];
00198 
00199   //this is where we store the head of each list as well as some general stats of each image
00200   //this is what will be returned as getImage()
00201   region_stats * stats=new region_stats[srcNumColors];
00202   
00203   //initialize the region parameters (held in color definition...)
00204   memcpy(stats,srcColors,srcNumColors*sizeof(region_stats));
00205   
00206   return reinterpret_cast<unsigned char*>(stats);
00207 }
00208 
00209 void
00210 RegionGenerator::calcImage(unsigned int layer, unsigned int chan) {
00211   PROFSECTION("RegionGenerator::calcImage(...)",*mainProfiler);
00212   
00213   //some shorthand to make the rest of the code more readable
00214   RLEGenerator& srcRLE=dynamic_cast<RLEGenerator&>(*src); //source generator
00215   RLEGenerator::run * rmap=reinterpret_cast<RLEGenerator::run*>(srcRLE.getImage(layer,chan)); //the RLE encoded image from source
00216   region_stats * stats=reinterpret_cast<region_stats*>(images[layer][chan]); //our top level region stats array (which is what users get from getImage())
00217 
00218   //do the actual calculations
00219   CMVision::ConnectComponents(rmap,srcRLE.getNumRuns(layer,chan));
00220   unsigned int numReg = CMVision::ExtractRegions(regions[layer][chan],MAX_REGIONS,rmap,srcRLE.getNumRuns(layer,chan));
00221   unsigned int maxArea = CMVision::SeparateRegions(stats,srcNumColors,regions[layer][chan],numReg);
00222   CMVision::SortRegions(stats,srcNumColors,maxArea);
00223   CMVision::MergeRegions(stats,(int)srcNumColors,rmap); //yes that (int) is necessary or compiler complains of ambiguous function call
00224   CMVision::CalcTotalArea(stats,srcNumColors);
00225 
00226   //and set the flag so we don't recompute if getImage() is called again before the next frame
00227   imageValids[layer][chan]=true;
00228 }
00229 
00230 void
00231 RegionGenerator::destruct() {
00232   FilterBankGenerator::destruct();
00233   for(unsigned int i=0; i<numLayers; i++)
00234     delete [] regions[i];
00235   delete [] regions;
00236   regions=NULL;
00237 }
00238 
00239 /*! @file
00240  * @brief Implements RegionGenerator, which connects regions of CMVision format runs in RLEGenerator
00241  * @author alokl (Creator)
00242  * @author ejt (reorganized)
00243  *
00244  * $Author: ejt $
00245  * $Name: tekkotsu-4_0 $
00246  * $Revision: 1.16 $
00247  * $State: Exp $
00248  * $Date: 2006/09/11 23:05:23 $
00249  */
00250 

Tekkotsu v4.0
Generated Thu Nov 22 00:54:55 2007 by Doxygen 1.5.4