00001 00002 00003 #include "BeoSub/ColorSegmenter.H" 00004 00005 00006 ColorSegmenter::ColorSegmenter(){ 00007 00008 00009 debugmode = false; 00010 setup = false; 00011 color.resize(4,0.0F); 00012 std.resize(4,0.0F); 00013 norm.resize(4,0.0F); 00014 adapt.resize(4,0.0F); 00015 lowerBound.resize(4,0.0F); 00016 upperBound.resize(4,0.0F); 00017 candidate_color = "none"; 00018 Hz = 0.0F; 00019 fps = 0.0F; 00020 res = 0.0F; 00021 00022 int wi = 320/4; 00023 int hi = 240/4; 00024 00025 00026 width = 320; 00027 height = 240; 00028 segmenter = new segmentImageTrackMC<float,unsigned int, 4> (width*height); 00029 00030 segmenter->SITsetFrame(&wi,&hi); 00031 00032 segmenter->SITsetCircleColor(0,255,0); 00033 segmenter->SITsetBoxColor(255,255,0,0,255,255); 00034 segmenter->SITsetUseSmoothing(false,10); 00035 00036 00037 segmenter->SITtoggleCandidateBandPass(false); 00038 segmenter->SITtoggleColorAdaptation(false); 00039 } 00040 00041 ColorSegmenter::~ColorSegmenter(){ 00042 } 00043 00044 00045 void ColorSegmenter::setupColorSegmenter(const char* inputColor, bool debug){ 00046 debugmode = debug; 00047 //for now just allow it orange 00048 //candidate_color = inputColor; 00049 //inputColor = "Orange"; 00050 // canidate_color = inputColor; 00051 00052 //if(!strcmp(candidate_color, "Orange")){ 00053 setupOrange(); 00054 // } 00055 // else{ 00056 // printf("Cannot setup decoder without a color to decode! exiting...\n"); 00057 // return; 00058 // } 00059 00060 segmenter->SITsetTrackColor(&color,&std,&norm,&adapt,&upperBound,&lowerBound); 00061 00062 //if(debugmode){ 00063 wini.reset(new XWindow(Dims(width, height), 0, 0, "test-input window")); 00064 wini->setPosition(0, 0); 00065 wino.reset(new XWindow(Dims(width, height), 0, 0, "test-output window")); 00066 wino->setPosition(width+10, 0); 00067 //} 00068 00069 00070 setup = true; 00071 } 00072 00073 void ColorSegmenter::setupOrange() { 00074 00075 colorConf.openFile("colortrack.conf", true); 00076 00077 PixRGB<float> P1(colorConf.getItemValueF("ORANGE_R"), 00078 colorConf.getItemValueF("ORANGE_G"), 00079 colorConf.getItemValueF("ORANGE_B")); 00080 00081 PixH2SV1<float> ORANGE(P1); 00082 00083 color[0] = ORANGE.H1(); color[1] = ORANGE.H2(); color[2] = ORANGE.S(); color[3] = ORANGE.V(); 00084 00085 //! +/- tollerance value on mean for track 00086 std[0] = colorConf.getItemValueF("ORNG_std0"); 00087 std[1] = colorConf.getItemValueF("ORNG_std1"); 00088 std[2] = colorConf.getItemValueF("ORNG_std2"); 00089 std[3] = colorConf.getItemValueF("ORNG_std3"); 00090 00091 //! normalizer over color values (highest value possible) 00092 norm[0] = colorConf.getItemValueF("ORNG_norm0"); 00093 norm[1] = colorConf.getItemValueF("ORNG_norm1"); 00094 norm[2] = colorConf.getItemValueF("ORNG_norm2"); 00095 norm[3] = colorConf.getItemValueF("ORNG_norm3"); 00096 00097 //! how many standard deviations out to adapt, higher means less bias 00098 adapt[0] = colorConf.getItemValueF("ORNG_adapt0"); 00099 adapt[1] = colorConf.getItemValueF("ORNG_adapt1"); 00100 adapt[2] = colorConf.getItemValueF("ORNG_adapt2"); 00101 adapt[3] = colorConf.getItemValueF("ORNG_adapt3"); 00102 00103 //! highest value for color adaptation possible (hard boundry) 00104 upperBound[0] = color[0] + colorConf.getItemValueF("ORNG_up0"); 00105 upperBound[1] = color[1] + colorConf.getItemValueF("ORNG_up1"); 00106 upperBound[2] = color[2] + colorConf.getItemValueF("ORNG_up2"); 00107 upperBound[3] = color[3] + colorConf.getItemValueF("ORNG_up3"); 00108 00109 //! lowest value for color adaptation possible (hard boundry) 00110 lowerBound[0] = color[0] - colorConf.getItemValueF("ORNG_lb0"); 00111 lowerBound[1] = color[1] - colorConf.getItemValueF("ORNG_lb1"); 00112 lowerBound[2] = color[2] - colorConf.getItemValueF("ORNG_lb2"); 00113 lowerBound[3] = color[3] - colorConf.getItemValueF("ORNG_lb3"); 00114 } 00115 00116 /* 00117 //true test with frame 3498 00118 float ColorSegmenter::oldisolateOrange(Image< PixRGB<byte> > &inputImage, Image<byte> &outputImage) 00119 { 00120 00121 readConfig colorConf; 00122 colorConf.openFile("colortrack.conf", false); 00123 00124 int orangeCount = 0; 00125 00126 Image<PixRGB<byte> >::iterator iptr = inputImage.beginw(); 00127 Image<byte>::iterator optr = outputImage.beginw(); 00128 Image<PixRGB<byte> >::iterator stop = inputImage.endw(); 00129 00130 float tR = colorConf.getItemValueF("ORANGE_stdR");//70.0; 00131 float tG = colorConf.getItemValueF("ORANGE_stdG");//200.0; 00132 float tB = colorConf.getItemValueF("ORANGE_stdB");//128.0; 00133 00134 float R = colorConf.getItemValueF("ORANGE_R");//255; 00135 float G = colorConf.getItemValueF("ORANGE_G");//198; 00136 float B = colorConf.getItemValueF("ORANGE_B");//0; 00137 00138 00139 //for average 00140 float totalHue = 0.0; 00141 int numTotal = 0; 00142 00143 //orange as a hue 00144 float pure_orange_hue = 60*(((G/255)-(B/255))/((R/255)-(B/255)))+0; 00145 float orange_hue = 60*(((tB/255)-(tR/255))/((tG/255) - (tR/255)))+120; 00146 //orange saturation (of HSL) 00147 float orange_sat = ((200.0/255.0)-(70/255.0))/(2.0-(270.0/255.0));//using tR,tG,tB, R,B,G gives '1' 00148 std::cout<<"orange hue is: "<<orange_hue<<std::endl; 00149 std::cout<<"orange saturation(purity) is: "<<orange_sat<<std::endl; 00150 std::cout<<"orange HSV saturation is: "<<(1.0-70.0/200.0)<<std::endl; 00151 // LINFO("orange values (RGB):(std RGB): %f, %f, %f: %f, %f, %f", R, G, B, tR, tG, tB); 00152 while (iptr != stop) 00153 { 00154 float hue = 0.0; 00155 float s = 0.0; //saturation 00156 float avgR = (*iptr).red(); 00157 float avgG = (*iptr).green(); 00158 float avgB = (*iptr).blue(); 00159 float r = avgR/255; 00160 float g = avgG/255; 00161 float b = avgB/255; 00162 00163 00164 00165 00166 //do conversion to HSV to find the hue 00167 float max = 0; 00168 float min = 1; 00169 //find max 00170 if(r > max) { max = r;} 00171 if(g > max) { max = g;} 00172 if(b > max) { max = b;} 00173 //find min 00174 if(r < min){min = r;} 00175 if(g < min){min = g;} 00176 if(b < min){min = b;} 00177 00178 //do conversion to find hue 00179 if(max == min) {hue = 0.0;} 00180 else if(max == r && g >= b) {hue = 60.0*((g-b)/(max - min)) + 0.0;} 00181 else if(max == r && g < b) {hue = 60.0*((g-b)/(max - min)) + 360.0;} 00182 else if(max == g) {hue = 60.0*((b-r)/(max-min))+120.0;} 00183 else if(max == b) {hue = 60.0*((r-g)/(max-min))+240.0;} 00184 00185 00186 //for average calculation 00187 totalHue += hue; 00188 numTotal++; 00189 00190 //find saturation 00191 if(max){s = max;} 00192 if(max != 0){s = 1 - min/max;} 00193 //std::cout<<" "<<hue; 00194 if(hue == orange_hue)//result:get spects here and there 00195 { 00196 //(*optr) = (byte)255; // orange 00197 //orangeCount++; 00198 } 00199 if(hue == pure_orange_hue)//result:nothing 00200 { 00201 //(*optr) = (byte)255; // orange 00202 //orangeCount++; 00203 } 00204 //to reason these numbers 145 is about the value of orange hue 00205 //pretty good but with spects, "s != 1" gets rid of specs, but also takes out some of the pipe 00206 //value of 120 to 145 seems best 00207 //using 130 as min makes it less accurate 00208 //using a higher max does not seem to make a difference 00209 //probably because of the colors involved here 00210 if(!(120<hue && hue<146) && 00211 s != 1) 00212 { 00213 //std::cout<<" "<<s; 00214 (*optr) = (byte)255; // orange 00215 orangeCount++; 00216 } 00217 00218 //float avg = (avgR+avgG+avgB)/3.0; 00219 //float sigma = pow(avgR - avg, 2.) + pow(avgG - avg, 2.) + pow(avgB - avg, 2.); 00220 //float stdDev = sqrt( (1./3.) * sigma ); 00221 00222 //result: pretty good but is confused by highlights 00223 if (avgR > R - tR && avgR < R + tR && 00224 avgG > G - tG && avgG < G + tG && 00225 avgB > B - tB && avgB < B + tB ) 00226 { 00227 (*optr) = (byte)255; // orange 00228 orangeCount++; 00229 } 00230 // else 00231 // { 00232 // //if(outputImage.coordsOk(i,j)){ 00233 // //(*optr) = (byte)0; //not orange 00234 // //} 00235 // } 00236 00237 iptr++; optr++; 00238 } 00239 00240 std::cout<<"average hue was "<<totalHue/numTotal<<std::endl; 00241 return float(orangeCount)/float( (inputImage.getHeight() * inputImage.getWidth())); 00242 } 00243 00244 00245 */ 00246 00247 00248 00249 //true test with frame 3498 00250 float ColorSegmenter::isolateOrange(Image< PixRGB<byte> > &inputImage, Image<byte> &outputImage) 00251 { 00252 Image< PixRGB<byte> > tempImage(inputImage); 00253 Image<PixH2SV2<float> > h2svImage(tempImage); 00254 00255 readConfig colorConf; 00256 colorConf.openFile("colortrack.conf", false); 00257 00258 int orangeCount = 0; 00259 00260 Image<PixRGB<byte> >::iterator iptr = inputImage.beginw(); 00261 Image<byte>::iterator optr = outputImage.beginw(); 00262 Image<PixRGB<byte> >::iterator stop = inputImage.endw(); 00263 00264 float tR = colorConf.getItemValueF("ORANGE_stdR");//70.0; 00265 float tG = colorConf.getItemValueF("ORANGE_stdG");//200.0; 00266 float tB = colorConf.getItemValueF("ORANGE_stdB");//128.0; 00267 00268 float R = colorConf.getItemValueF("ORANGE_R");//255; 00269 float G = colorConf.getItemValueF("ORANGE_G");//198; 00270 float B = colorConf.getItemValueF("ORANGE_B");//0; 00271 00272 00273 //for average 00274 float totalHue = 0.0; 00275 int numTotal = 0; 00276 00277 //orange as a hue 00278 float pure_orange_hue = 60*(((G/255)-(B/255))/((R/255)-(B/255)))+0; 00279 float orange_hue = 60*(((tB/255)-(tR/255))/((tG/255) - (tR/255)))+120; 00280 //orange saturation (of HSL) 00281 float orange_sat = ((200.0/255.0)-(70/255.0))/(2.0-(270.0/255.0));//using tR,tG,tB, R,B,G gives '1' 00282 00283 std::cout<<"orange hue is: "<<orange_hue<<std::endl; 00284 std::cout<<"orange saturation(purity) is: "<<orange_sat<<std::endl; 00285 std::cout<<"orange HSV saturation is: "<<(1.0-70.0/200.0)<<std::endl; 00286 // LINFO("orange values (RGB):(std RGB): %f, %f, %f: %f, %f, %f", R, G, B, tR, tG, tB); 00287 00288 while (iptr != stop) 00289 { 00290 float hue = 0.0; 00291 float s = 0.0; //saturation 00292 float avgR = (*iptr).red(); 00293 float avgG = (*iptr).green(); 00294 float avgB = (*iptr).blue(); 00295 float r = avgR/255; 00296 float g = avgG/255; 00297 float b = avgB/255; 00298 00299 00300 00301 00302 //do conversion to HSV to find the hue 00303 float max = 0; 00304 float min = 1; 00305 //find max 00306 if(r > max) { max = r;} 00307 if(g > max) { max = g;} 00308 if(b > max) { max = b;} 00309 //find min 00310 if(r < min){min = r;} 00311 if(g < min){min = g;} 00312 if(b < min){min = b;} 00313 00314 //do conversion to find hue 00315 if(max == min) {hue = 0.0;} 00316 else if(max == r && g >= b) {hue = 60.0*((g-b)/(max - min)) + 0.0;} 00317 else if(max == r && g < b) {hue = 60.0*((g-b)/(max - min)) + 360.0;} 00318 else if(max == g) {hue = 60.0*((b-r)/(max-min))+120.0;} 00319 else if(max == b) {hue = 60.0*((r-g)/(max-min))+240.0;} 00320 00321 00322 //for average calculation 00323 totalHue += hue; 00324 numTotal++; 00325 00326 //find saturation 00327 if(max){s = max;} 00328 if(max != 0){s = 1 - min/max;} 00329 //std::cout<<" "<<hue; 00330 if(hue == orange_hue)//result:get spects here and there 00331 { 00332 //(*optr) = (byte)255; // orange 00333 //orangeCount++; 00334 } 00335 if(hue == pure_orange_hue)//result:nothing 00336 { 00337 //(*optr) = (byte)255; // orange 00338 //orangeCount++; 00339 } 00340 //to reason these numbers 145 is about the value of orange hue 00341 //pretty good but with spects, "s != 1" gets rid of specs, but also takes out some of the pipe 00342 //value of 120 to 145 seems best 00343 //using 130 as min makes it less accurate 00344 //using a higher max does not seem to make a difference 00345 //probably because of the colors involved here 00346 if(!(120<hue && hue<146) && 00347 s != 1) 00348 { 00349 //std::cout<<" "<<s; 00350 (*optr) = (byte)255; // orange 00351 orangeCount++; 00352 } 00353 00354 //float avg = (avgR+avgG+avgB)/3.0; 00355 //float sigma = pow(avgR - avg, 2.) + pow(avgG - avg, 2.) + pow(avgB - avg, 2.); 00356 //float stdDev = sqrt( (1./3.) * sigma ); 00357 00358 //result: pretty good but is confused by highlights 00359 if (avgR > R - tR && avgR < R + tR && 00360 avgG > G - tG && avgG < G + tG && 00361 avgB > B - tB && avgB < B + tB ) 00362 { 00363 (*optr) = (byte)255; // orange 00364 orangeCount++; 00365 } 00366 // else 00367 // { 00368 // //if(outputImage.coordsOk(i,j)){ 00369 // //(*optr) = (byte)0; //not orange 00370 // //} 00371 // } 00372 iptr++; optr++; 00373 00374 } 00375 00376 //display image to compare to what we get with the color segmenter 00377 00378 Image<PixRGB<byte> > Aux; 00379 Aux.resize(100,450,true); 00380 00381 /******************************************************************/ 00382 // SEGMENT IMAGE ON EACH INPUT FRAME 00383 00384 segmenter->SITtrackImageAny(h2svImage,&inputImage,&Aux,true); 00385 00386 /* Retrieve and Draw all our output images */ 00387 Image<byte> temp = quickInterpolate(segmenter->SITreturnCandidateImage(),4); 00388 //display for now for testing purposes 00389 //wini->drawImage(display); 00390 wino->drawImage(temp); 00391 00392 std::cout<<"average hue was "<<totalHue/numTotal<<std::endl; 00393 return float(orangeCount)/float( (inputImage.getHeight() * inputImage.getWidth())); 00394 } 00395 00396 00397 00398 00399