segmentImage2.C

Go to the documentation of this file.
00001 /*!@file VFAT/segmentImage2.C Basic image segmenter blob finder using color */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // 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: T. Nathan Mundhenk <mundhenk@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/VFAT/segmentImage2.C $
00035 // $Id: segmentImage2.C 14376 2011-01-11 02:44:34Z pez $
00036 //
00037 
00038 #include "VFAT/segmentImage2.H"
00039 
00040 #include "Util/Assert.H"
00041 #include <iostream>
00042 #include <vector>
00043 #include <cstdio>
00044 #include <cstdlib>
00045 
00046 
00047 
00048 /* find candidate pixels by just checking image pixels to see if they
00049    are within threshold of desired RGB values
00050    if so, set candidatePixels image pixel to true
00051 */
00052 void segmentImage2::SIfindCandidatesRGB()
00053 {
00054   PixRGB<float> pix;
00055 
00056   for(unsigned int x = 0; x < SI_masterVec.size(); x++)
00057     SI_masterVec[x] = -1;
00058 
00059   for(int x = SI_frameX1; x < SI_frameX2; x++)
00060   {
00061     for(int y = SI_frameY1; y < SI_frameY2; y++)
00062     {
00063       pix = SI_workImage.getVal(x,y);
00064       SI_candidatePixels.setVal(x,y,false);
00065 
00066       // first check if the values are within threshold
00067       if ((pix.red() < SI_redUT) &&
00068           (pix.green() < SI_greenUT) &&
00069           (pix.blue() < SI_blueUT) &&
00070           (pix.red() > SI_redLT) &&
00071           (pix.green() > SI_greenLT) &&
00072           (pix.blue() > SI_blueLT))
00073       {
00074           SI_candidatePixels.setVal(x,y,true);
00075 
00076       }
00077     }
00078   }
00079 }
00080 
00081 /* find candidate pixels by just checking image pixels to see if they
00082    are within threshold of desired HSV values
00083    if so, set candidatePixels image pixel to true
00084 */
00085 void segmentImage2::SIfindCandidatesHSV()
00086 {
00087   PixRGB<float> pix;
00088 
00089   for(unsigned int x = 0; x < SI_masterVec.size(); x++)
00090     SI_masterVec[x] = -1;
00091 
00092   bool modu = false;
00093   double HmoduL = SI_HLT;
00094   double HmoduU = SI_HUT;
00095   // modulus on the hue value, if lower bound is less than 0
00096   if(SI_HLT < 0)
00097   {
00098     modu = true;
00099     HmoduL = 360.0F + SI_HLT;
00100   }
00101   //else if used here because wrapping both upper and lower bounds will
00102   //cause undesirable behavior (pixels out of range for hue even though
00103   //whole range should be in range)
00104   // modulus on upper bound, if greater than 360
00105   else if(SI_HUT > 360)
00106   {
00107     modu = true;
00108     HmoduU = SI_HUT - 360.0F;
00109   }
00110 
00111   Image<PixRGB<float> >::iterator
00112     workImageIter = SI_workImage.beginw() + SI_frameX1 +
00113     (SI_frameY1*SI_workImage.getWidth());
00114   Image<bool>::iterator
00115     candidatePixelsIter = SI_candidatePixels.beginw() + SI_frameX1 +
00116     (SI_frameY1*SI_workImage.getWidth());
00117   Image<bool>::iterator
00118     preCandidatePixelsIter = SI_preCandidatePixels.beginw() + SI_frameX1 +
00119     (SI_frameY1*SI_workImage.getWidth());
00120 
00121   int jump = SI_frameX1 + (SI_workImage.getWidth()-SI_frameX2);
00122 
00123   for(int y = SI_frameY1; y < SI_frameY2; y++)
00124   {
00125     for(int x = SI_frameX1; x < SI_frameX2; x++)
00126     {
00127       float pixH,pixS,pixV;
00128       pix = (*workImageIter);
00129       PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00130       *candidatePixelsIter = false;
00131 
00132       //LINFO("%f,%f,%f,%f,%f,%f",pixH, SI_HUT, pixS, SI_SUT, pixV, SI_VUT);
00133       //LINFO("%f,%f,%f,%f,%f,%f",pixH, SI_HLT, pixS, SI_SLT, pixV, SI_VLT);
00134       // first check if the values are within threshold
00135       if ((pixS < SI_SUT) &&
00136           (pixV < SI_VUT) &&
00137           (pixS > SI_SLT) &&
00138           (pixV > SI_VLT))
00139       {
00140         //if((pixH < SI_HUT) && (pixH > SI_HLT))
00141         // changed to account for modulus properties in HSV for H
00142         if(((modu == false) && (pixH < SI_HUT) && (pixH > SI_HLT)) ||
00143            ((modu == true) && (!((pixH > HmoduU) && (pixH < HmoduL)))))
00144         {
00145          // LINFO("PASS: %f, %f, %f,%d,%d", pixH,pixS,pixV,x,y);
00146           if((*preCandidatePixelsIter) == true)
00147           {
00148             //LINFO("SET CANDIDATE: (%d,%d)",x,y);
00149             *candidatePixelsIter = true;
00150           }
00151           *preCandidatePixelsIter = true;
00152         }
00153         else
00154         {
00155           //LINFO("FAIL: %f, %f, %f,%d,%d", pixH,pixS,pixV,x,y);
00156           *preCandidatePixelsIter = false;
00157         }
00158       }
00159       ++workImageIter; ++candidatePixelsIter; ++preCandidatePixelsIter;
00160     }
00161     workImageIter = workImageIter + jump;
00162     candidatePixelsIter = candidatePixelsIter + jump;
00163     preCandidatePixelsIter = preCandidatePixelsIter + jump;
00164   }
00165 }
00166 
00167 /* find candidate pixels by just checking image pixels to see if they
00168    are within threshold of desired HSV values
00169    if so, set candidatePixels image pixel to true
00170 */
00171 
00172 void segmentImage2::SIfindCandidatesGREY()
00173 {
00174   float pix;
00175 
00176   for(unsigned int x = 0; x < SI_masterVec.size(); x++)
00177     SI_masterVec[x] = -1;
00178 
00179   for(int x = SI_frameX1; x < SI_frameX2; x++)
00180   {
00181     for(int y = SI_frameY1; y < SI_frameY2; y++)
00182     {
00183       pix = SI_workImageGREY.getVal(x,y);
00184       SI_candidatePixels.setVal(x,y,false);
00185 
00186       // first check if the values are within threshold
00187       if ((pix < SI_VUT) && (pix > SI_VLT))
00188       {
00189           SI_candidatePixels.setVal(x,y,true);
00190       }
00191     }
00192   }
00193 }
00194 
00195 /* if a pixel does not have an orthogonal neighbor then it is removed
00196    i.e. all pixels without 4 connectivity are removed as noise
00197 */
00198 
00199 void segmentImage2::SIremoveSingles()
00200 {
00201   for(int x = SI_frameX1; x < SI_frameX2; x++)
00202   {
00203     for(int y = SI_frameY1; y < SI_frameY2; y++)
00204     {
00205       if(SI_candidatePixels.getVal(x,y))
00206       {
00207         int kill = 0;
00208         int XLeft = x - 1;
00209         int XRight = x + 1;
00210         int YTop = y - 1;
00211         int YBottom = y + 1;
00212         if((XLeft >= 0) && (SI_candidatePixels.getVal(XLeft,y)))
00213           kill++;
00214         if((XRight < SI_candidatePixels.getWidth())
00215            && (SI_candidatePixels.getVal(XRight,y)))
00216           kill++;
00217         if((YTop >= 0) && (SI_candidatePixels.getVal(x,YTop)))
00218           kill++;
00219         if((YBottom < SI_candidatePixels.getHeight())
00220            && (SI_candidatePixels.getVal(x,YBottom)))
00221           kill++;
00222         if(kill < 2)
00223           SI_candidatePixels.setVal(x,y,false);
00224       }
00225     }
00226   }
00227 }
00228 
00229 /* scan pixels from top to bottom/left to right. Link all pixels in the
00230    same blob. Do this using recursive back tracking to make a blob linked
00231    as one object and not a collection of objects
00232 */
00233 
00234 void segmentImage2::SIdiscreteLinking()
00235 {
00236 
00237   bool trace = false;
00238   long pixID = 0;
00239   long lastNeighbor;
00240   SI_masters = 0;
00241   SI_mastersCount = 0;
00242   for(int x = SI_frameX1; x < SI_frameX2; x++)
00243   {
00244     trace = false;
00245     lastNeighbor = -2;
00246     for(int y = SI_frameY1; y < SI_frameY2; y++)
00247     {
00248       if(SI_candidatePixels.getVal(x,y))
00249       {
00250         if(!trace)
00251         {
00252           pixID++;
00253           trace = true;
00254           lastNeighbor = -2;
00255         }
00256         SI_blobID.setVal(x,y,pixID);
00257         if((x-1) > SI_frameX1)
00258         {
00259           if(SI_candidatePixels.getVal(x-1,y))
00260           {
00261             // relink blob pixels if needed
00262             long check = SI_blobID.getVal((x-1),y);
00263             if(check != lastNeighbor)
00264             {
00265               SIbackwardLink(pixID,check);
00266               lastNeighbor = check;
00267             }
00268           }
00269           else
00270           {
00271             lastNeighbor = -2;
00272           }
00273         }
00274         else
00275         {
00276           SIbackwardLink(pixID,pixID);
00277         }
00278       }
00279       else
00280       {
00281         trace = false;
00282         SI_blobID.setVal(x,y,0);
00283         lastNeighbor = -2;
00284       }
00285     }
00286   }
00287   //LINFO("Candidate Blobs scanned %d", pixID);
00288   //LINFO("Candidate pixels recognized %d",candi);
00289   SI_num = pixID;
00290 }
00291 
00292 /* relink pixels with new val. This allows pixels that have a new value
00293    to take on the old value of the blob. Slaves take on masters and
00294    masters can take on a slaves master.
00295 
00296 */
00297 
00298 void segmentImage2::SIbackwardLink(long slave, long master)
00299 {
00300   long *masterVecMaster = &SI_masterVec[master];
00301   long *masterVecSlave = &SI_masterVec[slave];
00302   // my master has no master
00303   if(*masterVecMaster == -1)
00304   {
00305     // I have no master
00306     if(*masterVecSlave == -1)
00307     {
00308       //LINFO("my master has no master/I have no master");
00309       *masterVecMaster = SI_masters;
00310       *masterVecSlave = SI_masters;
00311       SI_masters++;
00312       SI_mastersCount++;
00313     }
00314     // I already have a master
00315     else
00316     {
00317       //LINFO("my master has no master/I already have a master");
00318       *masterVecMaster = *masterVecSlave;
00319     }
00320   }
00321   // my master has a master
00322   else
00323   {
00324     // I have no master
00325     if(*masterVecSlave == -1)
00326     {
00327       //LINFO("my master has a master/I have no master");
00328       *masterVecSlave = *masterVecMaster;
00329     }
00330     // I already have a master
00331     else
00332     {
00333       //LINFO("my master has a master/I already have a master");
00334       SI_mastersCount--;
00335       for(int i = 0; i < slave; i++)
00336       {
00337         if(SI_masterVec[i] == *masterVecMaster)
00338         {
00339           //LINFO("SET %d to %d",masterVec[i],masterVec[slave]);
00340           SI_masterVec[i] = *masterVecSlave;
00341         }
00342       }
00343     }
00344   }
00345 }
00346 
00347 /* combine individual elements into a fully combined blob */
00348 
00349 void segmentImage2::SIcombine()
00350 {
00351   SI_totalBlobs = 0;
00352   for(int x = SI_frameX1; x < SI_frameX2; x++)
00353   {
00354     for(int y = SI_frameY1; y < SI_frameY2; y++)
00355     {
00356       if(SI_candidatePixels.getVal(x,y))
00357       {
00358         SI_blobID.setVal(x,y,SI_masterVec[SI_blobID.getVal(x,y)]);
00359       }
00360     }
00361   }
00362   for(int x = 0; x < SI_num; x++)
00363   {
00364     bool add = true;
00365     //LINFO("Master Vec %d is %d",x,masterVec[x]);
00366     for(int y = 0; y < SI_totalBlobs; y++)
00367     {
00368       if(SI_reOrderVec[y] == SI_masterVec[x])
00369         add = false;
00370     }
00371 
00372     if((add) && (SI_masterVec[x] != -1))
00373     {
00374       //LINFO("DOING %d",masterVec[x]);
00375       SI_reOrderVec[SI_totalBlobs] = SI_masterVec[x];
00376       SI_reverseOrderVec[SI_masterVec[x]] = SI_totalBlobs;
00377       SI_reset[SI_totalBlobs] = true;
00378       SI_totalBlobs++;
00379     }
00380   }
00381   //totalBlobs--;
00382 }
00383 
00384 void segmentImage2::SIdoSegment()
00385 {
00386   //LINFO("FINDING CANDIDATES");
00387   if(SI_doType == 1)
00388   {
00389     ASSERT(SI_set1); ASSERT(SI_set2); ASSERT(SI_set3); ASSERT(SI_set4);
00390     SIfindCandidatesRGB();
00391   }
00392   if(SI_doType == 2)
00393   {
00394     ASSERT(SI_set1); ASSERT(SI_set2); ASSERT(SI_set3); ASSERT(SI_set4);
00395     SIfindCandidatesHSV();
00396   }
00397   if(SI_doType == 3)
00398   {
00399     ASSERT(SI_set3); ASSERT(SI_set4);
00400     SIfindCandidatesGREY();
00401   }
00402   //LINFO("REMOVING SINGLES");
00403   SIremoveSingles();
00404   //LINFO("LINKING PIXELS");
00405   SIdiscreteLinking();
00406   //LINFO("RELABELING");
00407   SIcombine();
00408   //LINFO("DONE");
00409 }
00410 
00411 /*=============================================================*/
00412 /*        PUBLIC methods                                       */
00413 /*=============================================================*/
00414 
00415 segmentImage2::segmentImage2(int imageType)
00416 {
00417   SI_doType = imageType;
00418   SI_set1 = false; SI_set2 = false; SI_set3 = false; SI_set4 = false;
00419   LINFO("CREATED");
00420 }
00421 
00422 segmentImage2::segmentImage2()
00423 {
00424   SI_doType = HSV;
00425   SI_set1 = false; SI_set2 = false; SI_set3 = false; SI_set4 = false;
00426   LINFO("CREATED");
00427 }
00428 
00429 segmentImage2::~segmentImage2()
00430 {}
00431 
00432 /* set color segmentation values for color and
00433    threshold
00434 */
00435 
00436 void segmentImage2::SIsetRed(int val, int thresh = 1, int skew = 0)
00437 {
00438   ASSERT(SI_doType == 1);
00439   SI_red = val;
00440   if(skew <= 0)
00441   {
00442     SI_redLT = val - thresh + skew;
00443     SI_redUT = val + thresh;
00444   }
00445   else
00446   {
00447     SI_redLT = val - thresh;
00448     SI_redUT = val + thresh + skew;
00449   }
00450   SI_set1 = true;
00451 }
00452 
00453 void segmentImage2::SIsetGreen(int val, int thresh = 1, int skew = 0)
00454 {
00455   ASSERT(SI_doType == 1);
00456   SI_green = val;
00457   if(skew <= 0)
00458   {
00459     SI_greenLT = val - thresh + skew;
00460     SI_greenUT = val + thresh;
00461   }
00462   else
00463   {
00464     SI_greenLT = val - thresh;
00465     SI_greenUT = val + thresh + skew;
00466   }
00467   SI_set2 = true;
00468 }
00469 
00470 void segmentImage2::SIsetBlue(int val, int thresh = 1, int skew = 0)
00471 {
00472   ASSERT(SI_doType == 1);
00473   SI_blue = val;
00474   if(skew <= 0)
00475   {
00476     SI_blueLT = val - thresh + skew;
00477     SI_blueUT = val + thresh;
00478   }
00479   else
00480   {
00481     SI_blueLT = val - thresh;
00482     SI_blueUT = val + thresh + skew;
00483   }
00484   SI_set3 = true;
00485 }
00486 
00487 void segmentImage2::SIsetHue(double val, double thresh = 1, double skew = 0)
00488 {
00489   ASSERT(SI_doType == 2);
00490   SI_H = val;
00491   if(skew <= 0)
00492   {
00493     SI_HLT = val - thresh + skew;
00494     SI_HUT = val + thresh;
00495   }
00496   else
00497   {
00498     SI_HLT = val - thresh;
00499     SI_HUT = val + thresh + skew;
00500   }
00501   SI_set1 = true;
00502 }
00503 
00504 void segmentImage2::SIsetSat(double val, double thresh = 1, double skew = 0)
00505 {
00506   ASSERT(SI_doType == 2);
00507   SI_S = val;
00508   if(skew <= 0)
00509   {
00510     SI_SLT = val - thresh + skew;
00511     SI_SUT = val + thresh;
00512   }
00513   else
00514   {
00515     SI_SLT = val - thresh;
00516     SI_SUT = val + thresh + skew;
00517   }
00518   SI_set2 = true;
00519 }
00520 
00521 void segmentImage2::SIsetVal(double val, double thresh = 1, double skew = 0)
00522 {
00523   ASSERT((SI_doType == 2) || (SI_doType == 3));
00524   SI_V = val;
00525   if(skew <= 0)
00526   {
00527     SI_VLT = val - thresh + skew;
00528     SI_VUT = val + thresh;
00529   }
00530   else
00531   {
00532     SI_VLT = val - thresh;
00533     SI_VUT = val + thresh + skew;
00534   }
00535   SI_set3 = true;
00536 }
00537 
00538 /* set size of window frame to inspect in image */
00539 
00540 void segmentImage2::SIsetFrame(int x1, int y1, int x2, int y2,
00541                             int realX, int realY)
00542 {
00543   SI_frameX1 = x1;
00544   SI_frameX2 = x2;
00545   SI_frameY1 = y1;
00546   SI_frameY2 = y2;
00547   SI_masterVec.resize(((x2-x1)*(y2-y1)),-1);
00548   SI_reOrderVec.resize(((x2-x1)*(y2-y1)));
00549   SI_reverseOrderVec.resize(((x2-x1)*(y2-y1)));
00550   SI_centerX.resize(((x2-x1)*(y2-y1)));
00551   SI_centerY.resize(((x2-x1)*(y2-y1)));
00552   SI_Xsum.resize(((x2-x1)*(y2-y1)));
00553   SI_Ysum.resize(((x2-x1)*(y2-y1)));
00554   SI_mass.resize(((x2-x1)*(y2-y1)));
00555   SI_xmin.resize(((x2-x1)*(y2-y1)));
00556   SI_xmax.resize(((x2-x1)*(y2-y1)));
00557   SI_ymin.resize(((x2-x1)*(y2-y1)));
00558   SI_ymax.resize(((x2-x1)*(y2-y1)));
00559   SI_reset.resize(((x2-x1)*(y2-y1)));
00560   LINFO("SETTING WIDTH %d, HEIGHT %d",realX,realY);
00561   SI_blobID.resize(realX,realY,-1);
00562   SI_candidatePixels.resize(realX,realY,false);
00563   SI_preCandidatePixels.resize(realX,realY,false);
00564   SI_set4 = true;
00565 }
00566 
00567 void segmentImage2::SIsetHSVavg(long doAvg)
00568 {
00569   SI_Havg.resize(doAvg,0);
00570   SI_Savg.resize(doAvg,0);
00571   SI_Vavg.resize(doAvg,0);
00572   SI_Hstdd.resize(doAvg,0);
00573   SI_Sstdd.resize(doAvg,0);
00574   SI_Vstdd.resize(doAvg,0);
00575   SI_HSVN.resize(doAvg,0);
00576   SI_HSViter = doAvg;
00577   SI_HSVcount = 0;
00578 }
00579 
00580 /* do image segmentation by calling private memebers to
00581    operate on image.
00582    1. Low pass image
00583    2. Find candidate pixels
00584    3. Eleminate single isolated candidates
00585    4. Link pixels in each blob
00586    5. Clean up
00587 */
00588 
00589 void segmentImage2::SIsegment(Image<PixRGB<float> > &image)
00590 {
00591   double micros;
00592   struct timezone tz;
00593   struct timeval start, stop;
00594   tz.tz_minuteswest = 0;
00595   tz.tz_dsttime = 0;
00596   gettimeofday(&start, &tz);
00597 
00598   SI_workImage.resize(1,1);
00599   SI_workImage = lowPass5(image);
00600 
00601   SIdoSegment();
00602 
00603   gettimeofday(&stop,&tz);
00604   micros = stop.tv_usec - start.tv_usec;
00605         LINFO("%.1f Microseconds to segment\n", micros);
00606   //std::cout << micros << " Microseconds to segment\n";
00607 
00608 }
00609 
00610 void segmentImage2::SIsegment(Image<float> &image)
00611 {
00612   struct timezone tz;
00613   struct timeval start, stop;
00614   tz.tz_minuteswest = 0;
00615   tz.tz_dsttime = 0;
00616   gettimeofday(&start, &tz);
00617 
00618   SI_workImageGREY.resize(1,1);
00619   SI_workImageGREY = lowPass5(image);
00620 
00621   SIdoSegment();
00622 
00623   gettimeofday(&stop,&tz);
00624         //LINFO("%.1f Microseconds to segment\n", micros);
00625 
00626 }
00627 
00628 /* This method when called will take all remaning blobs from post
00629    processing and create a mother blob
00630 */
00631 
00632 Image<long> segmentImage2::SIcreateMother(Image<long> &img)
00633 {
00634   Image<long> mother;
00635   mother.resize(img.getWidth(),img.getHeight(),ZEROS);
00636   for(int x = SI_frameX1; x < SI_frameX2; x++)
00637   {
00638     for(int y = SI_frameY1; y < SI_frameY2; y++)
00639     {
00640       if(img.getVal(x,y) != 0)
00641         mother.setVal(x,y,1);
00642       else
00643         mother.setVal(x,y,0);
00644     }
00645   }
00646   return mother;
00647 }
00648 
00649 /* return blob map
00650  */
00651 
00652 Image<long> segmentImage2::SIreturnBlobs()
00653 {
00654   return SI_blobID;
00655 }
00656 
00657 Image<bool> segmentImage2::SIreturnCandidates()
00658 {
00659   return SI_candidatePixels;
00660 }
00661 
00662 Image<float> segmentImage2::SIreturnNormalizedCandidates()
00663 {
00664   Image<float> NC;
00665   NC.resize(SI_candidatePixels.getWidth(),SI_candidatePixels.getHeight());
00666   for(int x = 0; x < SI_candidatePixels.getWidth(); x++)
00667   {
00668     for(int y = 0; y < SI_candidatePixels.getHeight(); y++)
00669     {
00670       if(SI_candidatePixels.getVal(x,y))
00671         NC.setVal(x,y,255.0F);
00672       else
00673         NC.setVal(x,y,0.0F);
00674     }
00675   }
00676   return NC;
00677 }
00678 
00679 Image<PixRGB<float> > segmentImage2::SIreturnWorkImage()
00680 {
00681   ASSERT((SI_doType == 1) || (SI_doType == 2));
00682   return SI_workImage;
00683 }
00684 
00685 Image<float> segmentImage2::SIreturnWorkImageGREY()
00686 {
00687   ASSERT(SI_doType == 3);
00688   return SI_workImageGREY;
00689 }
00690 
00691 
00692 int segmentImage2::SInumberBlobs()
00693 {
00694   return SI_totalBlobs;
00695 }
00696 
00697 std::vector<long> segmentImage2::SIgetBlobMap()
00698 {
00699   return SI_reOrderVec;
00700 }
00701 
00702 void segmentImage2::SIcalcMassCenter()
00703 {
00704   for(int x = SI_frameX1; x < SI_frameX2; x++)
00705   {
00706     for(int y = SI_frameY1; y < SI_frameY2; y++)
00707     {
00708       if((SI_candidatePixels.getVal(x,y)) && (SI_blobID.getVal(x,y) != -1))
00709       {
00710         //std::cerr << "foo " << reverseOrderVec[blobID.getVal(x,y)] << "\n";
00711         long *indexBlob = &SI_reverseOrderVec[SI_blobID.getVal(x,y)];
00712         if(SI_reset[*indexBlob])
00713         {
00714           SI_reset[*indexBlob] = false;
00715           SI_Xsum[*indexBlob] = x;
00716           SI_Ysum[*indexBlob] = y;
00717           SI_mass[*indexBlob] = 1;
00718           SI_xmin[*indexBlob] = x;
00719           SI_ymin[*indexBlob] = y;
00720           SI_xmax[*indexBlob] = x;
00721           SI_ymax[*indexBlob] = y;
00722         }
00723         else
00724         {
00725           SI_Xsum[*indexBlob] += x;
00726           SI_Ysum[*indexBlob] += y;
00727           SI_mass[*indexBlob]++;
00728           if(x <= SI_xmin[*indexBlob])
00729             SI_xmin[*indexBlob] = x;
00730           if(x >= SI_xmax[*indexBlob])
00731             SI_xmax[*indexBlob] = x;
00732           if(y <= SI_ymin[*indexBlob])
00733             SI_ymin[*indexBlob] = y;
00734           if(y >= SI_ymax[*indexBlob])
00735             SI_ymax[*indexBlob] = y;
00736         }
00737       }
00738     }
00739   }
00740 
00741   for(int x = 0; x < SI_totalBlobs; x++)
00742   {
00743     //std::cerr << "MASS " << mass[x] << "\n";
00744     if(SI_mass[x] > 0)
00745     {
00746       SI_centerX[x] = SI_Xsum[x]/SI_mass[x];
00747       SI_centerY[x] = SI_Ysum[x]/SI_mass[x];
00748     }
00749   }
00750 }
00751 
00752 float segmentImage2::SIgetCenterX(long blob)
00753 {
00754   return SI_centerX[blob];
00755 }
00756 
00757 float segmentImage2::SIgetCenterY(long blob)
00758 {
00759   return SI_centerY[blob];
00760 }
00761 
00762 long segmentImage2::SIgetMass(long blob)
00763 {
00764   return SI_mass[blob];
00765 }
00766 
00767 int segmentImage2::SIgetXmin(long blob)
00768 {
00769   return SI_xmin[blob];
00770 }
00771 
00772 //! get X max for a blob
00773 
00774 int segmentImage2::SIgetXmax(long blob)
00775 {
00776   return SI_xmax[blob];
00777 }
00778 
00779 //! get Y min for a blob
00780 
00781 int segmentImage2::SIgetYmin(long blob)
00782 {
00783   return SI_ymin[blob];
00784 }
00785 
00786 //! get Y max for a blob
00787 
00788 int segmentImage2::SIgetYmax(long blob)
00789 {
00790   return SI_ymax[blob];
00791 }
00792 
00793  //! get the working image size in X
00794 int segmentImage2::SIgetImageSizeX()
00795 {
00796   return SI_candidatePixels.getWidth();
00797 }
00798 //! get the working image size in Y
00799 int segmentImage2::SIgetImageSizeY()
00800 {
00801   return SI_candidatePixels.getHeight();
00802 }
00803 
00804 void segmentImage2::SIgetHSVvalue(long blob, float *H, float *S, float *V,
00805                    float *Hstd, float *Sstd, float *Vstd)
00806 {
00807   float totH = 0.0F, totS = 0.0F, totV = 0.0F;
00808   float ssH = 0.0F, ssS = 0.0F, ssV = 0.0F;
00809   PixRGB<float> pix;
00810   for(int x = SI_frameX1; x < SI_frameX2; x++)
00811   {
00812     for(int y = SI_frameY1; y < SI_frameY2; y++)
00813     {
00814       if((SI_candidatePixels.getVal(x,y)) && (SI_blobID.getVal(x,y) != -1))
00815       {
00816         if(SI_reverseOrderVec[SI_blobID.getVal(x,y)] == blob)
00817         {
00818           float pixH,pixS,pixV;
00819           pix = SI_workImage.getVal(x,y);
00820           PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00821           totH +=pixH; totS += pixS; totV += pixV;
00822           ssH += (pow(pixH,2))/SI_mass[blob];
00823           ssS += (pow(pixS,2))/SI_mass[blob];
00824           ssV += (pow(pixV,2))/SI_mass[blob];
00825         }
00826       }
00827     }
00828   }
00829   if(SI_mass[blob] > 0)
00830   {
00831     *H = totH/SI_mass[blob];
00832     *S = totS/SI_mass[blob];
00833     *V = totV/SI_mass[blob];
00834     *Hstd = sqrt(ssH - pow(*H,2));
00835     *Sstd = sqrt(ssS - pow(*S,2));
00836     *Vstd = sqrt(ssV - pow(*V,2));
00837   }
00838 }
00839 
00840 void segmentImage2::SIgetHSVvalueMean(long blob, float *H, float *S, float *V,
00841                         float *Hstd, float *Sstd, float *Vstd)
00842 {
00843   double massSum = 0;
00844   if(SI_HSVcount == SI_HSViter)
00845     SI_HSVcount = 0;
00846 
00847   SIgetHSVvalue(blob, &SI_Havg[SI_HSVcount], &SI_Savg[SI_HSVcount],
00848               &SI_Vavg[SI_HSVcount], &SI_Hstdd[SI_HSVcount],
00849               &SI_Sstdd[SI_HSVcount], &SI_Vstdd[SI_HSVcount]);
00850 
00851   SI_HSVN[SI_HSVcount] = SI_mass[blob];
00852   SI_HSVcount++;
00853   for(int i = 0; i < SI_HSViter; i++)
00854   {
00855     massSum += SI_HSVN[i];
00856     *H += SI_Havg[i]*SI_HSVN[i];
00857     *S += SI_Savg[i]*SI_HSVN[i];
00858     *V += SI_Vavg[i]*SI_HSVN[i];
00859     *Hstd += SI_Hstdd[i]*SI_HSVN[i];
00860     *Sstd += SI_Sstdd[i]*SI_HSVN[i];
00861     *Vstd += SI_Vstdd[i]*SI_HSVN[i];
00862   }
00863   if(massSum > 0)
00864   {
00865     *H = *H/massSum;
00866     *S = *S/massSum;
00867     *V = *V/massSum;
00868     *Hstd = *Hstd/massSum;
00869     *Sstd = *Sstd/massSum;
00870     *Vstd = *Vstd/massSum;
00871   }
00872 }
00873 
00874 // ######################################################################
00875 /* So things look consistent in everyone's emacs... */
00876 /* Local Variables: */
00877 /* indent-tabs-mode: nil */
00878 /* End: */
Generated on Sun May 8 08:42:35 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3