00001 /*!@file VFAT/segmentImageTrackMC.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/segmentImageTrackMC.C $ 00035 // $Id: segmentImageTrackMC.C 9412 2008-03-10 23:10:15Z farhan $ 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 SEGMENTIMAGETRACKMC_C_DEFINED 00049 #define SEGMENTIMAGETRACKMC_C_DEFINED 00050 00051 #include "Util/Assert.H" 00052 #include "VFAT/segmentImageTrackMC.H" 00053 #include "Image/DrawOps.H" 00054 #include "Raster/Raster.H" 00055 00056 #include <climits> 00057 #include <cstdio> 00058 #include <cstdlib> 00059 #include <fstream> 00060 #include <iostream> 00061 #include <time.h> 00062 00063 00064 //! maximum lose of tracks before color is reset 00065 #define LOTMAX 5 00066 00067 //! How many iteration to calculate over for movement statistics 00068 #define ERRINTERVAL 5 00069 00070 //! decimation size reduction factor 00071 #define DEC 4 00072 00073 //! Width of channel bars 00074 #define BARWIDTH 10 00075 00076 //! spacing between channel histo bars 00077 #define BARSPACE 5 00078 00079 //! histogram height 00080 #define HISTOHEIGHT 450.0F 00081 00082 /*********************************************************************/ 00083 // compute color adaptation 00084 00085 template SIT_TEMPLATE_CLASS 00086 void segmentImageTrackMC<SIT_TEMPLATE>::SITcolorAdaptation() 00087 { 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 if(SIT_drawColorAdaptImage == true) 00187 SITdrawHistoValues(&SIT_chMean1,&SIT_chStd1, 00188 &SIT_chUB,&SIT_chLB,&SIT_chNorm,false); 00189 // (5.b) if adaptive thresholding is turned on, adjust color 00190 // by standard deviation of color. As such each blobs color will 00191 // determin the new tracking color. 00192 istd1 = SIT_chStd1.begin(); 00193 ilb = SIT_chLB.begin(); 00194 iub = SIT_chUB.begin(); 00195 00196 typename std::vector<FLOAT>::iterator iadapt = SIT_chAdapt.begin(); 00197 typename std::vector<FLOAT>::iterator instd = SIT_chNSTD.begin(); 00198 00199 for(imean1 = SIT_chMean1.begin(); imean1 != SIT_chMean1.end(); ++imean1, 00200 ++istd1, ++iub, ++ilb, ++instd) 00201 { 00202 00203 *instd = *istd1*(*iadapt); 00204 /* 00205 if(*imean1 > *iub) 00206 { 00207 *imean1 = *iub; 00208 } 00209 else if(*imean1 < *ilb) 00210 { 00211 *imean1 = *ilb; 00212 } 00213 */ 00214 00215 } 00216 if(SIT_useLog == true) 00217 { 00218 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00219 outfile << "FRAME " << SIT_frameNumber << " ADAPT " << "\t"; 00220 typename std::vector<FLOAT>::iterator instd = SIT_chNSTD.begin(); 00221 for(imean1 = SIT_chMean1.begin(); imean1 != SIT_chMean1.end(); 00222 ++imean1,++instd) 00223 { 00224 outfile << *imean1 << " +/- (" << *instd << ")\t"; 00225 } 00226 outfile << "\n"; 00227 outfile.close(); 00228 } 00229 SIT_segment.SIsetVal(SIT_chMean1,SIT_chNSTD,SIT_chSkew); 00230 } 00231 } 00232 else 00233 { 00234 LINFO("COLOR RESET TO USERS"); 00235 SIT_resetColor = false; 00236 } 00237 } 00238 00239 /*********************************************************************/ 00240 template SIT_TEMPLATE_CLASS 00241 void segmentImageTrackMC<SIT_TEMPLATE>::SITresetColor() 00242 { 00243 SIT_segment.SIresetAvg(); 00244 SIT_segment.SIsetVal(SIT_initMean,SIT_initStd,SIT_chSkew); 00245 00246 if(SIT_useLog == true) 00247 { 00248 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00249 outfile << "FRAME " << SIT_frameNumber << " RESET " << "\t"; 00250 typename std::vector<FLOAT>::iterator imean = SIT_initMean.begin(); 00251 typename std::vector<FLOAT>::iterator istd = SIT_initStd.begin(); 00252 while(imean != SIT_initMean.end()) 00253 { 00254 outfile << *imean << " +/- (" << *istd << ")\t"; 00255 ++imean; ++istd; 00256 } 00257 outfile << "\n"; 00258 outfile.close(); 00259 } 00260 00261 SIT_segment.SIresetCandidates(true); 00262 SIT_LOTcount = 0; 00263 SIT_resetColor = true; 00264 SIT_LOTandRESET = true; 00265 } 00266 00267 /*********************************************************************/ 00268 // weed out blobs that suck 00269 00270 template SIT_TEMPLATE_CLASS 00271 void segmentImageTrackMC<SIT_TEMPLATE>::SITanalyzeBlobs() 00272 { 00273 SIT_totalBlobs = SIT_segment.SInumberBlobs(); 00274 SIT_killedBlobs = 0; 00275 00276 // (1.a) We have a loss of track, as such we need to reset some of 00277 // the adaptive parameters. Here we reset the parameter where we 00278 // expect the target to be to a much larger area since we no longer 00279 // can assume its location do to loss of track. 00280 if(SIT_LOT == true) 00281 { 00282 SIT_xBound = SIT_blobProp.BP_LOTbound; 00283 SIT_yBound = SIT_blobProp.BP_LOTbound; 00284 } 00285 else 00286 { 00287 // (1.b) We expect the target to appear close to where we last saw it 00288 // we set a parameter around the last known location. Any blob outside 00289 // this parameter must be predjidist 00290 00291 SIT_xBound = (int)(SIT_blobProp.BP_bound + 00292 (SIT_thresh*SIT_blobProp.BP_softBound)); 00293 SIT_yBound = (int)(SIT_blobProp.BP_bound + 00294 (SIT_thresh*SIT_blobProp.BP_softBound)); 00295 } 00296 00297 std::vector<bool>::iterator softCandidateBlobItr 00298 = SIT_softCandidateBlob.begin(); 00299 std::vector<bool>::iterator candidateBlobItr 00300 = SIT_candidateBlob.begin(); 00301 std::vector<bool>::iterator killedByTrackItr 00302 = SIT_killedByTrack.begin(); 00303 std::vector<std::string>::iterator reasonForKillItr 00304 = SIT_reasonForKill.begin(); 00305 std::vector<unsigned short>::iterator reasonForKillCodeItr 00306 = SIT_reasonForKillCode.begin(); 00307 00308 std::string S1,S2,S3; 00309 char C1[48], C2[48], C3[48]; 00310 // (2) For each blob that the tracker found as a potential target, 00311 // check its properties such as its location in the image vs. 00312 // where we expect the target to be. Also check to make sure that the 00313 // target is geometrically good. That is, make sure its mass, size and 00314 // basic shape conform to our expectations. 00315 for(INT i = 0; i < SIT_totalBlobs; i++, 00316 ++softCandidateBlobItr, ++candidateBlobItr, 00317 ++killedByTrackItr, ++reasonForKillItr, ++reasonForKillCodeItr) 00318 { 00319 *softCandidateBlobItr = true; 00320 *candidateBlobItr = true; 00321 *killedByTrackItr = false; 00322 *reasonForKillCodeItr = 0; 00323 *reasonForKillItr = "(0) Blob OK "; 00324 00325 LDEBUG("[%d] expected x min = %d", 00326 SIT_useExpectedLocation == true, SIT_expectedXmin); 00327 00328 00329 // (3) check if a blobs mass is within constraints. That is 00330 // Make sure the blob is neither too large or to small. If so, we 00331 // don't like it. 00332 if((SIT_segment.SIgetMass(i) < (INT)SIT_blobProp.BP_minMass) 00333 && (SIT_blobProp.BP_checkMass == true)) 00334 { 00335 *candidateBlobItr = false; 00336 *softCandidateBlobItr = false; 00337 *killedByTrackItr = true; 00338 *reasonForKillCodeItr = 1; 00339 SIT_killedBlobs++; 00340 00341 S1 = " Blob Mass Contraints : Min : "; S2 = " < "; 00342 sprintf(C1,"%d",(int)SIT_segment.SIgetMass(i)); 00343 sprintf(C2,"%d",(int)SIT_blobProp.BP_minMass); 00344 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00345 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00346 00347 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00348 } 00349 else if((SIT_segment.SIgetMass(i) > (INT)SIT_blobProp.BP_maxMass) 00350 && (SIT_blobProp.BP_checkMass == true)) 00351 { 00352 00353 *candidateBlobItr = false; 00354 *softCandidateBlobItr = false; 00355 *killedByTrackItr = true; 00356 *reasonForKillCodeItr = 2; 00357 SIT_killedBlobs++; 00358 00359 S1 = " Blob Mass Contraints : Max : "; S2 = " > "; 00360 sprintf(C1,"%d",(int)SIT_segment.SIgetMass(i)); 00361 sprintf(C2,"%d",(int)SIT_blobProp.BP_maxMass); 00362 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00363 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00364 00365 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00366 } 00367 // (4) check that a blob is within our X frame. That is, does 00368 // a blob fall in the image in a place where we would expect it 00369 // for instance close to where we last saw it. 00370 else if((SIT_segment.SIgetCenterX(i) < (SIT_centerX - SIT_xBound)) 00371 && (SIT_blobProp.BP_checkFrameX == true)) 00372 { 00373 *candidateBlobItr = false; 00374 *killedByTrackItr = true; 00375 *reasonForKillCodeItr = 3; 00376 SIT_killedBlobs++; 00377 00378 S1 = " Blob Out of X Frame : Low : "; S2 = " < "; 00379 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00380 sprintf(C2,"%d",(int)(SIT_centerX - SIT_xBound)); 00381 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00382 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00383 00384 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00385 } 00386 else if((SIT_segment.SIgetCenterX(i) > (SIT_centerX + SIT_xBound)) 00387 && (SIT_blobProp.BP_checkFrameX == true)) 00388 { 00389 *candidateBlobItr = false; 00390 *killedByTrackItr = true; 00391 *reasonForKillCodeItr = 4; 00392 SIT_killedBlobs++; 00393 00394 S1 = " Blob Out of X Frame : High : "; S2 = " > "; 00395 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00396 sprintf(C2,"%d",(int)(SIT_centerX + SIT_xBound)); 00397 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00398 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00399 00400 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00401 } 00402 // (5) check that a blob is within our Y frame. That is, does 00403 // a blob fall in the image in a place where we would expect it 00404 // for instance close to where we last saw it. 00405 else if((SIT_segment.SIgetCenterY(i) < (SIT_centerY - SIT_yBound)) 00406 && (SIT_blobProp.BP_checkFrameY == true)) 00407 { 00408 *candidateBlobItr = false; 00409 *killedByTrackItr = true; 00410 *reasonForKillCodeItr = 5; 00411 SIT_killedBlobs++; 00412 00413 S1 = " Blob Out of Y Frame : Low : "; S2 = " < "; 00414 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00415 sprintf(C2,"%d",(int)(SIT_centerY - SIT_yBound)); 00416 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00417 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00418 00419 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00420 } 00421 else if((SIT_segment.SIgetCenterY(i) > (SIT_centerY + SIT_yBound)) 00422 && (SIT_blobProp.BP_checkFrameY == true)) 00423 { 00424 *candidateBlobItr = false; 00425 *killedByTrackItr = true; 00426 *reasonForKillCodeItr = 6; 00427 SIT_killedBlobs++; 00428 00429 S1 = " Blob Out of Y Frame : High : "; S2 = " > "; 00430 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00431 sprintf(C2,"%d",(int)(SIT_centerY + SIT_yBound)); 00432 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00433 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00434 00435 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00436 } 00437 // (6) check that a blob is within our EXPECTED X frame. That is, does 00438 // a blob fall in the image in a place where we would expect it 00439 // for instance close to where we last saw it. 00440 // This is used only if we apriori set this value 00441 else if((SIT_segment.SIgetCenterX(i) > SIT_expectedXmax) && 00442 (SIT_useExpectedLocation == true)) 00443 { 00444 *candidateBlobItr = false; 00445 *killedByTrackItr = true; 00446 *reasonForKillCodeItr = 7; 00447 SIT_killedBlobs++; 00448 00449 S1 = " Blob Out of Set Expected X Frame : High : "; S2 = " > "; 00450 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00451 sprintf(C2,"%d",(int)(SIT_expectedXmax)); 00452 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00453 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00454 00455 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00456 } 00457 else if((SIT_segment.SIgetCenterX(i) < SIT_expectedXmin) && 00458 (SIT_useExpectedLocation == true)) 00459 { 00460 *candidateBlobItr = false; 00461 *killedByTrackItr = true; 00462 *reasonForKillCodeItr = 8; 00463 SIT_killedBlobs++; 00464 00465 S1 = " Blob Out of Set Expected X Frame : Low : "; S2 = " < "; 00466 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterX(i)); 00467 sprintf(C2,"%d",(int)(SIT_expectedXmin)); 00468 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00469 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00470 00471 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00472 } 00473 // (7) check that a blob is within our EXPECTED Y frame. That is, does 00474 // a blob fall in the image in a place where we would expect it 00475 // for instance close to where we last saw it. 00476 // This is used only if we apriori set this value 00477 else if((SIT_segment.SIgetCenterY(i) > SIT_expectedYmax) && 00478 (SIT_useExpectedLocation == true)) 00479 { 00480 *candidateBlobItr = false; 00481 *killedByTrackItr = true; 00482 *reasonForKillCodeItr = 9; 00483 SIT_killedBlobs++; 00484 00485 S1 = " Blob Out of Set Expected Y Frame : High : "; S2 = " > "; 00486 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00487 sprintf(C2,"%d",(int)(SIT_expectedYmax)); 00488 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00489 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00490 00491 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00492 } 00493 else if((SIT_segment.SIgetCenterY(i) < SIT_expectedYmin) && 00494 (SIT_useExpectedLocation == true)) 00495 { 00496 *candidateBlobItr = false; 00497 *killedByTrackItr = true; 00498 *reasonForKillCodeItr = 10; 00499 SIT_killedBlobs++; 00500 00501 S1 = " Blob Out of Set Expected Y Frame : Low : "; S2 = " < "; 00502 sprintf(C1,"%d",(int)SIT_segment.SIgetCenterY(i)); 00503 sprintf(C2,"%d",(int)(SIT_expectedYmin)); 00504 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00505 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00506 00507 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00508 } 00509 // (8) check that blob is within size ratios. That is, does the 00510 // blob have a proper height and width for the target as we would 00511 // expect. For instance, as head should have a height and width that 00512 // are about the same. 00513 else if(SIT_blobProp.BP_checkSizeRatios == true) 00514 { 00515 FLOAT foo = (SIT_segment.SIgetXmax(i) - SIT_segment.SIgetXmin(i)); 00516 if(foo != 0) 00517 { 00518 FLOAT temp = (SIT_segment.SIgetYmax(i) 00519 - SIT_segment.SIgetYmin(i))/foo; 00520 00521 if(temp < (SIT_blobProp.BP_ratioMin 00522 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))) 00523 { 00524 *candidateBlobItr = false; 00525 *killedByTrackItr = true; 00526 *reasonForKillCodeItr = 11; 00527 SIT_killedBlobs++; 00528 00529 S1 = " Blob Size Ratios Contraint : Min :"; S2 = " < "; 00530 sprintf(C1,"%d",(int)temp); 00531 sprintf(C2,"%d",(int)(SIT_blobProp.BP_ratioMin 00532 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))); 00533 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00534 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00535 00536 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00537 } 00538 else if (temp > (SIT_blobProp.BP_ratioMax 00539 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))) 00540 { 00541 *candidateBlobItr = false; 00542 *killedByTrackItr = true; 00543 *reasonForKillCodeItr = 12; 00544 SIT_killedBlobs++; 00545 00546 S1 = " Blob Size Ratios Contraint : Max : "; S2 = " > "; 00547 sprintf(C1,"%d",(int)temp); 00548 sprintf(C2,"%d",(int)(SIT_blobProp.BP_ratioMax 00549 + (SIT_thresh*SIT_blobProp.BP_softRatioMin))); 00550 sprintf(C3,"(%d)",*reasonForKillCodeItr); 00551 *reasonForKillItr = C3 + S1 + C1 + S2 + C2; 00552 00553 LDEBUG("%3d. reason to kill: %s", i, (*reasonForKillItr).c_str()); 00554 } 00555 else 00556 LDEBUG("%3d. not killed", i); 00557 } 00558 } 00559 } 00560 } 00561 00562 00563 /*********************************************************************/ 00564 // merge all remaining blobs into a single new blob 00565 00566 template SIT_TEMPLATE_CLASS 00567 void segmentImageTrackMC<SIT_TEMPLATE>::SITmergeBlobs() 00568 { 00569 SIT_mass = 0; 00570 FLOAT meanX = 0; 00571 FLOAT meanY = 0; 00572 SIT_minX = UINT_MAX; 00573 SIT_minY = UINT_MAX; 00574 SIT_maxX = 0; 00575 SIT_maxY = 0; 00576 00577 // calculate the center of a combined blob from the average 00578 // mass center of all remaining blobs 00579 std::vector<bool>::iterator candidateBlobItr = SIT_candidateBlob.begin(); 00580 00581 for(INT i = 0; i < SIT_segment.SInumberBlobs(); i++, ++candidateBlobItr) 00582 { 00583 if(*candidateBlobItr == true) 00584 { 00585 LDEBUG("*candidateBlobItr == true"); 00586 SIT_mass += SIT_segment.SIgetMass(i); 00587 meanX += SIT_segment.SIgetMass(i)*SIT_segment.SIgetCenterX(i); 00588 meanY += SIT_segment.SIgetMass(i)*SIT_segment.SIgetCenterY(i); 00589 00590 if((unsigned)SIT_segment.SIgetXmax(i) > SIT_maxX) 00591 SIT_maxX = SIT_segment.SIgetXmax(i); 00592 00593 if((unsigned)SIT_segment.SIgetYmax(i) > SIT_maxY) 00594 SIT_maxY = SIT_segment.SIgetYmax(i); 00595 00596 if((unsigned)SIT_segment.SIgetXmin(i) < SIT_minX) 00597 SIT_minX = SIT_segment.SIgetXmin(i); 00598 00599 if((unsigned)SIT_segment.SIgetYmin(i) < SIT_minY) 00600 SIT_minY = SIT_segment.SIgetYmin(i); 00601 } 00602 00603 LDEBUG("%3d. [%3f %3f] SIT_mass: %f ", i, 00604 float(SIT_segment.SIgetCenterX(i)), 00605 float(SIT_segment.SIgetCenterY(i)), 00606 float(SIT_segment.SIgetMass(i))); 00607 } 00608 00609 // Compute SIT_LOT here and set 00610 if(SIT_mass != 0) 00611 { 00612 SIT_centerX = (int)(meanX/SIT_mass); 00613 SIT_centerY = (int)(meanY/SIT_mass); 00614 SIT_centerM = (int)(SIT_mass); 00615 00616 if(((SIT_maxX - SIT_minX) * (SIT_maxY - SIT_minY)) > 00617 ((SIT_segment.SIgetImageSizeX() * SIT_segment.SIgetImageSizeY())/ 00618 SIT_blobProp.BP_maxFrameSize)) 00619 { 00620 SIT_LOT = true; 00621 SIT_LOTtype = 1; 00622 SIT_LOTtypeName = "(1) Positive Mass but Spacially too Large"; 00623 LDEBUG("(1) Positive Mass but Spacially too Large"); 00624 } 00625 else 00626 { 00627 SIT_LOT = false; 00628 SIT_LOTtypeName = "(0) NO LOT, OK"; 00629 SIT_useExpectedLocation = false; 00630 LDEBUG("(0) NO LOT, OK"); 00631 } 00632 } 00633 else 00634 { 00635 SIT_LOTtypeName = "(2) Zero Mass in merged blobs"; 00636 SIT_LOTtype = 2; 00637 SIT_LOT = true; 00638 LDEBUG("(2) Zero Mass in merged blobs"); 00639 00640 // JACOB: changed this to fixed values instead of calling 00641 // a pointer that may or may not be assigned to something 00642 SIT_centerX = SIT_x_center; 00643 SIT_centerY = SIT_y_center; 00644 } 00645 } 00646 00647 /*********************************************************************/ 00648 // PUBLIC ACCESS METHODS 00649 /*********************************************************************/ 00650 00651 // When called at the start, this will resize all the vectors we use 00652 // We only call this once since it is expensive to call. 00653 template SIT_TEMPLATE_CLASS 00654 segmentImageTrackMC<SIT_TEMPLATE>::segmentImageTrackMC(INT maxBlobCount) 00655 { 00656 SIT_LOTcount = 0; 00657 SIT_frameNumber = 0; 00658 SIT_useLog = false; 00659 SIT_drawTargetImage = true; 00660 SIT_drawColorAdaptImage = true; 00661 SIT_useColorAdaptation = true; 00662 SIT_useExpectedLocation = false; 00663 00664 time_t t = time(0); 00665 std::string theTime = asctime(localtime(&t)); 00666 00667 std::ofstream outfile(SIT_LOG_FILE,std::ios::out); 00668 outfile << theTime << "\n"; 00669 outfile.close(); 00670 00671 SIT_draw = false; 00672 SIT_didCircleColor = false; 00673 SIT_didBoxColor = false; 00674 SIT_didTrackColor = false; 00675 00676 // resize a bunch of std contaner vectors 00677 00678 SIT_chMean1.resize( SIT_channels,0); 00679 SIT_chMean2.resize( SIT_channels,0); 00680 SIT_chStd1.resize( SIT_channels,0); 00681 SIT_chStd2.resize( SIT_channels,0); 00682 SIT_chLB.resize( SIT_channels,0); 00683 SIT_chUB.resize( SIT_channels,0); 00684 SIT_chNSTD.resize( SIT_channels,0); 00685 SIT_chAdapt.resize( SIT_channels,0); 00686 SIT_chSkew.resize( SIT_channels,0); 00687 SIT_initMean.resize(SIT_channels,0); 00688 SIT_initStd.resize( SIT_channels,0); 00689 00690 SIT_softCandidateBlob.resize(maxBlobCount,false); 00691 SIT_candidateBlob.resize( maxBlobCount,false); 00692 SIT_killedByTrack.resize( maxBlobCount,false); 00693 SIT_blobList.resize( maxBlobCount,0); 00694 SIT_reasonForKill.resize( maxBlobCount,"no reason"); 00695 SIT_reasonForKillCode.resize(maxBlobCount,0); 00696 00697 SIT_barWidth = BARWIDTH; 00698 SIT_barSpace = BARSPACE; 00699 SIT_histoHeight = HISTOHEIGHT; 00700 00701 00702 // Load the config file and set a whole bunch of parameters from it 00703 00704 blobConf.openFile("blob.conf",true); 00705 00706 SIT_blobProp.BP_LOTbound = (int)blobConf.getItemValueF("BP_LOTbound"); 00707 SIT_blobProp.BP_bound = (int)blobConf.getItemValueF("BP_bound"); 00708 SIT_blobProp.BP_softBound = (int)blobConf.getItemValueF("BP_softBound"); 00709 SIT_blobProp.BP_lowBound = (int)blobConf.getItemValueF("BP_lowBound"); 00710 SIT_blobProp.BP_traj = (int)blobConf.getItemValueF("BP_traj"); 00711 SIT_blobProp.BP_sampleStart = (int)blobConf.getItemValueF("BP_sampleStart"); 00712 SIT_blobProp.BP_maxTraj = (int)blobConf.getItemValueF("BP_maxTraj"); 00713 SIT_blobProp.BP_maxSize = (int)blobConf.getItemValueF("BP_maxSize"); 00714 SIT_blobProp.BP_minSize = (int)blobConf.getItemValueF("BP_minSize"); 00715 SIT_blobProp.BP_maxFrameSize = blobConf.getItemValueF("BP_maxFrameSize"); 00716 SIT_blobProp.BP_minMass = (int)blobConf.getItemValueF("BP_minMass"); 00717 SIT_blobProp.BP_maxMass = (int)blobConf.getItemValueF("BP_maxMass"); 00718 SIT_blobProp.BP_ratioMin = blobConf.getItemValueF("BP_ratioMin"); 00719 SIT_blobProp.BP_softRatioMin = blobConf.getItemValueF("BP_softRatioMin"); 00720 SIT_blobProp.BP_ratioMax = blobConf.getItemValueF("BP_ratioMax"); 00721 SIT_blobProp.BP_softRatioMax = blobConf.getItemValueF("BP_softRatioMax"); 00722 SIT_blobProp.BP_checkMass = blobConf.getItemValueB("BP_checkMass"); 00723 SIT_blobProp.BP_checkFrameX = blobConf.getItemValueB("BP_checkFrameX"); 00724 SIT_blobProp.BP_checkFrameY = blobConf.getItemValueB("BP_checkFrameY"); 00725 SIT_blobProp.BP_checkSizeRatios = 00726 blobConf.getItemValueB("BP_checkSizeRatios"); 00727 00728 } 00729 00730 /*********************************************************************/ 00731 00732 template SIT_TEMPLATE_CLASS 00733 segmentImageTrackMC<SIT_TEMPLATE>::~segmentImageTrackMC() 00734 {} 00735 00736 /*********************************************************************/ 00737 00738 template SIT_TEMPLATE_CLASS 00739 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetCircleColor(unsigned int r, 00740 unsigned int g, 00741 unsigned int b) 00742 { 00743 SIT_circleRed = r; 00744 SIT_circleBlue = g; 00745 SIT_circleGreen = b; 00746 SIT_didCircleColor = true; 00747 } 00748 00749 /*********************************************************************/ 00750 00751 template SIT_TEMPLATE_CLASS 00752 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetBoxColor(unsigned int r, 00753 unsigned int g, 00754 unsigned int b, 00755 unsigned int bigr, 00756 unsigned int bigg, 00757 unsigned int bigb) 00758 { 00759 SIT_boxRed = r; 00760 SIT_boxGreen = g; 00761 SIT_boxBlue = b; 00762 SIT_bigBoxRed = bigr; 00763 SIT_bigBoxGreen = bigg; 00764 SIT_bigBoxBlue = bigb; 00765 SIT_didBoxColor = true; 00766 } 00767 00768 00769 /*********************************************************************/ 00770 00771 template SIT_TEMPLATE_CLASS 00772 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetTrackColor( 00773 typename std::vector<FLOAT> *color, 00774 typename std::vector<FLOAT> *std, 00775 typename std::vector<FLOAT> *norm, 00776 typename std::vector<FLOAT> *adapt, 00777 typename std::vector<FLOAT> *upperBound, 00778 typename std::vector<FLOAT> *lowerBound, 00779 bool resetColor, 00780 bool resetCandidates) 00781 00782 { 00783 // make sure that all our contaners are the same size 00784 ASSERT(color->size() == std->size()); 00785 ASSERT(std->size() == norm->size()); 00786 ASSERT(norm->size() == adapt->size()); 00787 ASSERT(adapt->size() == upperBound->size()); 00788 ASSERT(upperBound->size() == lowerBound->size()); 00789 00790 // set initial tracking parameters 00791 SIT_thresh = 1; 00792 SIT_initMean = *color; 00793 SIT_initStd = *std; 00794 SIT_chNorm = *norm; 00795 SIT_chAdapt = *adapt; 00796 SIT_chUB = *upperBound; 00797 SIT_chLB = *lowerBound; 00798 SIT_didTrackColor = true; 00799 SIT_LOTcount = 0; 00800 typename std::vector<FLOAT> skew(color->size(),0); 00801 SIT_chSkew = skew; 00802 SIT_segment.SIsetAvg(ERRINTERVAL); 00803 SIT_segment.SIresetAvg(); 00804 SIT_segment.SIsetVal(SIT_initMean,SIT_initStd,SIT_chSkew); 00805 00806 if(SIT_useLog == true) 00807 { 00808 std::ofstream outfile(SIT_LOG_FILE,std::ios::app); 00809 outfile << "FRAME " << SIT_frameNumber << " INIT " << "\t"; 00810 typename std::vector<FLOAT>::iterator imean = SIT_initMean.begin(); 00811 typename std::vector<FLOAT>::iterator istd = SIT_initStd.begin(); 00812 while(imean != SIT_initMean.end()) 00813 { 00814 outfile << *imean << " +/- (" << *istd << ")\t"; 00815 ++imean; ++istd; 00816 } 00817 outfile << "\n"; 00818 outfile.close(); 00819 } 00820 00821 00822 SIT_resetColor = resetColor; 00823 if(resetCandidates == true) 00824 SIT_segment.SIresetCandidates(true); 00825 } 00826 00827 00828 /*********************************************************************/ 00829 00830 template SIT_TEMPLATE_CLASS 00831 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetFrame(int *x, int *y) 00832 { 00833 SIT_segment.SIsetFrame(x,y); 00834 SIT_x_center = *x/2; 00835 SIT_y_center = *y/2; 00836 SIT_centerX = SIT_x_center; 00837 SIT_centerY = SIT_y_center; 00838 } 00839 00840 /*********************************************************************/ 00841 00842 template SIT_TEMPLATE_CLASS 00843 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetUseSmoothing(bool smoothing, FLOAT alpha) 00844 { 00845 SIT_useSmoothing = smoothing; 00846 SIT_smoothingAlpha = alpha; 00847 SIT_didSmoothing = false; 00848 } 00849 00850 /*********************************************************************/ 00851 template SIT_TEMPLATE_CLASS 00852 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetExpectedTargetPosition( 00853 const unsigned int posX, 00854 const unsigned int posY, 00855 const unsigned int maxX, 00856 const unsigned int maxY, 00857 const unsigned int minX, 00858 const unsigned int minY) 00859 { 00860 SIT_expectedX = posX; 00861 SIT_expectedY = posY; 00862 SIT_expectedXmax = maxX; 00863 SIT_expectedYmax = maxY; 00864 SIT_expectedXmin = minX; 00865 SIT_expectedYmin = minY; 00866 SIT_useExpectedLocation = true; 00867 00868 } 00869 00870 /*********************************************************************/ 00871 template SIT_TEMPLATE_CLASS 00872 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetExpectedTargetPosition( 00873 unsigned int *posX, 00874 unsigned int *posY, 00875 unsigned int *maxX, 00876 unsigned int *maxY, 00877 unsigned int *minX, 00878 unsigned int *minY, 00879 bool *isSet) 00880 { 00881 *posX = SIT_expectedX; 00882 *posY = SIT_expectedY; 00883 *maxX = SIT_expectedXmax; 00884 *maxY = SIT_expectedYmax; 00885 *minX = SIT_expectedXmin; 00886 *minY = SIT_expectedYmin; 00887 *isSet = SIT_useExpectedLocation; 00888 } 00889 00890 /*********************************************************************/ 00891 template SIT_TEMPLATE_CLASS 00892 void segmentImageTrackMC<SIT_TEMPLATE>::SITunsetExpectedTargetPosition() 00893 { 00894 SIT_useExpectedLocation = false; 00895 } 00896 00897 /*********************************************************************/ 00898 template SIT_TEMPLATE_CLASS 00899 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleCandidateBandPass(bool toggle) 00900 { 00901 SIT_segment.SItoggleCandidateBandPass(toggle); 00902 } 00903 /*********************************************************************/ 00904 template SIT_TEMPLATE_CLASS 00905 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleColorAdaptation(bool toggle) 00906 { 00907 SIT_useColorAdaptation = toggle; 00908 } 00909 00910 /*********************************************************************/ 00911 template SIT_TEMPLATE_CLASS 00912 void segmentImageTrackMC<SIT_TEMPLATE>::SITsetFrameNumber(unsigned long frame) 00913 { 00914 SIT_frameNumber = frame; 00915 } 00916 00917 /*********************************************************************/ 00918 // MAIN METHOD 00919 /*********************************************************************/ 00920 00921 /* This is a basic tracker access method that tracks on one image at a time */ 00922 /* this one is designed to work with any Pixels pixel */ 00923 00924 template SIT_TEMPLATE_CLASS 00925 void segmentImageTrackMC<SIT_TEMPLATE>::SITtrackImageAny 00926 (Image<PixH2SV2<FLOAT> >& input, 00927 Image<PixRGB<byte> > *image, 00928 Image<PixRGB<byte> > *auxImage, 00929 bool editBlobs) 00930 { 00931 // Assert that parameters have been set up before starting 00932 ASSERT(SIT_didCircleColor == true); 00933 ASSERT(SIT_didBoxColor == true); 00934 ASSERT(SIT_didTrackColor == true); 00935 00936 SIT_imageHold = image; 00937 SIT_auxHold = auxImage; 00938 00939 // decimate input image twice to speed things up 00940 input = decXY(input); 00941 input = decXY(input); 00942 00943 Image<FLOAT> timage; 00944 timage.resize(input.getWidth(),input.getHeight(),true); 00945 SIT_chans.resize(SIT_channels,timage); 00946 for(unsigned int i = 0; i < SIT_channels; i++) 00947 { 00948 typename Image<FLOAT>::iterator iSIT_chans = SIT_chans[i].beginw(); 00949 for(typename Image<PixH2SV2<FLOAT> >::iterator 00950 iinput = input.beginw(); 00951 iinput != input.endw(); ++iinput, ++iSIT_chans) 00952 { 00953 *iSIT_chans = iinput->p[i]; 00954 } 00955 } 00956 00957 if(SIT_useSmoothing) 00958 SITsmoothImage(&SIT_chans); 00959 00960 SITrunTrack(SIT_imageHold,&SIT_chans,editBlobs); 00961 } 00962 00963 /*********************************************************************/ 00964 00965 /* This is a basic tracker access method that tracks on one image at a time */ 00966 template SIT_TEMPLATE_CLASS 00967 void segmentImageTrackMC<SIT_TEMPLATE>::SITtrackImage 00968 (Image<PixRGB<byte> >& input, 00969 Image<PixRGB<byte> > *image, 00970 Image<PixRGB<byte> > *auxImage, 00971 bool editBlobs) 00972 { 00973 00974 // Assert that parameters have been set up before starting 00975 ASSERT(SIT_didCircleColor == true); 00976 ASSERT(SIT_didBoxColor == true); 00977 ASSERT(SIT_didTrackColor == true); 00978 00979 SIT_imageHold = image; 00980 SIT_auxHold = auxImage; 00981 Image< PixRGB<FLOAT> > fima; 00982 00983 // decimate input image twice to speed things up 00984 fima = decXY(input); 00985 fima = decXY(fima); 00986 SIT_fimaHold = &fima; 00987 00988 // break image into seperate channels 00989 Image<FLOAT> timage; 00990 timage.resize(fima.getWidth(),fima.getHeight(),true); 00991 00992 //typename std::vector<Image<FLOAT> > chans(3,timage); 00993 SIT_chans.resize(3,timage); 00994 typename Image<FLOAT>::iterator iHimage = SIT_chans[0].beginw(); 00995 typename Image<FLOAT>::iterator iSimage = SIT_chans[1].beginw(); 00996 typename Image<FLOAT>::iterator iVimage = SIT_chans[2].beginw(); 00997 for(typename Image<PixRGB<FLOAT> >::iterator iImage = fima.beginw(); 00998 iImage != fima.endw(); ++iImage, ++iHimage, ++iSimage, ++iVimage) 00999 { 01000 FLOAT pixH,pixS,pixV; 01001 PixRGB<FLOAT> pix; 01002 pix = *iImage; 01003 PixHSV<FLOAT>(pix).getHSV(pixH,pixS,pixV); 01004 *iHimage = pixH; *iSimage = pixS; *iVimage = pixV; 01005 } 01006 01007 if(SIT_useSmoothing) 01008 SITsmoothImage(&SIT_chans); 01009 01010 SITrunTrack(SIT_imageHold,&SIT_chans,editBlobs); 01011 } 01012 01013 /*********************************************************************/ 01014 01015 template SIT_TEMPLATE_CLASS 01016 void segmentImageTrackMC<SIT_TEMPLATE>::SITtrackImage(typename 01017 std::vector<Image<FLOAT> >& input, 01018 Image<PixRGB<byte> > *image, 01019 Image<PixRGB<byte> > *auxImage, 01020 bool editBlobs) 01021 { 01022 SIT_imageHold = image; 01023 SIT_auxHold = auxImage; 01024 Image<FLOAT> told; 01025 typename std::vector<Image<FLOAT> > fima(input.size(),told); 01026 typename std::vector<Image<FLOAT> >::iterator ifima = fima.begin(); 01027 for(typename std::vector<Image<FLOAT> >::iterator iinput = input.begin(); 01028 iinput != input.end(); ++iinput, ++ifima) 01029 { 01030 *ifima = decXY(*iinput); 01031 *ifima = decXY(*ifima); 01032 } 01033 01034 if(SIT_useSmoothing) 01035 SITsmoothImage(&fima); 01036 01037 SITrunTrack(SIT_imageHold,&fima,editBlobs); 01038 } 01039 01040 /*********************************************************************/ 01041 01042 template SIT_TEMPLATE_CLASS 01043 void segmentImageTrackMC<SIT_TEMPLATE>::SITsmoothImage(typename 01044 std::vector<Image<FLOAT> > *input) 01045 { 01046 if(SIT_didSmoothing == false) 01047 { 01048 Image<FLOAT> timage; 01049 timage.resize(input->at(0).getWidth(),input->at(0).getHeight(),true); 01050 SIT_fimaLast.resize(input->size(),timage); 01051 } 01052 01053 typename std::vector<Image<FLOAT> >::iterator iinput = input->begin(); 01054 typename std::vector<Image<FLOAT> >::iterator ifima = SIT_fimaLast.begin(); 01055 while(iinput != input->end()) 01056 { 01057 if(SIT_didSmoothing) 01058 { 01059 *ifima = (*iinput + ((*ifima) * SIT_smoothingAlpha))/ 01060 (1+SIT_smoothingAlpha); 01061 } 01062 else 01063 { 01064 *ifima = *iinput; 01065 SIT_didSmoothing = true; 01066 } 01067 ++iinput; ++ifima; 01068 } 01069 input = &SIT_fimaLast; 01070 } 01071 01072 /*********************************************************************/ 01073 01074 template SIT_TEMPLATE_CLASS 01075 void segmentImageTrackMC<SIT_TEMPLATE>::SITuseLog(bool useLog) 01076 { 01077 SIT_useLog = useLog; 01078 } 01079 01080 /*********************************************************************/ 01081 01082 template SIT_TEMPLATE_CLASS 01083 void segmentImageTrackMC<SIT_TEMPLATE>::SITtoggleDrawing(bool targetImage, 01084 bool colorAdaptImage) 01085 { 01086 SIT_drawTargetImage = targetImage; 01087 SIT_drawColorAdaptImage = colorAdaptImage; 01088 } 01089 01090 /*********************************************************************/ 01091 01092 template SIT_TEMPLATE_CLASS 01093 void segmentImageTrackMC<SIT_TEMPLATE>::SITrunTrack( 01094 Image<PixRGB<byte> > *image, 01095 typename 01096 std::vector<Image<FLOAT> > *input, 01097 bool editBlobs = true) 01098 { 01099 SIT_LOTandRESET = false; 01100 // (1) segment the decimated image 01101 SIT_segment.SIsegment(image,input); 01102 LDEBUG("SEGMENTED"); 01103 // (2) get center of mass for blobs 01104 SIT_segment.SIcalcMassCenter(); 01105 LDEBUG("CALCULATED MASS CENTER"); 01106 // (3) edit blobs, weed out all the non-hackers who are not 01107 // fit to carry a rifle 01108 if(editBlobs) 01109 SITanalyzeBlobs(); 01110 LDEBUG("BLOBS ANALYZED"); 01111 // (4) merge all remaining blobs 01112 SITmergeBlobs(); 01113 LDEBUG("BLOBS MERGED"); 01114 // (5) apply adaptive color thesholding 01115 SITcolorAdaptation(); 01116 LDEBUG("COLORS ADAPTED"); 01117 } 01118 01119 /*********************************************************************/ 01120 // DATA RETURN METHODS 01121 /*********************************************************************/ 01122 01123 template SIT_TEMPLATE_CLASS 01124 bool segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOT() 01125 { 01126 return SIT_LOT; 01127 } 01128 01129 /*********************************************************************/ 01130 01131 template SIT_TEMPLATE_CLASS 01132 unsigned int segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOTtype() 01133 { 01134 return SIT_LOTtype; 01135 } 01136 01137 /*********************************************************************/ 01138 01139 template SIT_TEMPLATE_CLASS 01140 std::string segmentImageTrackMC<SIT_TEMPLATE>::SITreturnLOTtypeName() 01141 { 01142 return SIT_LOTtypeName; 01143 } 01144 01145 /*********************************************************************/ 01146 01147 template SIT_TEMPLATE_CLASS 01148 Image<long> segmentImageTrackMC<SIT_TEMPLATE>::SITreturnBlobMap() 01149 { 01150 return SIT_segment.SIreturnBlobs(); 01151 } 01152 01153 /*********************************************************************/ 01154 01155 template SIT_TEMPLATE_CLASS 01156 Image<byte> segmentImageTrackMC<SIT_TEMPLATE>::SITreturnCandidateImage() 01157 { 01158 return SIT_segment.SIreturnNormalizedCandidates(); 01159 } 01160 01161 /*********************************************************************/ 01162 01163 template SIT_TEMPLATE_CLASS 01164 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosition(int &x, 01165 int &y) 01166 { 01167 SIT_centerXmod = SIT_centerX*DEC; 01168 SIT_centerYmod = SIT_centerY*DEC; 01169 x = SIT_centerXmod; 01170 y = SIT_centerYmod; 01171 } 01172 01173 /*********************************************************************/ 01174 01175 template SIT_TEMPLATE_CLASS 01176 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobWeight(int &m) 01177 { 01178 m = SIT_centerM*DEC; 01179 } 01180 01181 /*********************************************************************/ 01182 01183 template SIT_TEMPLATE_CLASS 01184 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetMinMaxBoundry(unsigned int *minX, 01185 unsigned int *maxX, 01186 unsigned int *minY, 01187 unsigned int *maxY) 01188 { 01189 SIT_minXmod = SIT_minX*DEC; 01190 SIT_maxXmod = SIT_maxX*DEC; 01191 SIT_minYmod = SIT_minY*DEC; 01192 SIT_maxYmod = SIT_maxY*DEC; 01193 *minX = SIT_minXmod; 01194 *maxX = SIT_maxXmod; 01195 *minY = SIT_minYmod; 01196 *maxY = SIT_maxYmod; 01197 } 01198 01199 /********************************************************************/ 01200 01201 /* commented this out because SIT_MASS is not defined (or even declared) 01202 anywhere, so we get an error with g++ 3.4.1 */ 01203 template SIT_TEMPLATE_CLASS 01204 FLOAT segmentImageTrackMC<SIT_TEMPLATE>::SITgetMass() 01205 { 01206 return SIT_mass; 01207 } 01208 01209 /********************************************************************/ 01210 01211 template SIT_TEMPLATE_CLASS 01212 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobAttrition( 01213 INT *totalBlobs, 01214 INT *killedBlobs) 01215 { 01216 totalBlobs = &SIT_totalBlobs; 01217 killedBlobs = &SIT_killedBlobs; 01218 } 01219 01220 /********************************************************************/ 01221 01222 template SIT_TEMPLATE_CLASS 01223 void segmentImageTrackMC<SIT_TEMPLATE>::SITgetAdaptiveChannelVals( 01224 typename std::vector<FLOAT> *mean, 01225 typename std::vector<FLOAT> *std) 01226 { 01227 mean = &SIT_chMean1; 01228 std = &SIT_chStd1; 01229 } 01230 01231 /********************************************************************/ 01232 01233 template SIT_TEMPLATE_CLASS 01234 unsigned int segmentImageTrackMC<SIT_TEMPLATE>::SITgetLOTcount() 01235 { 01236 return SIT_LOTcount; 01237 } 01238 01239 /********************************************************************/ 01240 01241 template SIT_TEMPLATE_CLASS 01242 INT segmentImageTrackMC<SIT_TEMPLATE>::SITnumberBlobs() 01243 { 01244 return SIT_segment.SInumberBlobs(); 01245 } 01246 01247 /********************************************************************/ 01248 01249 template SIT_TEMPLATE_CLASS 01250 unsigned short 01251 segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobReasonForKillCode(INT blob) 01252 { 01253 return SIT_reasonForKillCode[blob]; 01254 } 01255 01256 /********************************************************************/ 01257 01258 template SIT_TEMPLATE_CLASS 01259 std::string segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobReasonForKill(INT blob) 01260 { 01261 return SIT_reasonForKill[blob]; 01262 } 01263 01264 /********************************************************************/ 01265 01266 template SIT_TEMPLATE_CLASS 01267 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobMass(INT blob) 01268 { 01269 return SIT_segment.SIgetMass(blob); 01270 } 01271 01272 /********************************************************************/ 01273 01274 template SIT_TEMPLATE_CLASS 01275 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosX(INT blob) 01276 { 01277 return (INT)floor(SIT_segment.SIgetCenterX(blob)); 01278 } 01279 01280 /********************************************************************/ 01281 01282 template SIT_TEMPLATE_CLASS 01283 INT segmentImageTrackMC<SIT_TEMPLATE>::SITgetBlobPosY(INT blob) 01284 { 01285 return (INT)floor(SIT_segment.SIgetCenterY(blob)); 01286 } 01287 01288 01289 /*********************************************************************/ 01290 // DRAWING METHODS 01291 /*********************************************************************/ 01292 01293 template SIT_TEMPLATE_CLASS 01294 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobTrack(INT i) 01295 { 01296 // find boundaries of this blob 01297 unsigned int tt = SIT_segment.SIgetYmin(i); 01298 unsigned int bb = SIT_segment.SIgetYmax(i); 01299 unsigned int ll = SIT_segment.SIgetXmin(i); 01300 unsigned int rr = SIT_segment.SIgetXmax(i); 01301 01302 // draw bounding box for this blob 01303 // Note: box must be of height > 1 and width > 1 01304 if((bb != tt) && (ll != rr)) 01305 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(tt*DEC,ll*DEC,bb*DEC,rr*DEC), 01306 PixRGB<byte>(SIT_boxRed, 01307 SIT_boxGreen, 01308 SIT_boxBlue),1); 01309 01310 // draw target circle for this blob 01311 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_segment.SIgetCenterX(i) 01312 *DEC 01313 ,(int)SIT_segment.SIgetCenterY(i)*DEC) 01314 ,(int)sqrt((float)SIT_segment.SIgetMass(i)), 01315 PixRGB<byte>(SIT_circleRed, 01316 SIT_circleGreen, 01317 SIT_circleBlue),2); 01318 01319 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_segment.SIgetCenterX(i) 01320 *DEC 01321 ,(int)SIT_segment.SIgetCenterY(i)*DEC) 01322 ,2,PixRGB<byte>(255,0,0),2); 01323 } 01324 01325 /*********************************************************************/ 01326 01327 template SIT_TEMPLATE_CLASS 01328 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobTrackMerged() 01329 { 01330 if((SIT_minY != SIT_maxY) && (SIT_minX != SIT_maxX)) 01331 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(SIT_minY*DEC,SIT_minX*DEC, 01332 SIT_maxY*DEC,SIT_maxX*DEC), 01333 PixRGB<byte>(SIT_bigBoxRed, 01334 SIT_bigBoxGreen, 01335 SIT_bigBoxBlue),2); 01336 01337 // draw target circle for this blob 01338 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_centerX*DEC,(int)SIT_centerY*DEC) 01339 ,(int)sqrt(SIT_mass), 01340 PixRGB<byte>(SIT_bigBoxRed, 01341 SIT_bigBoxGreen, 01342 SIT_bigBoxBlue),2); 01343 01344 drawCircle(*SIT_imageHold, Point2D<int>((int)SIT_centerX*DEC,(int)SIT_centerY*DEC) 01345 ,2,PixRGB<byte>(255,0,0),2); 01346 } 01347 01348 01349 01350 /*********************************************************************/ 01351 template SIT_TEMPLATE_CLASS 01352 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawBlobBox(INT i) 01353 { 01354 // find boundaries of this blob 01355 unsigned int tt = SIT_segment.SIgetYmin(i); 01356 unsigned int bb = SIT_segment.SIgetYmax(i); 01357 unsigned int ll = SIT_segment.SIgetXmin(i); 01358 unsigned int rr = SIT_segment.SIgetXmax(i); 01359 01360 01361 // draw bounding box for this blob 01362 // Note: box must be of height > 1 and width > 1 01363 if((bb != tt) && (ll != rr)) 01364 drawRectEZ(*SIT_imageHold, Rectangle::tlbrI(tt*DEC,ll*DEC,bb*DEC,rr*DEC), 01365 PixRGB<byte>(SIT_circleRed, 01366 SIT_circleGreen, 01367 SIT_circleBlue),1); 01368 } 01369 01370 /*********************************************************************/ 01371 template SIT_TEMPLATE_CLASS 01372 void segmentImageTrackMC<SIT_TEMPLATE>::SITdrawHistoValues( 01373 typename std::vector<FLOAT> *mean, 01374 typename std::vector<FLOAT> *std, 01375 typename std::vector<FLOAT> *lb, 01376 typename std::vector<FLOAT> *ub, 01377 typename std::vector<FLOAT> *norm, 01378 bool LOT) 01379 { 01380 unsigned int minWidth = SIT_barWidth+SIT_barSpace*mean->size(); 01381 if((unsigned)SIT_auxHold->getWidth() < minWidth) 01382 SIT_auxHold->resize(minWidth,(int)SIT_histoHeight,true); 01383 // draw background grid in HSV bar graph 01384 if(LOT == false) 01385 drawGrid(*SIT_auxHold, 25,25,1,1,PixRGB<byte>(100,100,100)); 01386 else 01387 drawGrid(*SIT_auxHold, 25,25,1,1,PixRGB<byte>(200,100,100)); 01388 01389 typename std::vector<FLOAT>::iterator imean = mean->begin(); 01390 typename std::vector<FLOAT>::iterator istd = std->begin(); 01391 typename std::vector<FLOAT>::iterator ilb = lb->begin(); 01392 typename std::vector<FLOAT>::iterator iub = ub->begin(); 01393 typename std::vector<FLOAT>::iterator inorm = norm->begin(); 01394 01395 unsigned int start = SIT_barSpace; 01396 unsigned int end = SIT_barWidth + start; 01397 01398 while(imean != mean->end()) 01399 { 01400 FLOAT mean = (*imean/(*inorm)); 01401 FLOAT std = (*istd/(*inorm)); 01402 FLOAT ub = (*iub/(*inorm)); 01403 FLOAT lb = (*ilb/(*inorm)); 01404 01405 // draw HSV mean value bars as a bunch of rectangles 01406 drawRectEZ(*SIT_auxHold, Rectangle::tlbrI(0,start,(int)(mean* 01407 SIT_histoHeight),end), 01408 PixRGB<byte>(0,0,255),1); 01409 01410 // draw standard deviation bars 01411 01412 if((((mean-std)*SIT_histoHeight) > 0) 01413 && (((mean+std)*SIT_histoHeight) < SIT_auxHold->getHeight())) 01414 drawRectEZ(*SIT_auxHold, Rectangle::tlbrI((int)((mean-std)*SIT_histoHeight) 01415 ,start+2, 01416 (int)((mean+std)*SIT_histoHeight) 01417 ,end-2), 01418 PixRGB<byte>(255,255,0),1); 01419 01420 01421 drawRectEZ(*SIT_auxHold, Rectangle::tlbrI((int)(lb*(SIT_histoHeight-1)) 01422 ,(signed)start-3, 01423 (int)(ub*(SIT_histoHeight-1)) 01424 ,(signed)start-1), 01425 PixRGB<byte>(255,0,0),1); 01426 01427 01428 ++imean, ++istd, ++ilb, ++iub, ++inorm; 01429 start = end + SIT_barSpace; 01430 end = start + SIT_barWidth; 01431 } 01432 } 01433 01434 #undef SIT_TEMPLATE_CLASS 01435 #undef SIT_TEMPLATE 01436 01437 template class segmentImageTrackMC<float, unsigned int, 3>; 01438 template class segmentImageTrackMC<float, unsigned int, 4>; 01439 01440 #endif 01441 01442 // ###################################################################### 01443 /* So things look consistent in everyone's emacs... */ 01444 /* Local Variables: */ 01445 /* indent-tabs-mode: nil */ 01446 /* End: */