segmentImage.C

Go to the documentation of this file.
00001 /*!@file VFAT/segmentImage.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/segmentImage.C $
00035 // $Id: segmentImage.C 14376 2011-01-11 02:44:34Z pez $
00036 //
00037 
00038 #include "VFAT/segmentImage.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 segmentImage::findCandidatesRGB()
00053 {
00054   PixRGB<float> pix;
00055 
00056   for(unsigned int x = 0; x < masterVec.size(); x++)
00057     masterVec[x] = -1;
00058 
00059   for(int x = frameX1; x < frameX2; x++)
00060   {
00061     for(int y = frameY1; y < frameY2; y++)
00062     {
00063       pix = workImage.getVal(x,y);
00064       candidatePixels.setVal(x,y,false);
00065 
00066       // first check if the values are within threshold
00067       if ((pix.red() < redUT) &&
00068           (pix.green() < greenUT) &&
00069           (pix.blue() < blueUT) &&
00070           (pix.red() > redLT) &&
00071           (pix.green() > greenLT) &&
00072           (pix.blue() > blueLT))
00073       {
00074           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 segmentImage::findCandidatesHSV()
00086 {
00087   PixRGB<float> pix;
00088 
00089   for(unsigned int x = 0; x < masterVec.size(); x++)
00090     masterVec[x] = -1;
00091 
00092   for(int x = frameX1; x < frameX2; x++)
00093   {
00094     for(int y = frameY1; y < frameY2; y++)
00095     {
00096       float pixH,pixS,pixV;
00097       pix = workImage.getVal(x,y);
00098       PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00099       candidatePixels.setVal(x,y,false);
00100 
00101       //LINFO("%f,%f,%f,%f,%f,%f",pixH, HUT, pixS, SUT, pixV, VUT);
00102       //LINFO("%f,%f,%f,%f,%f,%f",pixH, HLT, pixS, SLT, pixV, VLT);
00103       // first check if the values are within threshold
00104       if ((pixS < SUT) &&
00105           (pixV < VUT) &&
00106           (pixS > SLT) &&
00107           (pixV > VLT))
00108       {
00109         // changed to account for modulus properties in HSV for H
00110         if((pixH < HUT) && (pixH > HLT))
00111           //if(((modu == false) && (pixH < HUT) && (pixH > HLT)) ||
00112           // ((modu == true) && (!((pixH > HUT) && (pixH < Hmodu)))))
00113         {
00114           if(preCandidatePixels.getVal(x,y) == true)
00115           {
00116             //LINFO("SET CANDIDATE");
00117             candidatePixels.setVal(x,y,true);
00118           }
00119           preCandidatePixels.setVal(x,y,true);
00120         }
00121         else
00122         {
00123           preCandidatePixels.setVal(x,y,false);
00124         }
00125       }
00126     }
00127   }
00128 }
00129 
00130 /* find candidate pixels by just checking image pixels to see if they
00131    are within threshold of desired HSV values
00132    if so, set candidatePixels image pixel to true
00133 */
00134 
00135 void segmentImage::findCandidatesGREY()
00136 {
00137   float pix;
00138 
00139   for(unsigned int x = 0; x < masterVec.size(); x++)
00140     masterVec[x] = -1;
00141 
00142   for(int x = frameX1; x < frameX2; x++)
00143   {
00144     for(int y = frameY1; y < frameY2; y++)
00145     {
00146       pix = workImageGREY.getVal(x,y);
00147       candidatePixels.setVal(x,y,false);
00148 
00149       // first check if the values are within threshold
00150       if ((pix < VUT) && (pix > VLT))
00151       {
00152           candidatePixels.setVal(x,y,true);
00153       }
00154     }
00155   }
00156 }
00157 
00158 /* if a pixel does not have an orthogonal neighbor then it is removed
00159    i.e. all pixels without 4 connectivity are removed as noise
00160 */
00161 
00162 void segmentImage::removeSingles()
00163 {
00164   for(int x = frameX1; x < frameX2; x++)
00165   {
00166     for(int y = frameY1; y < frameY2; y++)
00167     {
00168       if(candidatePixels.getVal(x,y))
00169       {
00170         int kill = 0;
00171         int XLeft = x - 1;
00172         int XRight = x + 1;
00173         int YTop = y - 1;
00174         int YBottom = y + 1;
00175         if((XLeft >= 0) && (candidatePixels.getVal(XLeft,y)))
00176           kill++;
00177         if((XRight < candidatePixels.getWidth())
00178            && (candidatePixels.getVal(XRight,y)))
00179           kill++;
00180         if((YTop >= 0) && (candidatePixels.getVal(x,YTop)))
00181           kill++;
00182         if((YBottom < candidatePixels.getHeight())
00183            && (candidatePixels.getVal(x,YBottom)))
00184           kill++;
00185         if(kill < 2)
00186           candidatePixels.setVal(x,y,false);
00187       }
00188     }
00189   }
00190 }
00191 
00192 /* scan pixels from top to bottom/left to right. Link all pixels in the
00193    same blob. Do this using recursive back tracking to make a blob linked
00194    as one object and not a collection of objects
00195 */
00196 
00197 void segmentImage::discreteLinking()
00198 {
00199 
00200   bool trace = false;
00201   long pixID = 0;
00202   long lastNeighbor;
00203   masters = 0;
00204   mastersCount = 0;
00205   for(int x = frameX1; x < frameX2; x++)
00206   {
00207     trace = false;
00208     lastNeighbor = -2;
00209     for(int y = frameY1; y < frameY2; y++)
00210     {
00211       if(candidatePixels.getVal(x,y))
00212       {
00213         if(!trace)
00214         {
00215           pixID++;
00216           trace = true;
00217           lastNeighbor = -2;
00218         }
00219         blobID.setVal(x,y,pixID);
00220         if((x-1) > frameX1)
00221         {
00222           if(candidatePixels.getVal(x-1,y))
00223           {
00224             // relink blob pixels if needed
00225             long check = blobID.getVal((x-1),y);
00226             if(check != lastNeighbor)
00227             {
00228               backwardLink(pixID,check);
00229               lastNeighbor = check;
00230             }
00231           }
00232           else
00233           {
00234             lastNeighbor = -2;
00235           }
00236         }
00237         else
00238         {
00239           backwardLink(pixID,pixID);
00240         }
00241       }
00242       else
00243       {
00244         trace = false;
00245         blobID.setVal(x,y,0);
00246         lastNeighbor = -2;
00247       }
00248     }
00249   }
00250   //LINFO("Candidate Blobs scanned %d", pixID);
00251   //LINFO("Candidate pixels recognized %d",candi);
00252   num = pixID;
00253 }
00254 
00255 /* relink pixels with new val. This allows pixels that have a new value
00256    to take on the old value of the blob. Slaves take on masters and
00257    masters can take on a slaves master.
00258 
00259 */
00260 
00261 void segmentImage::backwardLink(long slave, long master)
00262 {
00263   long *masterVecMaster = &masterVec[master];
00264   long *masterVecSlave = &masterVec[slave];
00265   // my master has no master
00266   if(*masterVecMaster == -1)
00267   {
00268     // I have no master
00269     if(*masterVecSlave == -1)
00270     {
00271       //LINFO("my master has no master/I have no master");
00272       *masterVecMaster = masters;
00273       *masterVecSlave = masters;
00274       masters++;
00275       mastersCount++;
00276     }
00277     // I already have a master
00278     else
00279     {
00280       //LINFO("my master has no master/I already have a master");
00281       *masterVecMaster = *masterVecSlave;
00282     }
00283   }
00284   // my master has a master
00285   else
00286   {
00287     // I have no master
00288     if(*masterVecSlave == -1)
00289     {
00290       //LINFO("my master has a master/I have no master");
00291       *masterVecSlave = *masterVecMaster;
00292     }
00293     // I already have a master
00294     else
00295     {
00296       //LINFO("my master has a master/I already have a master");
00297       mastersCount--;
00298       for(int i = 0; i < slave; i++)
00299       {
00300         if(masterVec[i] == *masterVecMaster)
00301         {
00302           //LINFO("SET %d to %d",masterVec[i],masterVec[slave]);
00303           masterVec[i] = *masterVecSlave;
00304         }
00305       }
00306     }
00307   }
00308 }
00309 
00310 /* combine individual elements into a fully combined blob */
00311 
00312 void segmentImage::combine()
00313 {
00314   totalBlobs = 0;
00315   for(int x = frameX1; x < frameX2; x++)
00316   {
00317     for(int y = frameY1; y < frameY2; y++)
00318     {
00319       if(candidatePixels.getVal(x,y))
00320       {
00321         blobID.setVal(x,y,masterVec[blobID.getVal(x,y)]);
00322       }
00323     }
00324   }
00325   for(int x = 0; x < num; x++)
00326   {
00327     bool add = true;
00328     //LINFO("Master Vec %d is %d",x,masterVec[x]);
00329     for(int y = 0; y < totalBlobs; y++)
00330     {
00331       if(reOrderVec[y] == masterVec[x])
00332         add = false;
00333     }
00334 
00335     if((add) && (masterVec[x] != -1))
00336     {
00337       //LINFO("DOING %d",masterVec[x]);
00338       reOrderVec[totalBlobs] = masterVec[x];
00339       reverseOrderVec[masterVec[x]] = totalBlobs;
00340       reset[totalBlobs] = true;
00341       totalBlobs++;
00342     }
00343   }
00344   //totalBlobs--;
00345 }
00346 
00347 void segmentImage::doSegment()
00348 {
00349   //LINFO("FINDING CANDIDATES");
00350   if(doType == 1)
00351   {
00352     ASSERT(set1); ASSERT(set2); ASSERT(set3); ASSERT(set4);
00353     findCandidatesRGB();
00354   }
00355   if(doType == 2)
00356   {
00357     ASSERT(set1); ASSERT(set2); ASSERT(set3); ASSERT(set4);
00358     findCandidatesHSV();
00359   }
00360   if(doType == 3)
00361   {
00362     ASSERT(set3); ASSERT(set4);
00363     findCandidatesGREY();
00364   }
00365   //LINFO("REMOVING SINGLES");
00366   removeSingles();
00367   //LINFO("LINKING PIXELS");
00368   discreteLinking();
00369   //LINFO("RELABELING");
00370   combine();
00371   //LINFO("DONE");
00372 }
00373 
00374 /*=============================================================*/
00375 /*        PUBLIC methods                                       */
00376 /*=============================================================*/
00377 
00378 segmentImage::segmentImage(int imageType)
00379 {
00380   doType = imageType;
00381   set1 = false; set2 = false; set3 = false; set4 = false;
00382   LINFO("CREATED");
00383 }
00384 
00385 segmentImage::segmentImage()
00386 {
00387   doType = HSV;
00388   set1 = false; set2 = false; set3 = false; set4 = false;
00389   LINFO("CREATED");
00390 }
00391 
00392 segmentImage::~segmentImage()
00393 {}
00394 
00395 /* set color segmentation values for color and
00396    threshold
00397 */
00398 
00399 void segmentImage::setRed(int val, int thresh = 1, int skew = 0)
00400 {
00401   ASSERT(doType == 1);
00402   red = val;
00403   if(skew <= 0)
00404   {
00405     redLT = val - thresh + skew;
00406     redUT = val + thresh;
00407   }
00408   else
00409   {
00410     redLT = val - thresh;
00411     redUT = val + thresh + skew;
00412   }
00413   set1 = true;
00414 }
00415 
00416 void segmentImage::setGreen(int val, int thresh = 1, int skew = 0)
00417 {
00418   ASSERT(doType == 1);
00419   green = val;
00420   if(skew <= 0)
00421   {
00422     greenLT = val - thresh + skew;
00423     greenUT = val + thresh;
00424   }
00425   else
00426   {
00427     greenLT = val - thresh;
00428     greenUT = val + thresh + skew;
00429   }
00430   set2 = true;
00431 }
00432 
00433 void segmentImage::setBlue(int val, int thresh = 1, int skew = 0)
00434 {
00435   ASSERT(doType == 1);
00436   blue = val;
00437   if(skew <= 0)
00438   {
00439     blueLT = val - thresh + skew;
00440     blueUT = val + thresh;
00441   }
00442   else
00443   {
00444     blueLT = val - thresh;
00445     blueUT = val + thresh + skew;
00446   }
00447   set3 = true;
00448 }
00449 
00450 void segmentImage::setHue(double val, double thresh = 1, double skew = 0)
00451 {
00452   ASSERT(doType == 2);
00453   H = val;
00454   if(skew <= 0)
00455   {
00456     HLT = val - thresh + skew;
00457     HUT = val + thresh;
00458   }
00459   else
00460   {
00461     HLT = val - thresh;
00462     HUT = val + thresh + skew;
00463   }
00464   set1 = true;
00465 }
00466 
00467 void segmentImage::setSat(double val, double thresh = 1, double skew = 0)
00468 {
00469   ASSERT(doType == 2);
00470   S = val;
00471   if(skew <= 0)
00472   {
00473     SLT = val - thresh + skew;
00474     SUT = val + thresh;
00475   }
00476   else
00477   {
00478     SLT = val - thresh;
00479     SUT = val + thresh + skew;
00480   }
00481   set2 = true;
00482 }
00483 
00484 void segmentImage::setVal(double val, double thresh = 1, double skew = 0)
00485 {
00486   ASSERT((doType == 2) || (doType == 3));
00487   V = val;
00488   if(skew <= 0)
00489   {
00490     VLT = val - thresh + skew;
00491     VUT = val + thresh;
00492   }
00493   else
00494   {
00495     VLT = val - thresh;
00496     VUT = val + thresh + skew;
00497   }
00498   set3 = true;
00499 }
00500 
00501 /* set size of window frame to inspect in image */
00502 
00503 void segmentImage::setFrame(int x1, int y1, int x2, int y2,
00504                             int realX, int realY)
00505 {
00506   frameX1 = x1;
00507   frameX2 = x2;
00508   frameY1 = y1;
00509   frameY2 = y2;
00510   masterVec.resize(((x2-x1)*(y2-y1)),-1);
00511   reOrderVec.resize(((x2-x1)*(y2-y1)));
00512   reverseOrderVec.resize(((x2-x1)*(y2-y1)));
00513   centerX.resize(((x2-x1)*(y2-y1)));
00514   centerY.resize(((x2-x1)*(y2-y1)));
00515   Xsum.resize(((x2-x1)*(y2-y1)));
00516   Ysum.resize(((x2-x1)*(y2-y1)));
00517   mass.resize(((x2-x1)*(y2-y1)));
00518   xmin.resize(((x2-x1)*(y2-y1)));
00519   xmax.resize(((x2-x1)*(y2-y1)));
00520   ymin.resize(((x2-x1)*(y2-y1)));
00521   ymax.resize(((x2-x1)*(y2-y1)));
00522   reset.resize(((x2-x1)*(y2-y1)));
00523   LINFO("SETTING WIDTH %d, HEIGHT %d",realX,realY);
00524   blobID.resize(realX,realY,-1);
00525   candidatePixels.resize(realX,realY,false);
00526   preCandidatePixels.resize(realX,realY,false);
00527   set4 = true;
00528 }
00529 
00530 void segmentImage::setHSVavg(long doAvg)
00531 {
00532   Havg.resize(doAvg,0);
00533   Savg.resize(doAvg,0);
00534   Vavg.resize(doAvg,0);
00535   Hstdd.resize(doAvg,0);
00536   Sstdd.resize(doAvg,0);
00537   Vstdd.resize(doAvg,0);
00538   HSVN.resize(doAvg,0);
00539   HSViter = doAvg;
00540   HSVcount = 0;
00541 }
00542 
00543 /* do image segmentation by calling private memebers to
00544    operate on image.
00545    1. Low pass image
00546    2. Find candidate pixels
00547    3. Eleminate single isolated candidates
00548    4. Link pixels in each blob
00549    5. Clean up
00550 */
00551 
00552 void segmentImage::segment(Image<PixRGB<float> > &image)
00553 {
00554   struct timezone tz;
00555   struct timeval start, stop;
00556   tz.tz_minuteswest = 0;
00557   tz.tz_dsttime = 0;
00558   gettimeofday(&start, &tz);
00559 
00560   workImage.resize(1,1);
00561   workImage = lowPass5(image);
00562 
00563   doSegment();
00564 
00565   gettimeofday(&stop,&tz);
00566   //std::cout << micros << " Microseconds to segment\n";
00567 
00568 }
00569 
00570 void segmentImage::segment(Image<float> &image)
00571 {
00572   struct timezone tz;
00573   struct timeval start, stop;
00574   tz.tz_minuteswest = 0;
00575   tz.tz_dsttime = 0;
00576   gettimeofday(&start, &tz);
00577 
00578   workImageGREY.resize(1,1);
00579   workImageGREY = lowPass5(image);
00580 
00581   doSegment();
00582 
00583   gettimeofday(&stop,&tz);
00584   //std::cout << micros << " Microseconds to segment\n";
00585 
00586 }
00587 
00588 /* This method when called will take all remaning blobs from post
00589    processing and create a mother blob
00590 */
00591 
00592 Image<long> segmentImage::createMother(Image<long> &img)
00593 {
00594   Image<long> mother;
00595   mother.resize(img.getWidth(),img.getHeight(),ZEROS);
00596   for(int x = frameX1; x < frameX2; x++)
00597   {
00598     for(int y = frameY1; y < frameY2; y++)
00599     {
00600       if(img.getVal(x,y) != 0)
00601         mother.setVal(x,y,1);
00602       else
00603         mother.setVal(x,y,0);
00604     }
00605   }
00606   return mother;
00607 }
00608 
00609 /* return blob map
00610  */
00611 
00612 Image<long> segmentImage::returnBlobs()
00613 {
00614   return blobID;
00615 }
00616 
00617 Image<bool> segmentImage::returnCandidates()
00618 {
00619   return candidatePixels;
00620 }
00621 
00622 Image<float> segmentImage::returnNormalizedCandidates()
00623 {
00624   Image<float> NC;
00625   NC.resize(candidatePixels.getWidth(),candidatePixels.getHeight());
00626   for(int x = 0; x < candidatePixels.getWidth(); x++)
00627   {
00628     for(int y = 0; y < candidatePixels.getHeight(); y++)
00629     {
00630       if(candidatePixels.getVal(x,y))
00631         NC.setVal(x,y,255.0F);
00632       else
00633         NC.setVal(x,y,0.0F);
00634     }
00635   }
00636   return NC;
00637 }
00638 
00639 Image<PixRGB<float> > segmentImage::returnWorkImage()
00640 {
00641   ASSERT((doType == 1) || (doType == 2));
00642   return workImage;
00643 }
00644 
00645 Image<float> segmentImage::returnWorkImageGREY()
00646 {
00647   ASSERT(doType == 3);
00648   return workImageGREY;
00649 }
00650 
00651 
00652 int segmentImage::numberBlobs()
00653 {
00654   return totalBlobs;
00655 }
00656 
00657 std::vector<long> segmentImage::getBlobMap()
00658 {
00659   return reOrderVec;
00660 }
00661 
00662 void segmentImage::calcMassCenter()
00663 {
00664   for(int x = frameX1; x < frameX2; x++)
00665   {
00666     for(int y = frameY1; y < frameY2; y++)
00667     {
00668       if((candidatePixels.getVal(x,y)) && (blobID.getVal(x,y) != -1))
00669       {
00670         //std::cerr << "foo " << reverseOrderVec[blobID.getVal(x,y)] << "\n";
00671         long *indexBlob = &reverseOrderVec[blobID.getVal(x,y)];
00672         if(reset[*indexBlob])
00673         {
00674           reset[*indexBlob] = false;
00675           Xsum[*indexBlob] = x;
00676           Ysum[*indexBlob] = y;
00677           mass[*indexBlob] = 1;
00678           xmin[*indexBlob] = x;
00679           ymin[*indexBlob] = y;
00680           xmax[*indexBlob] = x;
00681           ymax[*indexBlob] = y;
00682         }
00683         else
00684         {
00685           Xsum[*indexBlob] += x;
00686           Ysum[*indexBlob] += y;
00687           mass[*indexBlob]++;
00688           if(x <= xmin[*indexBlob])
00689             xmin[*indexBlob] = x;
00690           if(x >= xmax[*indexBlob])
00691             xmax[*indexBlob] = x;
00692           if(y <= ymin[*indexBlob])
00693             ymin[*indexBlob] = y;
00694           if(y >= ymax[*indexBlob])
00695             ymax[*indexBlob] = y;
00696         }
00697       }
00698     }
00699   }
00700 
00701   for(int x = 0; x < totalBlobs; x++)
00702   {
00703     //std::cerr << "MASS " << mass[x] << "\n";
00704     if(mass[x] > 0)
00705     {
00706       centerX[x] = Xsum[x]/mass[x];
00707       centerY[x] = Ysum[x]/mass[x];
00708     }
00709   }
00710 }
00711 
00712 float segmentImage::getCenterX(long blob)
00713 {
00714   return centerX[blob];
00715 }
00716 
00717 float segmentImage::getCenterY(long blob)
00718 {
00719   return centerY[blob];
00720 }
00721 
00722 long segmentImage::getMass(long blob)
00723 {
00724   return mass[blob];
00725 }
00726 
00727 int segmentImage::getXmin(long blob)
00728 {
00729   return xmin[blob];
00730 }
00731 
00732 //! get X max for a blob
00733 
00734 int segmentImage::getXmax(long blob)
00735 {
00736   return xmax[blob];
00737 }
00738 
00739 //! get Y min for a blob
00740 
00741 int segmentImage::getYmin(long blob)
00742 {
00743   return ymin[blob];
00744 }
00745 
00746 //! get Y max for a blob
00747 
00748 int segmentImage::getYmax(long blob)
00749 {
00750   return ymax[blob];
00751 }
00752 
00753  //! get the working image size in X
00754 int segmentImage::getImageSizeX()
00755 {
00756   return candidatePixels.getWidth();
00757 }
00758 //! get the working image size in Y
00759 int segmentImage::getImageSizeY()
00760 {
00761   return candidatePixels.getHeight();
00762 }
00763 
00764 void segmentImage::getHSVvalue(long blob, float *H, float *S, float *V,
00765                    float *Hstd, float *Sstd, float *Vstd)
00766 {
00767   float totH = 0.0F, totS = 0.0F, totV = 0.0F;
00768   float ssH = 0.0F, ssS = 0.0F, ssV = 0.0F;
00769   PixRGB<float> pix;
00770   for(int x = frameX1; x < frameX2; x++)
00771   {
00772     for(int y = frameY1; y < frameY2; y++)
00773     {
00774       if((candidatePixels.getVal(x,y)) && (blobID.getVal(x,y) != -1))
00775       {
00776         if(reverseOrderVec[blobID.getVal(x,y)] == blob)
00777         {
00778           float pixH,pixS,pixV;
00779           pix = workImage.getVal(x,y);
00780           PixHSV<float>(pix).getHSV(pixH,pixS,pixV);
00781           totH +=pixH; totS += pixS; totV += pixV;
00782           ssH += (pow(pixH,2))/mass[blob];
00783           ssS += (pow(pixS,2))/mass[blob];
00784           ssV += (pow(pixV,2))/mass[blob];
00785         }
00786       }
00787     }
00788   }
00789   if(mass[blob] > 0)
00790   {
00791     *H = totH/mass[blob];
00792     *S = totS/mass[blob];
00793     *V = totV/mass[blob];
00794     *Hstd = sqrt(ssH - pow(*H,2));
00795     *Sstd = sqrt(ssS - pow(*S,2));
00796     *Vstd = sqrt(ssV - pow(*V,2));
00797   }
00798 }
00799 
00800 void segmentImage::getHSVvalueMean(long blob, float *H, float *S, float *V,
00801                         float *Hstd, float *Sstd, float *Vstd)
00802 {
00803   double massSum = 0;
00804   if(HSVcount == HSViter)
00805     HSVcount = 0;
00806   getHSVvalue(blob, &Havg[HSVcount], &Savg[HSVcount], &Vavg[HSVcount]
00807               ,&Hstdd[HSVcount], &Sstdd[HSVcount], &Vstdd[HSVcount]);
00808   HSVN[HSVcount] = mass[blob];
00809   HSVcount++;
00810   for(int i = 0; i < HSViter; i++)
00811   {
00812     massSum += HSVN[i];
00813     *H += Havg[i]*HSVN[i];
00814     *S += Savg[i]*HSVN[i];
00815     *V += Vavg[i]*HSVN[i];
00816     *Hstd += Hstdd[i]*HSVN[i];
00817     *Sstd += Sstdd[i]*HSVN[i];
00818     *Vstd += Vstdd[i]*HSVN[i];
00819   }
00820   if(massSum > 0)
00821   {
00822     *H = *H/massSum;
00823     *S = *S/massSum;
00824     *V = *V/massSum;
00825     *Hstd = *Hstd/massSum;
00826     *Sstd = *Sstd/massSum;
00827     *Vstd = *Vstd/massSum;
00828   }
00829 }
00830 
00831 // ######################################################################
00832 /* So things look consistent in everyone's emacs... */
00833 /* Local Variables: */
00834 /* indent-tabs-mode: nil */
00835 /* End: */
Generated on Sun May 8 08:42:35 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3