00001 /*!@file VFAT/segmentImageTrackMC2.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/segmentImageTrackMC2.C $ 00035 // $Id: segmentImageTrackMC2.C 14376 2011-01-11 02:44:34Z pez $ 00036 // 00037 00038 // ############################################################ 00039 // ############################################################ 00040 // ##### --- VFAT --- 00041 // ##### Vision Feature Analysis Tool: 00042 // ##### T. Nathan Mundhenk nathan@mundhenk.com 00043 // ##### Laurent Itti itti@pollux.usc.edu 00044 // ##### 00045 // ############################################################ 00046 // ############################################################ 00047 00048 #ifndef SEGMENTIMAGETRACKMC2_C_DEFINED 00049 #define SEGMENTIMAGETRACKMC2_C_DEFINED 00050 00051 #include "Util/Assert.H" 00052 #include "VFAT/segmentImageTrackMC2.H" 00053 #include "Image/DrawOps.H" 00054 #include "Raster/Raster.H" 00055 00056 #include <cstdio> 00057 #include <cstdlib> 00058 #include <iostream> 00059 #include <limits> 00060 #include <time.h> 00061 00062 00063 //! maximum lose of tracks before color is reset 00064 #define LOTMAX 5 00065 00066 //! How many iteration to calculate over for movement statistics 00067 #define ERRINTERVAL 5 00068 00069 //! decimation size reduction factor 00070 //#define DEC 2 00071 00072 //! Width of channel bars 00073 #define BARWIDTH 10 00074 00075 //! spacing between channel histo bars 00076 #define BARSPACE 5 00077 00078 //! histogram height 00079 #define HISTOHEIGHT 450.0F 00080 00081 /*********************************************************************/ 00082 // compute color adaptation 00083 00084 template SIT_TEMPLATE_CLASS 00085 void segmentImageTrackMC<SIT_TEMPLATE>::SITcolorAdaptation() 00086 { 00087 SIT_totalLifeSpan++; 00088 if(SIT_resetColor == false) 00089 { 00090 FLOAT mass = 0; 00091 typename std::vector<FLOAT>::iterator imean1 = SIT_chMean1.begin(); 00092 typename std::vector<FLOAT>::iterator imean2; 00093 typename std::vector<FLOAT>::iterator istd1; 00094 typename std::vector<FLOAT>::iterator istd2; 00095 typename std::vector<FLOAT>::iterator ilb; 00096 typename std::vector<FLOAT>::iterator iub; 00097 00098 while(imean1 != SIT_chMean1.end()) 00099 *imean1++ = 0; 00100 00101 // iterate over all blobs and asses new color thresholds from 00102 // candidate blobs 00103 SIT_blobListSize = 0; 00104 // (1) figure out which blobs we wish to extract information from 00105 for(INT i = 0; i < (unsigned)SIT_segment.SInumberBlobs(); i++) 00106 { 00107 if(SIT_candidateBlob[i] == true) 00108 { 00109 SIT_blobList[SIT_blobListSize] = i; 00110 SIT_blobListSize++; 00111 } 00112 } 00113 // (2) find mean color values for each blob if we have at least 00114 // one blob. This includes 00115 // (a) mean color for each blob 00116 // (b) variance (sum of squares) color for each blob 00117 // (c) Mass of each blob (number of pixels) 00118 if(SIT_blobListSize > 0) 00119 SIT_segment.SIgetValueMean(&SIT_blobListSize,&SIT_blobList, 00120 &SIT_chMean1,&SIT_chStd1,&mass); 00121 00122 // (3) If we have elected to, draw tracking targets for blobs 00123 if(SIT_drawTargetImage == true) 00124 { 00125 for(INT i = 0; i < SIT_segment.SInumberBlobs(); i++) 00126 { 00127 if(SIT_candidateBlob[i] == true) 00128 { 00129 SITdrawBlobTrack(i); 00130 } 00131 else 00132 { 00133 if(SIT_killedByTrack[i] == false) 00134 { 00135 SITdrawBlobBox(i); 00136 } 00137 } 00138 } 00139 } 00140 00141 // (4) draw color bar graph if blobs have any mass 00142 if((SIT_LOT == false) && (SIT_drawTargetImage == true)) 00143 { 00144 SITdrawBlobTrackMerged(); 00145 } 00146 00147 if(SIT_mass != 0) 00148 { 00149 istd1 = SIT_chStd1.begin(); 00150 SIT_oldMean = SIT_chMean1; 00151 SIT_oldStd = SIT_chStd1; 00152 SIT_oldUB = SIT_chUB; 00153 SIT_oldLB = SIT_chLB; 00154 SIT_oldNorm = SIT_chNorm; 00155 SIT_draw = true; 00156 } 00157 00158 // (5.a) If loss of track is registered 5 times (whatever LOTMAX is) 00159 // , reset color to orignal values from start up. throw away adaptive 00160 // values since they are no longer dependable 00161 if((SIT_LOT == true) && (SIT_useColorAdaptation == true)) 00162 { 00163 //LINFO("LOT Number %d",SIT_LOTcount); 00164 if(SIT_drawColorAdaptImage == true) 00165 SITdrawHistoValues(&SIT_oldMean,&SIT_oldStd, 00166 &SIT_oldUB,&SIT_oldLB,&SIT_oldNorm,true); 00167 if(SIT_LOTcount > LOTMAX) 00168 { 00169 LINFO("COLOR RESET due to LOT COUNT"); 00170 SITresetColor(); // Will set SIT_resetColor = true 00171 } 00172 else 00173 { 00174 SIT_LOTcount++; 00175 } 00176 } 00177 else 00178 { 00179 SIT_LOTcount = 0; 00180 } 00181 00182 //if((SIT_mass != 0) && (SIT_resetColor == false)) 00183 if((SIT_LOT == false) && (SIT_useColorAdaptation == true)) 00184 //if(SIT_mass != 0) 00185 { 00186 SIT_lifeSpan++; 00187 if(SIT_drawColorAdaptImage == true) 00188 SITdrawHistoValues(&SIT_chMean1,&SIT_chStd1, 00189 &SIT_chUB,&SIT_chLB,&SIT_chNorm,false); 00190 // (5.b) if adaptive thresholding is turned on, adjust color 00191 // by standard deviation of color. As such each blobs color will 00192 // determin the new tracking color. 00193 istd1 = SIT_chStd1.begin(); 00194 ilb = SIT_chLB.begin(); 00195 iub = SIT_chUB.begin(); 00196 00197 typename std::vector<FLOAT>::iterator iadapt = SIT_chAdapt.begin(); 00198 typename std::vector<FLOAT>::iterator instd = SIT_chNSTD.begin(); 00199 00200 for(imean1 = SIT_chMean1.begin(); imean1 != SIT_chMean1.end(); ++imean1, 00201 ++istd1, ++iub, ++ilb, ++instd) 00202 { 00203 00204 *instd = *istd1*(*iadapt); 00205 if(SIT_useHardBounds == true) 00206 { 00207 if(*imean1 > *iub) 00208 { 00209 *imean1 = *iub; 00210 } 00211 else if(*imean1 < *ilb) 00212 { 00213 *imean1 = *ilb; 00214 } 00215 } 00216 } 00217 if(SIT_useLog == true) 00218 { 00219 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00220 outfile << "FRAME " << SIT_frameNumber << " ADAPT " << "\t"; 00221 typename std::vector<FLOAT>::iterator instd = SIT_chNSTD.begin(); 00222 for(imean1 = SIT_chMean1.begin(); imean1 != SIT_chMean1.end(); 00223 ++imean1,++instd) 00224 { 00225 outfile << *imean1 << " +/- (" << *instd << ")\t"; 00226 } 00227 outfile << "\n"; 00228 outfile.close(); 00229 } 00230 SIT_segment.SIsetVal(SIT_chMean1,SIT_chNSTD); 00231 } 00232 } 00233 else 00234 { 00235 LINFO("COLOR RESET TO USERS"); 00236 SIT_resetColor = false; 00237 } 00238 } 00239 00240 /*********************************************************************/ 00241 template SIT_TEMPLATE_CLASS 00242 void segmentImageTrackMC<SIT_TEMPLATE>::SITresetColor() 00243 { 00244 SIT_segment.SIresetAvg(); 00245 SIT_segment.SIsetVal(SIT_initMean,SIT_initStd); 00246 00247 if(SIT_useLog == true) 00248 { 00249 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00250 outfile << "FRAME " << SIT_frameNumber << " RESET " << "\t"; 00251 typename std::vector<FLOAT>::iterator imean = SIT_initMean.begin(); 00252 typename std::vector<FLOAT>::iterator istd = SIT_initStd.begin(); 00253 while(imean != SIT_initMean.end()) 00254 { 00255 outfile << *imean << " +/- (" << *istd << ")\t"; 00256 ++imean; ++istd; 00257 } 00258 outfile << "\n"; 00259 outfile.close(); 00260 } 00261 00262 SIT_segment.SIresetCandidates(true); 00263 SIT_LOTcount = 0; 00264 SIT_totalLifeSpan = 0; 00265 SIT_lifeSpan = 0; 00266 SIT_resetColor = true; 00267 SIT_LOTandRESET = true; 00268 } 00269 00270 /*********************************************************************/ 00271 // weed out blobs that suck 00272 00273 template SIT_TEMPLATE_CLASS 00274 void segmentImageTrackMC<SIT_TEMPLATE>::SITanalyzeBlobs() 00275 { 00276 SIT_totalBlobs = SIT_segment.SInumberBlobs(); 00277 SIT_killedBlobs = 0; 00278 00279 // (1.a) We have a loss of track, as such we need to reset some of 00280 // the adaptive parameters. Here we reset the parameter where we 00281 // expect the target to be to a much larger area since we no longer 00282 // can assume its location do to loss of track. 00283 if(SIT_LOT == true) 00284 { 00285 SIT_xBound = SIT_blobProp.BP_LOTbound; 00286 SIT_yBound = SIT_blobProp.BP_LOTbound; 00287 } 00288 else 00289 { 00290 // (1.b) We expect the target to appear close to where we last saw it 00291 // we set a parameter around the last known location. Any blob outside 00292 // this parameter must be predjidist 00293 00294 SIT_xBound = (int)(SIT_blobProp.BP_bound + 00295 (SIT_thresh*SIT_blobProp.BP_softBound)); 00296 SIT_yBound = (int)(SIT_blobProp.BP_bound + 00297 (SIT_thresh*SIT_blobProp.BP_softBound)); 00298 } 00299 00300 std::vector<bool>::iterator softCandidateBlobItr 00301 = SIT_softCandidateBlob.begin(); 00302 std::vector<bool>::iterator candidateBlobItr 00303 = SIT_candidateBlob.begin(); 00304 std::vector<bool>::iterator killedByTrackItr 00305 = SIT_killedByTrack.begin(); 00306 std::vector<std::string>::iterator reasonForKillItr 00307 = SIT_reasonForKill.begin(); 00308 std::vector<unsigned short>::iterator reasonForKillCodeItr 00309 = SIT_reasonForKillCode.begin(); 00310 00311 std::string S1,S2,S3; 00312 char C1[48], C2[48], C3[48]; 00313 // (2) For each blob that the tracker found as a potential target, 00314 // check its properties such as its location in the image vs. 00315 // where we expect the target to be. Also check to make sure that the 00316 // target is geometrically good. That is, make sure its mass, size and 00317 // basic shape conform to our expectations. 00318 for(INT i = 0; i < SIT_totalBlobs; i++, 00319 ++softCandidateBlobItr, ++candidateBlobItr, 00320 ++killedByTrackItr, ++reasonForKillItr, ++reasonForKillCodeItr) 00321 { 00322 *softCandidateBlobItr = true; 00323 *candidateBlobItr = true; 00324 *killedByTrackItr = false; 00325 *reasonForKillCodeItr = 0; 00326 *reasonForKillItr = "(0) Blob OK "; 00327 00328 // (3) check if a blobs mass is within cosnstraints. That is 00329 // Make sure the blob is neither too large or to small. If so, we 00330 // don't like it. 00331 if((SIT_segment.SIgetMass(i) < (INT)SIT_blobProp.BP_minMass) 00332 && (SIT_blobProp.BP_checkMass == true)) 00333 { 00334 *candidateBlobItr = false; 00335 *softCandidateBlobItr = false; 00336 *killedByTrackItr = true; 00337 *reasonForKillCodeItr = 1; 00338 SIT_killedBlobs++; 00339 00340 S1 = " Blob Mass Contraints : Min : "; S2 = " < "; 00341 sprintf(C1,"%d",(int)SIT_segment.SIgetMass(i)); 00342 sprintf(C2,"%d",(int)SIT_blobProp.BP_minMass); 00343 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00344 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00345 } 00346 else if((SIT_segment.SIgetMass(i) > (INT)SIT_blobProp.BP_maxMass) 00347 && (SIT_blobProp.BP_checkMass == true)) 00348 { 00349 00350 *candidateBlobItr = false; 00351 *softCandidateBlobItr = false; 00352 *killedByTrackItr = true; 00353 *reasonForKillCodeItr = 2; 00354 SIT_killedBlobs++; 00355 00356 S1 = " Blob Mass Contraints : Max : "; S2 = " > "; 00357 sprintf(C1,"%d",(int)SIT_segment.SIgetMass(i)); 00358 sprintf(C2,"%d",(int)SIT_blobProp.BP_maxMass); 00359 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00360 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00361 } 00362 // (4) check that a blob is within our X frame. That is, does 00363 // a blob fall in the image in a place where we would expect it 00364 // for instance close to where we last saw it. 00365 else if((SIT_segment.SIgetCenterX(i) < (SIT_centerX - SIT_xBound)) 00366 && (SIT_blobProp.BP_checkFrameX == true)) 00367 { 00368 *candidateBlobItr = false; 00369 *killedByTrackItr = true; 00370 *reasonForKillCodeItr = 3; 00371 SIT_killedBlobs++; 00372 00373 S1 = " Blob Out of X Frame : Low : "; S2 = " < "; 00374 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00375 sprintf(C2,"%d",(int)(SIT_centerX - SIT_xBound)); 00376 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00377 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00378 } 00379 else if((SIT_segment.SIgetCenterX(i) > (SIT_centerX + SIT_xBound)) 00380 && (SIT_blobProp.BP_checkFrameX == true)) 00381 { 00382 *candidateBlobItr = false; 00383 *killedByTrackItr = true; 00384 *reasonForKillCodeItr = 4; 00385 SIT_killedBlobs++; 00386 00387 S1 = " Blob Out of X Frame : High : "; S2 = " > "; 00388 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00389 sprintf(C2,"%d",(int)(SIT_centerX + SIT_xBound)); 00390 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00391 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00392 } 00393 // (5) check that a blob is within our Y frame. That is, does 00394 // a blob fall in the image in a place where we would expect it 00395 // for instance close to where we last saw it. 00396 else if((SIT_segment.SIgetCenterY(i) < (SIT_centerY - SIT_yBound)) 00397 && (SIT_blobProp.BP_checkFrameY == true)) 00398 { 00399 *candidateBlobItr = false; 00400 *killedByTrackItr = true; 00401 *reasonForKillCodeItr = 5; 00402 SIT_killedBlobs++; 00403 00404 S1 = " Blob Out of Y Frame : Low : "; S2 = " < "; 00405 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00406 sprintf(C2,"%d",(int)(SIT_centerY - SIT_yBound)); 00407 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00408 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00409 } 00410 else if((SIT_segment.SIgetCenterY(i) > (SIT_centerY + SIT_yBound)) 00411 && (SIT_blobProp.BP_checkFrameY == true)) 00412 { 00413 *candidateBlobItr = false; 00414 *killedByTrackItr = true; 00415 *reasonForKillCodeItr = 6; 00416 SIT_killedBlobs++; 00417 00418 S1 = " Blob Out of Y Frame : High : "; S2 = " > "; 00419 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00420 sprintf(C2,"%d",(int)(SIT_centerY + SIT_yBound)); 00421 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00422 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00423 } 00424 // (6) check that a blob is within our EXPECTED X frame. That is, does 00425 // a blob fall in the image in a place where we would expect it 00426 // for instance close to where we last saw it. 00427 // This is used only if we apriori set this value 00428 else if((SIT_segment.SIgetCenterX(i) > SIT_expectedXmax) && 00429 (SIT_useExpectedLocation == true)) 00430 { 00431 *candidateBlobItr = false; 00432 *killedByTrackItr = true; 00433 *reasonForKillCodeItr = 7; 00434 SIT_killedBlobs++; 00435 00436 S1 = " Blob Out of Set Expected X Frame : High : "; S2 = " > "; 00437 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00438 sprintf(C2,"%d",(int)(SIT_expectedXmax)); 00439 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00440 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00441 } 00442 else if((SIT_segment.SIgetCenterX(i) < SIT_expectedXmin) && 00443 (SIT_useExpectedLocation == true)) 00444 { 00445 *candidateBlobItr = false; 00446 *killedByTrackItr = true; 00447 *reasonForKillCodeItr = 8; 00448 SIT_killedBlobs++; 00449 00450 S1 = " Blob Out of Set Expected X Frame : Low : "; S2 = " < "; 00451 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00452 sprintf(C2,"%d",(int)(SIT_expectedXmin)); 00453 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00454 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00455 } 00456 // (7) check that a blob is within our EXPECTED Y frame. That is, does 00457 // a blob fall in the image in a place where we would expect it 00458 // for instance close to where we last saw it. 00459 // This is used only if we apriori set this value 00460 else if((SIT_segment.SIgetCenterY(i) > SIT_expectedYmax) && 00461 (SIT_useExpectedLocation == true)) 00462 { 00463 *candidateBlobItr = false; 00464 *killedByTrackItr = true; 00465 *reasonForKillCodeItr = 9; 00466 SIT_killedBlobs++; 00467 00468 S1 = " Blob Out of Set Expected Y Frame : High : "; S2 = " > "; 00469 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00470 sprintf(C2,"%d",(int)(SIT_expectedYmax)); 00471 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00472 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00473 } 00474 else if((SIT_segment.SIgetCenterY(i) < SIT_expectedYmin) && 00475 (SIT_useExpectedLocation == true)) 00476 { 00477 *candidateBlobItr = false; 00478 *killedByTrackItr = true; 00479 *reasonForKillCodeItr = 10; 00480 SIT_killedBlobs++; 00481 00482 S1 = " Blob Out of Set Expected Y Frame : Low : "; S2 = " < "; 00483 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00484 sprintf(C2,"%d",(int)(SIT_expectedYmin)); 00485 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00486 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00487 } 00488 // (8) check that blob is within size ratios. That is, does the 00489 // blob have a proper height and width for the target as we would 00490 // expect. For instance, as head should have a height and width that 00491 // are about the same. 00492 else if(SIT_blobProp.BP_checkSizeRatios == true) 00493 { 00494 FLOAT foo = (SIT_segment.SIgetXmax(i) - SIT_segment.SIgetXmin(i)); 00495 if(foo != 0) 00496 { 00497 FLOAT temp = (SIT_segment.SIgetYmax(i) 00498 - SIT_segment.SIgetYmin(i))/foo; 00499 00500 if(temp < (SIT_blobProp.BP_ratioMin 00501 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))) 00502 { 00503 *candidateBlobItr = false; 00504 *killedByTrackItr = true; 00505 *reasonForKillCodeItr = 11; 00506 SIT_killedBlobs++; 00507 00508 S1 = " Blob Size Ratios Contraint : Min :"; S2 = " < "; 00509 sprintf(C1,"%d",(int)temp); 00510 sprintf(C2,"%d",(int)(SIT_blobProp.BP_ratioMin 00511 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))); 00512 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00513 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00514 } 00515 else if (temp > (SIT_blobProp.BP_ratioMax 00516 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))) 00517 { 00518 *candidateBlobItr = false; 00519 *killedByTrackItr = true; 00520 *reasonForKillCodeItr = 12; 00521 SIT_killedBlobs++; 00522 00523 S1 = " Blob Size Ratios Contraint : Max : "; S2 = " > "; 00524 sprintf(C1,"%d",(int)temp); 00525 sprintf(C2,"%d",(int)(SIT_blobProp.BP_ratioMax 00526 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))); 00527 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00528 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00529 } 00530 } 00531 } 00532 } 00533 } 00534 00535 00536 /*********************************************************************/ 00537 // merge all remaining blobs into a single new blob 00538 00539 template SIT_TEMPLATE_CLASS 00540 void segmentImageTrackMC<SIT_TEMPLATE>::SITmergeBlobs() 00541 { 00542 SIT_mass = 0; 00543 FLOAT meanX = 0; 00544 FLOAT meanY = 0; 00545 // changed from UINT_MAX to std::numeric_limits<unsigned 00546 // short>::max() to avoid "warning: large integer implicitly 00547 // truncated to unsigned type" from g++ 4.1 00548 SIT_minX = std::numeric_limits<unsigned short>::max(); 00549 SIT_minY = std::numeric_limits<unsigned short>::max(); 00550 SIT_maxX = 0; 00551 SIT_maxY = 0; 00552 00553 // calculate the center of a combined blob from the average 00554 // mass center of all remaining blobs 00555 std::vector<bool>::iterator candidateBlobItr = SIT_candidateBlob.begin(); 00556 00557 for(INT i = 0; i < SIT_segment.SInumberBlobs(); i++, ++candidateBlobItr) 00558 { 00559 if(*candidateBlobItr == true) 00560 { 00561 SIT_mass += SIT_segment.SIgetMass(i); 00562 meanX += SIT_segment.SIgetMass(i)*SIT_segment.SIgetCenterX(i); 00563 meanY += SIT_segment.SIgetMass(i)*SIT_segment.SIgetCenterY(i); 00564 00565 if((unsigned)SIT_segment.SIgetXmax(i) > SIT_maxX) 00566 SIT_maxX = SIT_segment.SIgetXmax(i); 00567 00568 if((unsigned)SIT_segment.SIgetYmax(i) > SIT_maxY) 00569 SIT_maxY = SIT_segment.SIgetYmax(i); 00570 00571 if((unsigned)SIT_segment.SIgetXmin(i) < SIT_minX) 00572 SIT_minX = SIT_segment.SIgetXmin(i); 00573 00574 if((unsigned)SIT_segment.SIgetYmin(i) < SIT_minY) 00575 SIT_minY = SIT_segment.SIgetYmin(i); 00576 } 00577 } 00578 00579 // Compute SIT_LOT here and set 00580 if(SIT_mass != 0) 00581 { 00582 SIT_centerX = (int)(meanX/SIT_mass); 00583 SIT_centerY = (int)(meanY/SIT_mass); 00584 00585 if(((SIT_maxX-SIT_minX)*(SIT_maxY-SIT_minY)) > 00586 ((SIT_segment.SIgetImageSizeX()*SIT_segment.SIgetImageSizeY()) 00587 /SIT_blobProp.BP_maxFrameSize)) 00588 { 00589 SIT_LOT = true; 00590 SIT_LOTtype = 1; 00591 SIT_LOTtypeName = "(1) Postive Mass but Spacially too Large"; 00592 } 00593 else 00594 { 00595 SIT_LOT = false; 00596 SIT_LOTtypeName = "(0) NO LOT, OK"; 00597 SIT_useExpectedLocation = false; 00598 } 00599 } 00600 else 00601 { 00602 SIT_LOTtypeName = "(2) Zero Mass in merged blobs"; 00603 SIT_LOTtype = 2; 00604 SIT_LOT = true; 00605 00606 // JACOB: changed this to fixed values instead of calling 00607 // a pointer that may or may not be assigned to something 00608 SIT_centerX = SIT_x_center; 00609 SIT_centerY = SIT_y_center; 00610 } 00611 } 00612 00613 /*********************************************************************/ 00614 // PUBLIC ACCESS METHODS 00615 /*********************************************************************/ 00616 00617 // When called at the start, this will resize all the vectors we use 00618 // We only call this once since it is expensive to call. 00619 template SIT_TEMPLATE_CLASS 00620 segmentImageTrackMC<SIT_TEMPLATE>::segmentImageTrackMC(INT maxBlobCount) 00621 { 00622 SIT_LOTcount = 0; 00623 SIT_frameNumber = 0; 00624 SIT_useLog = false; 00625 SIT_drawTargetImage = true; 00626 SIT_drawColorAdaptImage = true; 00627 SIT_useColorAdaptation = true; 00628 SIT_editBlobs = true; 00629 SIT_useHardBounds = false; 00630 00631 time_t t = time(0); 00632 std::string theTime = asctime(localtime(&t)); 00633 00634 std::ofstream outfile(SIT_LOG_FILE,std::ios::out); 00635 outfile << theTime << "\n"; 00636 outfile.close(); 00637 00638 SIT_draw = false; 00639 SIT_didCircleColor = false; 00640 SIT_didBoxColor = false; 00641 SIT_didTrackColor = false; 00642 00643 // resize a bunch of std contaner vectors 00644 00645 SIT_chMean1.resize( SIT_channels,0); 00646 SIT_chMean2.resize( SIT_channels,0); 00647 SIT_chStd1.resize( SIT_channels,0); 00648 SIT_chStd2.resize( SIT_channels,0); 00649 SIT_chLB.resize( SIT_channels,0); 00650 SIT_chUB.resize( SIT_channels,0); 00651 SIT_chNSTD.resize( SIT_channels,0); 00652 SIT_chAdapt.resize( SIT_channels,0); 00653 SIT_chSkew.resize( SIT_channels,0); 00654 SIT_initMean.resize(SIT_channels,0); 00655 SIT_initStd.resize( SIT_channels,0); 00656 00657 SIT_softCandidateBlob.resize(maxBlobCount,false); 00658 SIT_candidateBlob.resize( maxBlobCount,false); 00659 SIT_killedByTrack.resize( maxBlobCount,false); 00660 SIT_blobList.resize( maxBlobCount,0); 00661 SIT_reasonForKill.resize( maxBlobCount,"no reason"); 00662 SIT_reasonForKillCode.resize(maxBlobCount,0); 00663 00664 SIT_barWidth = BARWIDTH; 00665 SIT_barSpace = BARSPACE; 00666 SIT_histoHeight = HISTOHEIGHT; 00667 00668 00669 // Load the config file and set a whole bunch of parameters from it 00670 00671 blobConf.openFile("blob.conf",true); 00672 00673 SIT_blobProp.BP_LOTbound = (int)blobConf.getItemValueF("BP_LOTbound"); 00674 SIT_blobProp.BP_bound = (int)blobConf.getItemValueF("BP_bound"); 00675 SIT_blobProp.BP_softBound = (int)blobConf.getItemValueF("BP_softBound"); 00676 SIT_blobProp.BP_lowBound = (int)blobConf.getItemValueF("BP_lowBound"); 00677 SIT_blobProp.BP_traj = (int)blobConf.getItemValueF("BP_traj"); 00678 SIT_blobProp.BP_sampleStart = (int)blobConf.getItemValueF("BP_sampleStart"); 00679 SIT_blobProp.BP_maxTraj = (int)blobConf.getItemValueF("BP_maxTraj"); 00680 SIT_blobProp.BP_maxSize = (int)blobConf.getItemValueF("BP_maxSize"); 00681 SIT_blobProp.BP_minSize = (int)blobConf.getItemValueF("BP_minSize"); 00682 SIT_blobProp.BP_maxFrameSize = blobConf.getItemValueF("BP_maxFrameSize"); 00683 SIT_blobProp.BP_minMass = (int)blobConf.getItemValueF("BP_minMass"); 00684 SIT_blobProp.BP_maxMass = (int)blobConf.getItemValueF("BP_maxMass"); 00685 SIT_blobProp.BP_ratioMin = blobConf.getItemValueF("BP_ratioMin"); 00686 SIT_blobProp.BP_softRatioMin = blobConf.getItemValueF("BP_softRatioMin"); 00687 SIT_blobProp.BP_ratioMax = blobConf.getItemValueF("BP_ratioMax"); 00688 SIT_blobProp.BP_softRatioMax = blobConf.getItemValueF("BP_softRatioMax"); 00689 SIT_blobProp.BP_checkMass = blobConf.getItemValueB("BP_checkMass"); 00690 SIT_blobProp.BP_checkFrameX = blobConf.getItemValueB("BP_checkFrameX"); 00691 SIT_blobProp.BP_checkFrameY = blobConf.getItemValueB("BP_checkFrameY"); 00692 SIT_blobProp.BP_checkSizeRatios = 00693 blobConf.getItemValueB("BP_checkSizeRatios"); 00694 00695 } 00696 00697 /*********************************************************************/ 00698 00699 template SIT_TEMPLATE_CLASS 00700 segmentImageTrackMC<SIT_TEMPLATE>::~segmentImageTrackMC() 00701 {} 00702 00703 /*********************************************************************/ 00704 00705 template SIT_TEMPLATE_CLASS 00706 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetCircleColor(unsigned char r, 00707 unsigned char g, 00708 unsigned char b) 00709 { 00710 SIT_circleRed = r; 00711 SIT_circleBlue = g; 00712 SIT_circleGreen = b; 00713 SIT_didCircleColor = true; 00714 } 00715 00716 /*********************************************************************/ 00717 00718 template SIT_TEMPLATE_CLASS 00719 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetBoxColor(unsigned char r, 00720 unsigned char g, 00721 unsigned char b, 00722 unsigned char bigr, 00723 unsigned char bigg, 00724 unsigned char bigb) 00725 { 00726 SIT_boxRed = r; 00727 SIT_boxGreen = g; 00728 SIT_boxBlue = b; 00729 SIT_bigBoxRed = bigr; 00730 SIT_bigBoxGreen = bigg; 00731 SIT_bigBoxBlue = bigb; 00732 SIT_didBoxColor = true; 00733 } 00734 00735 00736 /*********************************************************************/ 00737 00738 template SIT_TEMPLATE_CLASS 00739 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetTrackSignature( 00740 const covHolder<double> *cov, 00741 segHolder<FLOAT,INT,SIT_channels> *seg) 00742 { 00743 std::vector<unsigned short>::iterator channelMap = seg->channelMap.begin(); 00744 typename std::vector<FLOAT>::iterator initMean = SIT_initMean.begin(); 00745 typename std::vector<FLOAT>::iterator initStd = SIT_initStd.begin(); 00746 typename std::vector<FLOAT>::iterator chUB = SIT_chUB.begin(); 00747 typename std::vector<FLOAT>::iterator chLB = SIT_chLB.begin(); 00748 typename std::vector<FLOAT>::iterator norm = SIT_chNorm.begin(); 00749 typename std::vector<FLOAT>::iterator STDmod = seg->STDmod.begin(); 00750 typename std::vector<FLOAT>::iterator UBMod = seg->upperBoundMod.begin(); 00751 typename std::vector<FLOAT>::iterator LBMod = seg->lowerBoundMod.begin(); 00752 00753 std::ofstream outfile1(SIT_LOG_FILE,std::ios::app); 00754 00755 for(unsigned int i = 0; i < seg->dim; i++, ++channelMap, 00756 ++initMean, ++initStd, ++chUB, ++chLB, ++norm, 00757 ++STDmod, ++UBMod, ++LBMod) 00758 { 00759 const unsigned int cmap = *channelMap; 00760 const FLOAT covMean = cov->mean[cmap]; 00761 const FLOAT covBias = cov->bias[cmap]; 00762 00763 // Set mean value on this channel from covHolder 00764 *initMean = covMean / covBias; 00765 // Set standard deviation on this channel from covHolder 00766 *initStd = (cov->STD[cmap] * (1/covBias)) * (*STDmod); 00767 // Set upperBound on this channel from covHolder 00768 *chUB = covMean / covBias + (*UBMod); 00769 // Set lowerBount on this channel from covHolder 00770 *chLB = covMean / covBias - (*LBMod); 00771 // set the norm from this channel from covHolder (in feature.conf) 00772 *norm = cov->norm[cmap]; 00773 if(SIT_useLog == true) 00774 { 00775 outfile1 << "Setting channel segHolder " << seg->baseID 00776 << " via covHolder " << cov->baseID 00777 << " - Matching " << seg->featureName[i] 00778 << " To " << cov->featureName[cmap] 00779 << "\t- Value: " << covMean 00780 << " STD: " << cov->STD[cmap] 00781 << " Bias: " << covBias 00782 << "\n"; 00783 } 00784 } 00785 00786 outfile1.close(); 00787 00788 00789 SIT_chAdapt = seg->channelAdapt; 00790 // reset the frame to the center 00791 SITsetFrame(&seg->imageSizeX,&seg->imageSizeY); 00792 // where should the target appear? 00793 seg->expectedX = cov->posX; seg->expectedY = cov->posY; 00794 seg->expectedXmin = cov->minX; seg->expectedYmin = cov->minY; 00795 seg->expectedXmax = cov->maxX; seg->expectedYmax = cov->maxY; 00796 00797 SITsetExpectedTargetPosition(cov->posX, cov->posY, cov->maxX, 00798 cov->maxY, cov->minX, cov->minY); 00799 00800 // reset some values we need to reset when uploading new sig. 00801 SIT_thresh = 1; 00802 SIT_didTrackColor = true; 00803 SIT_resetColor = true; 00804 SIT_LOTcount = 0; 00805 SIT_totalLifeSpan = 0; 00806 SIT_lifeSpan = 0; 00807 seg->LOTcount = SIT_LOTcount; 00808 seg->totalLifeSpan = SIT_totalLifeSpan; 00809 seg->lifeSpan = SIT_lifeSpan; 00810 00811 SIT_segment.SIsetAvg(ERRINTERVAL); 00812 SIT_segment.SIresetAvg(); 00813 SIT_segment.SIsetVal(SIT_initMean,SIT_initStd); 00814 if(SIT_useLog == true) 00815 { 00816 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00817 outfile << "FRAME " << SIT_frameNumber << " INIT " << "\t"; 00818 typename std::vector<FLOAT>::iterator imean = SIT_initMean.begin(); 00819 typename std::vector<FLOAT>::iterator istd = SIT_initStd.begin(); 00820 while(imean != SIT_initMean.end()) 00821 { 00822 outfile << *imean << " +/- (" << *istd << ")\t"; 00823 ++imean; ++istd; 00824 } 00825 outfile << "\n"; 00826 outfile.close(); 00827 } 00828 } 00829 00830 /*********************************************************************/ 00831 00832 template SIT_TEMPLATE_CLASS 00833 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetTrackSignature( 00834 segHolder<FLOAT,INT,SIT_channels> *seg) 00835 { 00836 SITgetBlobPosition(&(seg->posX),&(seg->posY)); 00837 SITgetMinMaxBoundry(&(seg->minX),&(seg->maxX),&(seg->minY),&(seg->maxY)); 00838 SITgetAdaptiveChannelVals(&(seg->mean),&(seg->STD)); 00839 SITgetBlobAttrition(&(seg->blobNumber),&(seg->killedBlobs)); 00840 SITgetLifeSpans(&(seg->totalLifeSpan),&(seg->lifeSpan)); 00841 seg->mass = (unsigned int)ceil(SITgetMass()); 00842 seg->LOT = SITreturnLOT(); 00843 seg->LOTtype = SITreturnLOTtype(); 00844 seg->LOTtypeName = SITreturnLOTtypeName(); 00845 seg->LOTcount = SITgetLOTcount(); 00846 seg->LOTandReset = SIT_LOTandRESET; 00847 seg->boundaryX = SIT_xBound * SIT_GLOBAL_DEC; 00848 seg->boundaryY = SIT_yBound * SIT_GLOBAL_DEC; 00849 } 00850 00851 /*********************************************************************/ 00852 template SIT_TEMPLATE_CLASS 00853 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetTrackColor( 00854 typename std::vector<FLOAT> color, 00855 typename std::vector<FLOAT> std, 00856 typename std::vector<FLOAT> norm, 00857 typename std::vector<FLOAT> adapt, 00858 typename std::vector<FLOAT> upperBound, 00859 typename std::vector<FLOAT> lowerBound, 00860 bool resetColor, 00861 bool resetCandidates) 00862 { 00863 // make sure that all our contaners are the same size 00864 ASSERT(color.size() == std.size()); 00865 ASSERT(std.size() == norm.size()); 00866 ASSERT(norm.size() == adapt.size()); 00867 ASSERT(adapt.size() == upperBound.size()); 00868 ASSERT(upperBound.size() == lowerBound.size()); 00869 00870 // set initial tracking parameters 00871 SIT_thresh = 1; 00872 SIT_initMean = color; 00873 SIT_initStd = std; 00874 SIT_chNorm = norm; 00875 SIT_chAdapt = adapt; 00876 SIT_chUB = upperBound; 00877 SIT_chLB = lowerBound; 00878 SIT_didTrackColor = true; 00879 SIT_totalLifeSpan = 0; 00880 SIT_lifeSpan = 0; 00881 SIT_LOTcount = 0; 00882 SIT_segment.SIsetAvg(ERRINTERVAL); 00883 SIT_segment.SIresetAvg(); 00884 SIT_segment.SIsetVal(SIT_initMean,SIT_initStd); 00885 00886 if(SIT_useLog == true) 00887 { 00888 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00889 outfile << "FRAME " << SIT_frameNumber << " INIT " << "\t"; 00890 typename std::vector<FLOAT>::iterator imean = SIT_initMean.begin(); 00891 typename std::vector<FLOAT>::iterator istd = SIT_initStd.begin(); 00892 while(imean != SIT_initMean.end()) 00893 { 00894 outfile << *imean << " +/- (" << *istd << ")\t"; 00895 ++imean; ++istd; 00896 } 00897 outfile << "\n"; 00898 outfile.close(); 00899 } 00900 00901 00902 SIT_resetColor = resetColor; 00903 if(resetCandidates == true) 00904 SIT_segment.SIresetCandidates(true); 00905 } 00906 00907 00908 /*********************************************************************/ 00909 00910 template SIT_TEMPLATE_CLASS 00911 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetFrame(unsigned short *x, 00912 unsigned short *y) 00913 { 00914 int xx = *x / SIT_GLOBAL_DEC; int yy = *y / SIT_GLOBAL_DEC; 00915 SIT_segment.SIsetFrame(&xx,&yy); 00916 SIT_x_center = xx/2; 00917 SIT_y_center = yy/2; 00918 SIT_centerX = SIT_x_center; 00919 SIT_centerY = SIT_y_center; 00920 } 00921 00922 /*********************************************************************/ 00923 00924 template SIT_TEMPLATE_CLASS 00925 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetUseSmoothing(bool smoothing, FLOAT alpha) 00926 { 00927 SIT_useSmoothing = smoothing; 00928 SIT_smoothingAlpha = alpha; 00929 SIT_didSmoothing = false; 00930 } 00931 00932 /*********************************************************************/ 00933 template SIT_TEMPLATE_CLASS 00934 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetExpectedTargetPosition( 00935 const unsigned short posX, 00936 const unsigned short posY, 00937 const unsigned short maxX, 00938 const unsigned short maxY, 00939 const unsigned short minX, 00940 const unsigned short minY) 00941 { 00942 SIT_expectedX = posX / SIT_GLOBAL_DEC; 00943 SIT_expectedY = posY / SIT_GLOBAL_DEC; 00944 SIT_expectedXmax = maxX / SIT_GLOBAL_DEC; 00945 SIT_expectedYmax = maxY / SIT_GLOBAL_DEC; 00946 SIT_expectedXmin = minX / SIT_GLOBAL_DEC; 00947 SIT_expectedYmin = minY / SIT_GLOBAL_DEC; 00948 SIT_useExpectedLocation = true; 00949 } 00950 00951 /*********************************************************************/ 00952 template SIT_TEMPLATE_CLASS 00953 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetExpectedTargetPosition( 00954 unsigned short *posX, 00955 unsigned short *posY, 00956 unsigned short *maxX, 00957 unsigned short *maxY, 00958 unsigned short *minX, 00959 unsigned short *minY, 00960 bool *isSet) const 00961 { 00962 unsigned short pX = SIT_expectedX * SIT_GLOBAL_DEC; 00963 unsigned short pY = SIT_expectedY * SIT_GLOBAL_DEC; 00964 unsigned short XM = SIT_expectedXmax * SIT_GLOBAL_DEC; 00965 unsigned short YM = SIT_expectedYmax * SIT_GLOBAL_DEC; 00966 unsigned short xM = SIT_expectedXmin * SIT_GLOBAL_DEC; 00967 unsigned short yM = SIT_expectedYmin * SIT_GLOBAL_DEC; 00968 bool is = SIT_useExpectedLocation; 00969 00970 *posX = pX; *posY = pY; 00971 *maxX = XM; *maxY = YM; 00972 *minX = xM; *minY = yM; 00973 00974 *isSet = is; 00975 } 00976 00977 /*********************************************************************/ 00978 template SIT_TEMPLATE_CLASS 00979 void segmentImageTrackMC<SIT_TEMPLATE>::SITunsetExpectedTargetPosition() 00980 { 00981 SIT_useExpectedLocation = false; 00982 } 00983 00984 /*********************************************************************/ 00985 template SIT_TEMPLATE_CLASS 00986 bool segmentImageTrackMC<SIT_TEMPLATE>::SITintersection( 00987 const covHolder<double> *cov, 00988 const int boundX, 00989 const int boundY) const 00990 { 00991 int maxX,maxY,minX,minY; 00992 bool Xok = false; 00993 bool Yok = false; 00994 00995 // what are the bounds of this object? 00996 // store and multiply by decimation reduction factor 00997 if(SIT_lifeSpan > 1) 00998 { 00999 minX = (signed)SIT_minX*SIT_GLOBAL_DEC; 01000 maxX = (signed)SIT_maxX*SIT_GLOBAL_DEC; 01001 minY = (signed)SIT_minY*SIT_GLOBAL_DEC; 01002 maxY = (signed)SIT_maxY*SIT_GLOBAL_DEC; 01003 } 01004 else 01005 { 01006 minX = (signed)SIT_expectedXmin*SIT_GLOBAL_DEC; 01007 maxX = (signed)SIT_expectedXmax*SIT_GLOBAL_DEC; 01008 minY = (signed)SIT_expectedYmin*SIT_GLOBAL_DEC; 01009 maxY = (signed)SIT_expectedYmax*SIT_GLOBAL_DEC; 01010 } 01011 01012 // check for intersection with other objects 01013 if((((signed)cov->minX < minX-boundX) && 01014 ((signed)cov->maxX < minX-boundX)) || 01015 (((signed)cov->minX > maxX+boundX) && 01016 ((signed)cov->maxX > maxX+boundX))) 01017 { 01018 Xok = true; 01019 } 01020 01021 if((((signed)cov->minY < minY-boundY) && 01022 ((signed)cov->maxY < minY-boundY)) || 01023 (((signed)cov->minY > maxY+boundY) && 01024 ((signed)cov->maxY > maxY+boundY))) 01025 { 01026 Yok = true; 01027 } 01028 01029 if((Xok == false) && (Yok == false)) 01030 { 01031 return false; 01032 } 01033 // else 01034 return true; 01035 } 01036 01037 /*********************************************************************/ 01038 template SIT_TEMPLATE_CLASS 01039 void segmentImageTrackMC<SIT_TEMPLATE>::SITpercentOverlap( 01040 const segHolder<FLOAT,INT,SIT_channels> *seg, 01041 FLOAT *overlap, 01042 FLOAT *thisArea, 01043 FLOAT *otherArea) const 01044 { 01045 const int minX = (signed)SIT_minX*SIT_GLOBAL_DEC; 01046 const int maxX = (signed)SIT_maxX*SIT_GLOBAL_DEC; 01047 const int minY = (signed)SIT_minY*SIT_GLOBAL_DEC; 01048 const int maxY = (signed)SIT_maxY*SIT_GLOBAL_DEC; 01049 01050 // Find which parts overlap, if any 01051 bool olapX = false; 01052 bool olapY = false; 01053 bool sMinX = false; bool sMaxX = false; 01054 bool sMinY = false; bool sMaxY = false; 01055 01056 // What are the intersections? 01057 if((seg->minX > minX) && (seg->minX < maxX)) 01058 { sMinX = true; olapX = true;} 01059 if((seg->maxX > minX) && (seg->maxX < maxX)) 01060 { sMaxX = true; olapX = true;} 01061 if((seg->minY > minY) && (seg->minY < maxY)) 01062 { sMinY = true; olapY = true;} 01063 if((seg->maxY > minY) && (seg->maxY < maxY)) 01064 { sMaxY = true; olapY = true;} 01065 01066 // If intersection, computer percent overlap 01067 // else no intersection, return 0 01068 if(olapX && olapY) 01069 { 01070 // else find the area of the overlap, then the percentage 01071 01072 const FLOAT slenX = seg->maxX - seg->minX; 01073 const FLOAT slenY = seg->maxY - seg->minY; 01074 *otherArea = slenX*slenY; 01075 01076 const FLOAT lenX = maxX - minX; 01077 const FLOAT lenY = maxY - minY; 01078 *thisArea = lenX*lenY; 01079 01080 // average the area. This forces the overlap to be a function 01081 // of the similarity if the two targets sizes. 01082 01083 const FLOAT avgArea = ((*thisArea)+(*otherArea))/2; 01084 01085 FLOAT diffX = 0.0F; FLOAT diffY = 0.0F; 01086 if( (sMinX == true) && (sMaxX == false)) 01087 diffX = maxX - seg->minX; 01088 else if((sMinX == false) && (sMaxX == true)) 01089 diffX = seg->maxX - minX; 01090 else 01091 diffX = slenX; 01092 01093 if( (sMinY == true) && (sMaxY == false)) 01094 diffY = maxY - seg->minY; 01095 else if((sMinY == false) && (sMaxY == true)) 01096 diffY = seg->maxY - minY; 01097 else 01098 diffY = slenY; 01099 01100 const FLOAT oarea = diffX*diffY; 01101 *overlap = oarea/avgArea; 01102 return; 01103 } 01104 01105 *overlap = 0.0F; 01106 return; 01107 } 01108 01109 01110 01111 /*********************************************************************/ 01112 template SIT_TEMPLATE_CLASS 01113 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleCandidateBandPass(bool toggle) 01114 { 01115 SIT_segment.SItoggleCandidateBandPass(toggle); 01116 } 01117 /*********************************************************************/ 01118 template SIT_TEMPLATE_CLASS 01119 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleColorAdaptation(bool toggle) 01120 { 01121 SIT_useColorAdaptation = toggle; 01122 } 01123 01124 /*********************************************************************/ 01125 template SIT_TEMPLATE_CLASS 01126 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleHardBounds(bool toggle) 01127 { 01128 SIT_useHardBounds = toggle; 01129 } 01130 01131 /*********************************************************************/ 01132 template SIT_TEMPLATE_CLASS 01133 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetFrameNumber(unsigned long frame) 01134 { 01135 SIT_frameNumber = frame; 01136 } 01137 01138 /*********************************************************************/ 01139 template SIT_TEMPLATE_CLASS 01140 void segmentImageTrackMC<SIT_TEMPLATE>::SITeditBlobs(bool toggle) 01141 { 01142 SIT_editBlobs = toggle; 01143 } 01144 01145 /*********************************************************************/ 01146 // MAIN METHOD 01147 /*********************************************************************/ 01148 01149 /* This is a basic tracker access method that tracks on one image at a time */ 01150 /* this one is designed to work with any Pixels pixel */ 01151 01152 template SIT_TEMPLATE_CLASS 01153 void segmentImageTrackMC<SIT_TEMPLATE>::SITtrackImage 01154 (Image<PixH2SV2<FLOAT> > &input, 01155 Image<PixRGB<byte> > *output) 01156 { 01157 // Assert that parameters have been set up before starting 01158 ASSERT(SIT_didCircleColor == true); 01159 ASSERT(SIT_didBoxColor == true); 01160 ASSERT(SIT_didTrackColor == true); 01161 01162 SIT_imageHold = output; 01163 01164 // decimate input image twice to speed things up 01165 if(SIT_GLOBAL_DEC >= 2) 01166 input = decXY(input); 01167 if(SIT_GLOBAL_DEC >= 4) 01168 input = decXY(input); 01169 if(SIT_GLOBAL_DEC >= 8) 01170 input = decXY(input); 01171 01172 Image<FLOAT> timage; 01173 timage.resize(input.getWidth(),input.getHeight(),true); 01174 SIT_chans.resize(SIT_channels,timage); 01175 for(unsigned int i = 0; i < SIT_channels; i++) 01176 { 01177 typename Image<FLOAT>::iterator iSIT_chans = SIT_chans[i].beginw(); 01178 for(typename Image<PixH2SV2<FLOAT> >::iterator 01179 iinput = input.beginw(); 01180 iinput != input.endw(); ++iinput, ++iSIT_chans) 01181 { 01182 *iSIT_chans = iinput->p[i]; 01183 } 01184 } 01185 01186 if(SIT_useSmoothing) 01187 SITsmoothImage(&SIT_chans); 01188 01189 SITrunTrack(SIT_imageHold,&SIT_chans); 01190 } 01191 01192 /*********************************************************************/ 01193 01194 template SIT_TEMPLATE_CLASS 01195 void segmentImageTrackMC<SIT_TEMPLATE>::SITsmoothImage(typename 01196 std::vector<Image<FLOAT> > *input) 01197 { 01198 if(SIT_didSmoothing == false) 01199 { 01200 Image<FLOAT> timage; 01201 timage.resize(input->at(0).getWidth(),input->at(0).getHeight(),true); 01202 SIT_fimaLast.resize(input->size(),timage); 01203 } 01204 01205 typename std::vector<Image<FLOAT> >::iterator iinput = input->begin(); 01206 typename std::vector<Image<FLOAT> >::iterator ifima = SIT_fimaLast.begin(); 01207 while(iinput != input->end()) 01208 { 01209 if(SIT_didSmoothing) 01210 { 01211 *ifima = (*iinput + ((*ifima) * SIT_smoothingAlpha))/ 01212 (1+SIT_smoothingAlpha); 01213 } 01214 else 01215 { 01216 *ifima = *iinput; 01217 SIT_didSmoothing = true; 01218 } 01219 ++iinput; ++ifima; 01220 } 01221 input = &SIT_fimaLast; 01222 } 01223 01224 /*********************************************************************/ 01225 01226 template SIT_TEMPLATE_CLASS 01227 void segmentImageTrackMC<SIT_TEMPLATE>::SITuseLog(bool useLog) 01228 { 01229 SIT_useLog = useLog; 01230 } 01231 01232 /*********************************************************************/ 01233 01234 template SIT_TEMPLATE_CLASS 01235 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleDrawing(bool targetImage, 01236 bool colorAdaptImage) 01237 { 01238 SIT_drawTargetImage = targetImage; 01239 SIT_drawColorAdaptImage = colorAdaptImage; 01240 } 01241 01242 /*********************************************************************/ 01243 01244 template SIT_TEMPLATE_CLASS 01245 void segmentImageTrackMC<SIT_TEMPLATE>::SITrunTrack( 01246 Image<PixRGB<byte> > *image, 01247 typename 01248 std::vector<Image<FLOAT> > *input) 01249 { 01250 SIT_LOTandRESET = false; 01251 SIT_didColorBars = false; 01252 // (1) segment the decimated image 01253 SIT_segment.SIsegment(image,input); 01254 LDEBUG("SEGMENTED"); 01255 // (2) get center of mass for blobs 01256 SIT_segment.SIcalcMassCenter(); 01257 LDEBUG("CALCULATED MASS CENTER"); 01258 // (3) edit blobs, weed out all the non-hackers who are not 01259 // fit to carry a rifle 01260 if(SIT_editBlobs) 01261 SITanalyzeBlobs(); 01262 LDEBUG("BLOBS ANALYZED"); 01263 // (4) merge all remaining blobs 01264 SITmergeBlobs(); 01265 LDEBUG("BLOBS MERGED"); 01266 // (5) apply adaptive color thesholding 01267 SITcolorAdaptation(); 01268 LDEBUG("COLORS ADAPTED"); 01269 } 01270 01271 /*********************************************************************/ 01272 // DATA RETURN METHODS 01273 /*********************************************************************/ 01274 01275 template SIT_TEMPLATE_CLASS 01276 bool segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOT() 01277 { 01278 return SIT_LOT; 01279 } 01280 01281 /*********************************************************************/ 01282 01283 template SIT_TEMPLATE_CLASS 01284 unsigned int segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOTtype() 01285 { 01286 return SIT_LOTtype; 01287 } 01288 01289 /*********************************************************************/ 01290 01291 template SIT_TEMPLATE_CLASS 01292 std::string segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOTtypeName() 01293 { 01294 return SIT_LOTtypeName; 01295 } 01296 01297 /*********************************************************************/ 01298 01299 template SIT_TEMPLATE_CLASS 01300 Image<long> segmentImageTrackMC<SIT_TEMPLATE>::SITreturnBlobMap() 01301 { 01302 return SIT_segment.SIreturnBlobs(); 01303 } 01304 01305 /*********************************************************************/ 01306 01307 template SIT_TEMPLATE_CLASS 01308 Image<byte> segmentImageTrackMC<SIT_TEMPLATE>::SITreturnCandidateImage() 01309 { 01310 return SIT_segment.SIreturnNormalizedCandidates(); 01311 } 01312 01313 /*********************************************************************/ 01314 01315 template SIT_TEMPLATE_CLASS 01316 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosition(unsigned short *x, 01317 unsigned short *y) 01318 { 01319 SIT_centerXmod = SIT_centerX*SIT_GLOBAL_DEC; 01320 SIT_centerYmod = SIT_centerY*SIT_GLOBAL_DEC; 01321 *x = SIT_centerXmod; 01322 *y = SIT_centerYmod; 01323 } 01324 /*********************************************************************/ 01325 01326 template SIT_TEMPLATE_CLASS 01327 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetMinMaxBoundry( 01328 unsigned short *minX, 01329 unsigned short *maxX, 01330 unsigned short *minY, 01331 unsigned short *maxY) 01332 { 01333 SIT_minXmod = SIT_minX*SIT_GLOBAL_DEC; 01334 SIT_maxXmod = SIT_maxX*SIT_GLOBAL_DEC; 01335 SIT_minYmod = SIT_minY*SIT_GLOBAL_DEC; 01336 SIT_maxYmod = SIT_maxY*SIT_GLOBAL_DEC; 01337 *minX = SIT_minXmod; 01338 *maxX = SIT_maxXmod; 01339 *minY = SIT_minYmod; 01340 *maxY = SIT_maxYmod; 01341 } 01342 01343 /*********************************************************************/ 01344 01345 template SIT_TEMPLATE_CLASS 01346 Image<PixRGB<byte> > segmentImageTrackMC<SIT_TEMPLATE>::SITgetColorBars() 01347 { 01348 return SIT_auxHold; 01349 } 01350 01351 /********************************************************************/ 01352 01353 /* commented this out because SIT_MASS is not defined (or even declared) 01354 anywhere, so we get an error with g++ 3.4.1 */ 01355 template SIT_TEMPLATE_CLASS 01356 FLOAT segmentImageTrackMC<SIT_TEMPLATE>::SITgetMass() 01357 { 01358 return SIT_mass; 01359 } 01360 01361 /********************************************************************/ 01362 01363 template SIT_TEMPLATE_CLASS 01364 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobAttrition( 01365 INT *totalBlobs, 01366 INT *killedBlobs) 01367 { 01368 *totalBlobs = SIT_totalBlobs; 01369 *killedBlobs = SIT_killedBlobs; 01370 } 01371 /********************************************************************/ 01372 01373 template SIT_TEMPLATE_CLASS 01374 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetLifeSpans( 01375 unsigned long *totalLifeSpan, 01376 unsigned long *lifeSpan) 01377 { 01378 *totalLifeSpan = SIT_totalLifeSpan; 01379 *lifeSpan = SIT_lifeSpan; 01380 } 01381 01382 /********************************************************************/ 01383 01384 template SIT_TEMPLATE_CLASS 01385 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetAdaptiveChannelVals( 01386 typename std::vector<FLOAT> *mean, 01387 typename std::vector<FLOAT> *std) 01388 { 01389 *mean = SIT_chMean1; 01390 *std = SIT_chStd1; 01391 } 01392 01393 /********************************************************************/ 01394 01395 template SIT_TEMPLATE_CLASS 01396 unsigned int segmentImageTrackMC<SIT_TEMPLATE>::SITgetLOTcount() 01397 { 01398 return SIT_LOTcount; 01399 } 01400 01401 /********************************************************************/ 01402 01403 template SIT_TEMPLATE_CLASS 01404 INT segmentImageTrackMC<SIT_TEMPLATE>::SITnumberBlobs() 01405 { 01406 return SIT_segment.SInumberBlobs(); 01407 } 01408 01409 /********************************************************************/ 01410 01411 template SIT_TEMPLATE_CLASS 01412 unsigned short 01413 segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobReasonForKillCode(INT blob) 01414 { 01415 return SIT_reasonForKillCode[blob]; 01416 } 01417 01418 /********************************************************************/ 01419 01420 template SIT_TEMPLATE_CLASS 01421 std::string segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobReasonForKill(INT blob) 01422 { 01423 return SIT_reasonForKill[blob]; 01424 } 01425 01426 /********************************************************************/ 01427 01428 template SIT_TEMPLATE_CLASS 01429 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobMass(INT blob) 01430 { 01431 return SIT_segment.SIgetMass(blob); 01432 } 01433 01434 /********************************************************************/ 01435 01436 template SIT_TEMPLATE_CLASS 01437 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosX(INT blob) 01438 { 01439 return (INT)floor(SIT_segment.SIgetCenterX(blob)) * SIT_GLOBAL_DEC; 01440 } 01441 01442 /********************************************************************/ 01443 01444 template SIT_TEMPLATE_CLASS 01445 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosY(INT blob) 01446 { 01447 return (INT)floor(SIT_segment.SIgetCenterY(blob)) * SIT_GLOBAL_DEC; 01448 } 01449 01450 01451 /*********************************************************************/ 01452 // DRAWING METHODS 01453 /*********************************************************************/ 01454 01455 template SIT_TEMPLATE_CLASS 01456 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobTrack(INT i) 01457 { 01458 // find boundaries of this blob 01459 unsigned int tt = SIT_segment.SIgetYmin(i); 01460 unsigned int bb = SIT_segment.SIgetYmax(i); 01461 unsigned int ll = SIT_segment.SIgetXmin(i); 01462 unsigned int rr = SIT_segment.SIgetXmax(i); 01463 01464 // draw bounding box for this blob 01465 // Note: box must be of height > 1 and width > 1 01466 if((bb != tt) && (ll != rr)) 01467 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(tt*SIT_GLOBAL_DEC, 01468 ll*SIT_GLOBAL_DEC, 01469 bb*SIT_GLOBAL_DEC, 01470 rr*SIT_GLOBAL_DEC), 01471 PixRGB<byte>(SIT_boxRed, 01472 SIT_boxGreen, 01473 SIT_boxBlue),1); 01474 01475 // draw target circle for this blob 01476 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_segment.SIgetCenterX(i) 01477 *SIT_GLOBAL_DEC 01478 ,(int)SIT_segment.SIgetCenterY(i) 01479 *SIT_GLOBAL_DEC) 01480 ,(int)sqrt((float)SIT_segment.SIgetMass(i)), 01481 PixRGB<byte>(SIT_boxRed, 01482 SIT_boxGreen, 01483 SIT_boxBlue),2); 01484 01485 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_segment.SIgetCenterX(i) 01486 *SIT_GLOBAL_DEC 01487 ,(int)SIT_segment.SIgetCenterY(i) 01488 *SIT_GLOBAL_DEC) 01489 ,2,PixRGB<byte>(255,0,0),2); 01490 } 01491 01492 /*********************************************************************/ 01493 01494 template SIT_TEMPLATE_CLASS 01495 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobTrackMerged() 01496 { 01497 01498 if((SIT_minY != SIT_maxY) && (SIT_minX != SIT_maxX)) 01499 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(SIT_minY*SIT_GLOBAL_DEC, 01500 SIT_minX*SIT_GLOBAL_DEC, 01501 SIT_maxY*SIT_GLOBAL_DEC, 01502 SIT_maxX*SIT_GLOBAL_DEC), 01503 PixRGB<byte>(SIT_bigBoxRed, 01504 SIT_bigBoxGreen, 01505 SIT_bigBoxBlue),2); 01506 01507 // draw target circle for this blob 01508 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_centerX*SIT_GLOBAL_DEC, 01509 (int)SIT_centerY*SIT_GLOBAL_DEC), 01510 (int)sqrt(SIT_mass), 01511 PixRGB<byte>(SIT_bigBoxRed, 01512 SIT_bigBoxGreen, 01513 SIT_bigBoxBlue),2); 01514 01515 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_centerX*SIT_GLOBAL_DEC,(int)SIT_centerY*SIT_GLOBAL_DEC) 01516 ,2,PixRGB<byte>(255,0,0),2); 01517 } 01518 01519 01520 01521 /*********************************************************************/ 01522 template SIT_TEMPLATE_CLASS 01523 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobBox(INT i) 01524 { 01525 // find boundaries of this blob 01526 unsigned int tt = SIT_segment.SIgetYmin(i); 01527 unsigned int bb = SIT_segment.SIgetYmax(i); 01528 unsigned int ll = SIT_segment.SIgetXmin(i); 01529 unsigned int rr = SIT_segment.SIgetXmax(i); 01530 01531 01532 // draw bounding box for this blob 01533 // Note: box must be of height > 1 and width > 1 01534 if((bb != tt) && (ll != rr)) 01535 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(tt*SIT_GLOBAL_DEC, 01536 ll*SIT_GLOBAL_DEC, 01537 bb*SIT_GLOBAL_DEC, 01538 rr*SIT_GLOBAL_DEC), 01539 PixRGB<byte>(SIT_circleRed, 01540 SIT_circleGreen, 01541 SIT_circleBlue),1); 01542 } 01543 01544 /*********************************************************************/ 01545 template SIT_TEMPLATE_CLASS 01546 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawHistoValues( 01547 typename std::vector<FLOAT> *mean, 01548 typename std::vector<FLOAT> *std, 01549 typename std::vector<FLOAT> *lb, 01550 typename std::vector<FLOAT> *ub, 01551 typename std::vector<FLOAT> *norm, 01552 bool LOT) 01553 { 01554 SIT_didColorBars = true; 01555 01556 unsigned int minWidth = SIT_barWidth+SIT_barSpace*mean->size(); 01557 if((unsigned)SIT_auxHold.getWidth() < minWidth) 01558 SIT_auxHold.resize(minWidth,(int)SIT_histoHeight,true); 01559 // draw background grid in HSV bar graph 01560 if(LOT == false) 01561 drawGrid(SIT_auxHold, 25,25,1,1,PixRGB<byte>(100,100,100)); 01562 else 01563 drawGrid(SIT_auxHold, 25,25,1,1,PixRGB<byte>(200,100,100)); 01564 01565 /* typename std::vector<FLOAT>::iterator imean = mean->begin(); 01566 typename std::vector<FLOAT>::iterator istd = std->begin(); 01567 typename std::vector<FLOAT>::iterator ilb = lb->begin(); 01568 typename std::vector<FLOAT>::iterator iub = ub->begin(); 01569 typename std::vector<FLOAT>::iterator inorm = norm->begin(); 01570 */ 01571 //unsigned int start = SIT_barSpace; 01572 //unsigned int end = SIT_barWidth + start; 01573 01574 /* 01575 while(imean != mean->end()) 01576 { 01577 if(*inorm != 0) 01578 { 01579 FLOAT mean = (*imean/(*inorm)); 01580 FLOAT std = (*istd/(*inorm)); 01581 FLOAT ub = (*iub/(*inorm)); 01582 FLOAT lb = (*ilb/(*inorm)); 01583 01584 // draw HSV mean value bars as a bunch of rectangles 01585 drawRectEZ(SIT_auxHold, Rectangle::tlbrI(0,start,(int)(mean* 01586 SIT_histoHeight),end), 01587 PixRGB<byte>(0,0,255),1); 01588 01589 // draw standard deviation bars 01590 01591 if((((mean-std)*SIT_histoHeight) > 0) 01592 && (((mean+std)*SIT_histoHeight) < SIT_auxHold.getHeight())) 01593 drawRectEZ(SIT_auxHold, Rectangle::tlbrI((int)((mean-std)*SIT_histoHeight) 01594 ,start+2, 01595 (int)((mean+std)*SIT_histoHeight) 01596 ,end-2), 01597 PixRGB<byte>(255,255,0),1); 01598 01599 01600 drawRectEZ(SIT_auxHold, Rectangle::tlbrI((int)(lb*(SIT_histoHeight-1)) 01601 ,(signed)start-3, 01602 (int)(ub*(SIT_histoHeight-1)) 01603 ,(signed)start-1), 01604 PixRGB<byte>(255,0,0),1); 01605 01606 01607 ++imean, ++istd, ++ilb, ++iub, ++inorm; 01608 start = end + SIT_barSpace; 01609 end = start + SIT_barWidth; 01610 } 01611 } 01612 */ 01613 } 01614 01615 #undef SIT_TEMPLATE_CLASS 01616 #undef SIT_TEMPLATE 01617 01618 template class segmentImageTrackMC<float, unsigned int, 3>; 01619 template class segmentImageTrackMC<float, unsigned int, 4>; 01620 01621 #endif