00001 /*!@file BeoSub/ColorTracker.C I method to check for the existence of a defined color in an image */ 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: Zack Gossman <gossman@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/ColorTracker.C $ 00035 // $Id: ColorTracker.C 9412 2008-03-10 23:10:15Z farhan $ 00036 00037 #include "BeoSub/ColorTracker.H" 00038 #include "BeoSub/ColorDef.H" 00039 00040 // ###################################################################### 00041 ColorTracker::ColorTracker(OptionManager& mgr, 00042 const std::string& descrName, 00043 const std::string& tagName): 00044 ModelComponent(mgr, descrName, tagName) 00045 { 00046 color.resize(4,0.0F); 00047 00048 debugmode = true; 00049 MYLOGVERB = 0; 00050 hasSetup = false; 00051 hasRun = false; 00052 } 00053 00054 // ###################################################################### 00055 ColorTracker::~ColorTracker(){ 00056 00057 } 00058 00059 // ###################################################################### 00060 void ColorTracker::setupTracker(const char* colorArg, Image< PixRGB<byte> > image, bool debug){ 00061 00062 debugmode = debug;//turns output on or off 00063 00064 //NOTE: the following group will output a large amount of extranous text to the console. However, it is necessary to keep it here in order to avoid a 320x240 hardcoded size. TRY doing a default setup like in the CannyModel class. FIX! 00065 if(!hasSetup){ 00066 segmenter = new segmentImageTrackMC<float,unsigned int,4> (image.getWidth()*image.getHeight()); 00067 segmenter->SITsetCircleColor(0,255,0); 00068 segmenter->SITsetBoxColor(255,255,0,0,255,255); 00069 segmenter->SITsetUseSmoothing(true,10); 00070 segmenter->SITtoggleCandidateBandPass(false); 00071 segmenter->SITtoggleColorAdaptation(false); 00072 00073 int ww = image.getWidth()/4; 00074 int hh = image.getHeight()/4; 00075 segmenter->SITsetFrame(&ww,&hh); 00076 } 00077 00078 //COLORTRACKING DECS: note that much of these may not need to be in this file 00079 //Colors MUST use H2SV2 pixel values! use test-sampleH2SV2 to sample needed values! --Z 00080 00081 ColorDef(); 00082 00083 //0 = H1 (0-1), 1=H2 (0-1), 2=S (0-1), 3=V (0-1) 00084 if(!strcmp(colorArg, "Red")){ 00085 color=red; 00086 } 00087 00088 else if(!strcmp(colorArg, "Green")){ 00089 color=green; 00090 } 00091 00092 else if(!strcmp(colorArg, "Orange")){ 00093 color=orange; 00094 } 00095 else if(!strcmp(colorArg, "Blue")){ 00096 color=blue; 00097 } 00098 else if(!strcmp(colorArg, "Yellow")){ 00099 color=yellow; 00100 } 00101 else if(!strcmp(colorArg, "White")){ 00102 color=white; 00103 } 00104 else if(!strcmp(colorArg, "Black")){ 00105 color=black; 00106 } 00107 else if (!strcmp(colorArg, "Brown")) { 00108 //BROWN 00109 color=brown; 00110 } 00111 else{ 00112 printf("Color argument not recognized.\n"); 00113 } 00114 00115 00116 //! +/- tollerance value on mean for track 00117 std::vector<float> std(4,0.0F); 00118 //NOTE that the saturation tolerance is important (if it gos any higher thn this, it will nearly always recognize white!) 00119 std[0] = 0.20000; std[1] = 0.40000; std[2] = 0.44500; std[3] = 0.65000; 00120 00121 //! normalizer over color values (highest value possible) 00122 std::vector<float> norm(4,0.0F); 00123 norm[0] = 1.0F; norm[1] = 1.0F; norm[2] = 1.0F; norm[3] = 1.0F; 00124 00125 //! how many standard deviations out to adapt, higher means less bias 00126 //The lower these are, the more strict recognition will be in subsequent frames 00127 //TESTED AND PROVED do NOT change unless you're SURE 00128 std::vector<float> adapt(4,0.0F); 00129 //adapt[0] = 3.5F; adapt[1] = 3.5F; adapt[2] = 3.5F; adapt[3] = 3.5F; 00130 adapt[0] = 5.0F; adapt[1] = 5.0F; adapt[2] = 5.0F; adapt[3] = 5.0F; 00131 00132 //! highest value for color adaptation possible (hard boundry) 00133 std::vector<float> upperBound(4,0.0F); 00134 upperBound[0] = color[0] + 0.45F; upperBound[1] = color[1] + 0.45F; upperBound[2] = color[2] + 0.55F; upperBound[3] = color[3] + 0.55F; 00135 00136 //! lowest value for color adaptation possible (hard boundry) 00137 std::vector<float> lowerBound(4,0.0F); 00138 lowerBound[0] = color[0] - 0.45F; lowerBound[1] = color[1] - 0.45F; lowerBound[2] = color[2] - 0.55F; lowerBound[3] = color[3] - 0.55F; 00139 //END DECS 00140 00141 if(!strcmp(colorArg, "White") || !strcmp(colorArg, "Black")){ 00142 adapt[0] = 25.0F; adapt[1] = 25.0F; adapt[2] = 0.1F; adapt[3] = 0.1F; 00143 00144 std[0] = 1.0F; std[1] = 1.0F; std[2] = 0.1F; std[3] = 0.1F; 00145 00146 } 00147 //Read image from file and display 00148 colorImg = image; 00149 00150 //color tracking stuff 00151 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound); 00152 00153 if(debugmode){ 00154 if(!hasSetup){ 00155 xwin1.reset(new XWindow(colorImg.getDims(), -1, -1, "input window")); 00156 xwin1->setPosition(0, 0); 00157 } 00158 xwin1->drawImage(colorImg); 00159 } 00160 hasSetup = true; 00161 00162 } 00163 00164 // ###################################################################### 00165 bool ColorTracker::runTracker(float threshold, float &xpos, float &ypos, float &mass){//xpos and ypos and mass are reference containers for final x and y positions 00166 bool colorFound = false; 00167 00168 Image< PixH2SV2<float> > H2SVimage = colorImg; 00169 00170 //junk images to make the segmenter happy 00171 Image< PixRGB<byte> > display; 00172 Image<PixRGB<byte> > Aux; 00173 segmenter->SITtrackImageAny(H2SVimage,&display,&Aux,true); 00174 00175 // Retrieve our output image 00176 outputImg = (Image<byte>)quickInterpolate(segmenter->SITreturnCandidateImage(),4); 00177 float foundMass = 0.0; 00178 int whichBlob = 0; 00179 int xWhere = 0; 00180 int yWhere = 0; 00181 00182 //identify the largest blob found 00183 for(unsigned int i = 0; i < segmenter->SITnumberBlobs(); i++){ 00184 if(4.0*(segmenter->SITgetBlobMass(i)) > foundMass){ 00185 whichBlob = (int)i; 00186 foundMass = 4.0*(segmenter->SITgetBlobMass(i)); 00187 } 00188 } 00189 00190 //Check whether largest blob exceeds threshold size 00191 if(foundMass > threshold){ 00192 mass = foundMass; 00193 xpos = xWhere = 4*(segmenter->SITgetBlobPosX(whichBlob)); 00194 ypos = yWhere = 4*(segmenter->SITgetBlobPosY(whichBlob)); 00195 if(debugmode){ 00196 printf("\n\nLargest blob found with mass %f at %d, %d\n\n", foundMass, xWhere, yWhere); 00197 } 00198 colorFound = true; 00199 } 00200 else if(debugmode){ 00201 printf("\n\nColor not found in appreciable quantities. Largest blob is %f\n\n", foundMass); 00202 } 00203 if(debugmode){ 00204 //point to center of mass 00205 drawDisk(outputImg, Point2D<int>(xWhere, yWhere), 2, PixRGB<byte>(225, 20, 20)); 00206 drawCircle(outputImg, Point2D<int>(xWhere, yWhere), (int)(sqrt(foundMass)), PixRGB<byte>(20, 20, 255), 2); 00207 00208 if(!hasRun){ 00209 xwin2.reset(new XWindow(outputImg.getDims(), -1, -1, "output window")); 00210 xwin2->setPosition(outputImg.getWidth()+10, 0); 00211 } 00212 xwin2->drawImage(outputImg); 00213 } 00214 00215 hasRun = true; 00216 return colorFound; 00217 } 00218 00219 // ###################################################################### 00220 /* So things look consistent in everyone's emacs... */ 00221 /* Local Variables: */ 00222 /* indent-tabs-mode: nil */ 00223 /* End: */ 00224