Now you can download a copy of these docs so you can use them offline! Download now
TrackAPI.cpp
00001 /******************************************************************************** 00002 * Project : FIRST Motor Controller 00003 * File Name : TrackAPI.cpp 00004 * Contributors : ELF, DWD 00005 * Creation Date : August 10, 2008 00006 * Revision History : Source code & revision history maintained at sourceforge.WPI.edu 00007 * File Description : Tracking Routines for FIRST Vision API 00008 */ 00009 /*----------------------------------------------------------------------------*/ 00010 /* Copyright (c) FIRST 2008. All Rights Reserved. */ 00011 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00012 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00013 /*----------------------------------------------------------------------------*/ 00014 00015 #include "string.h" 00016 #include "vxWorks.h" 00017 00018 #include "AxisCamera.h" 00019 #include "FrcError.h" 00020 #include "TrackAPI.h" 00021 #include "VisionAPI.h" 00022 00023 int TrackAPI_debugFlag = 0; 00024 #define DPRINTF if(TrackAPI_debugFlag)dprintf 00025 00032 bool InArea(Image* binaryImage, int particleIndex, Rect rect) 00033 { 00034 double position; 00035 00036 imaqMeasureParticle(binaryImage, particleIndex, 0, 00037 IMAQ_MT_BOUNDING_RECT_LEFT, &position); 00038 if ( position < (rect.left ) ) return false; // outside left of rectangle? 00039 00040 imaqMeasureParticle(binaryImage, particleIndex, 0, 00041 IMAQ_MT_BOUNDING_RECT_TOP, &position); 00042 if ( position < (rect.top ) ) return false; // outside top of rectangle ? 00043 00044 imaqMeasureParticle(binaryImage, particleIndex, 0, 00045 IMAQ_MT_BOUNDING_RECT_RIGHT, &position); 00046 if (position > (rect.left + rect.width) ) return false; // outside right of rectangle ? 00047 00048 imaqMeasureParticle(binaryImage, particleIndex, 0, 00049 IMAQ_MT_BOUNDING_RECT_BOTTOM, &position); 00050 if (position > (rect.top + rect.height) ) return false; // outside bottom of rectangle ? 00051 00052 DPRINTF(LOG_INFO, "particle %i is in (%i %i) height %i width %i\n", 00053 particleIndex, rect.left, rect.top, rect.height, rect.width); 00054 return true; 00055 } 00056 00064 int GetLargestParticle(Image* binaryImage, int* largestParticleIndex) 00065 { return GetLargestParticle(binaryImage, largestParticleIndex, IMAQ_NO_RECT); } 00066 00067 int GetLargestParticle(Image* binaryImage, int* largestParticleIndex, Rect rect) 00068 { 00069 *largestParticleIndex = 0; // points to caller-provided variable 00070 00071 /* determine number of particles in thresholded image */ 00072 int numParticles; 00073 int success = frcCountParticles(binaryImage, &numParticles); 00074 if ( !success ) { return success; } 00075 00076 /* if no particles found we can quit here */ 00077 if (numParticles == 0) { return 0; } // unsuccessful if zero particles found 00078 00079 // find the largest particle 00080 double largestParticleArea = 0; 00081 double particleArea; 00082 for (int i = 0; i < numParticles; ++i) { 00083 success = imaqMeasureParticle(binaryImage, i, 0, IMAQ_MT_AREA, &particleArea); 00084 if ( !success ) { return success; } 00085 if (particleArea > largestParticleArea) { 00086 // see if is in the right area 00087 if ( InArea(binaryImage, i, rect) ) { 00088 largestParticleArea = particleArea; 00089 *largestParticleIndex = i; // return index to caller 00090 } 00091 } 00092 } 00093 00094 return success; 00095 } 00096 00103 int FindColor(FrcHue color, ParticleAnalysisReport* trackReport) 00104 { 00105 int success = 0; // return: 0 = error 00106 00107 /* track color */ 00108 // use ACTIVE_LIGHT or WHITE_LIGHT for brightly lit objects 00109 TrackingThreshold td = GetTrackingData(color, PASSIVE_LIGHT); 00110 00111 success = FindColor(IMAQ_HSL, &td.hue, &td.saturation, &td.luminance, trackReport); 00112 if ( !success ) { 00113 DPRINTF (LOG_INFO, "did not find color - errorCode= %i",GetLastVisionError()); 00114 return success; 00115 } 00116 00117 //PrintReport(par); 00118 00119 /* set an image quality restriction */ 00120 if (trackReport->particleToImagePercent < PARTICLE_TO_IMAGE_PERCENT) { 00121 imaqSetError(ERR_PARTICLE_TOO_SMALL, __FUNCTION__); 00122 success = 0; 00123 } 00124 return success; 00125 } 00126 00133 int FindColor(const Range* hueRange, ParticleAnalysisReport *trackReport) 00134 { return FindColor(hueRange, DEFAULT_SATURATION_THRESHOLD, trackReport); } 00135 00143 int FindColor(const Range* hueRange, int minSaturation, ParticleAnalysisReport *trackReport) 00144 { 00145 Range satRange; 00146 satRange.minValue = minSaturation; 00147 satRange.maxValue = 255; 00148 Range lumRange; 00149 lumRange.minValue = 0; 00150 lumRange.maxValue = 255; 00151 ColorMode cmode = IMAQ_HSL; 00152 return FindColor(cmode, hueRange, &satRange, &lumRange, trackReport); 00153 } 00154 00164 int FindColor(ColorMode mode, const Range* plane1Range, const Range* plane2Range, 00165 const Range* plane3Range, ParticleAnalysisReport *trackReport) 00166 { 00167 return FindColor(mode, plane1Range, plane2Range, plane3Range, trackReport, NULL); 00168 } 00169 00180 int FindColor(ColorMode mode, const Range* plane1Range, const Range* plane2Range, 00181 const Range* plane3Range, ParticleAnalysisReport *trackReport, 00182 ColorReport *colorReport) 00183 { 00184 return FindColor(mode, plane1Range, plane2Range, plane3Range, trackReport, 00185 NULL, IMAQ_NO_RECT); 00186 } 00187 00199 int FindColor(ColorMode mode, const Range* plane1Range, const Range* plane2Range, 00200 const Range* plane3Range, ParticleAnalysisReport *trackReport, 00201 ColorReport *colorReport, Rect rect) 00202 { 00203 int errorCode = 0; 00204 int success = 0; 00205 00206 /* create an image object */ 00207 Image* cameraImage = frcCreateImage(IMAQ_IMAGE_HSL); 00208 if (!cameraImage) { return success; } 00209 00210 /* get image from camera - if the camera has not finished initializing, 00211 * this will fail 00212 */ 00213 double imageTime; 00214 success = GetImage(cameraImage, &imageTime); 00215 if (!success){ 00216 DPRINTF(LOG_INFO, "No camera Image available Error = %i %s", 00217 errorCode, GetVisionErrorText(errorCode)); 00218 frcDispose(cameraImage); 00219 imaqSetError(errorCode, __FUNCTION__); //reset error code for the caller 00220 return success; 00221 } 00222 00223 /* save a copy of the image to another image for color thresholding later */ 00224 Image* histImage = frcCreateImage(IMAQ_IMAGE_HSL); 00225 if (!histImage) { frcDispose(cameraImage); return success; } 00226 success = frcCopyImage(histImage,cameraImage); 00227 if ( !success ) { 00228 errorCode = GetLastVisionError(); 00229 frcDispose(__FUNCTION__,cameraImage,histImage,NULL); 00230 return success; 00231 } 00232 00233 /* Color threshold the image */ 00234 success = frcColorThreshold(cameraImage, cameraImage, mode, plane1Range, plane2Range, plane3Range); 00235 if ( !success ) { 00236 errorCode = GetLastVisionError(); 00237 DPRINTF (LOG_DEBUG, "Error = %i %s ", errorCode, GetVisionErrorText(errorCode)); 00238 frcDispose(__FUNCTION__,cameraImage,histImage,NULL); 00239 return success; 00240 } 00241 00242 int largestParticleIndex = 0; 00243 success = GetLargestParticle(cameraImage, &largestParticleIndex, rect ); 00244 if ( !success ) { 00245 errorCode = GetLastVisionError(); 00246 DPRINTF (LOG_DEBUG, "Error after GetLargestParticle = %i %s ", errorCode, GetVisionErrorText(errorCode)); 00247 frcDispose(__FUNCTION__,cameraImage,histImage,NULL); 00248 imaqSetError(ERR_COLOR_NOT_FOUND, __FUNCTION__); 00249 return success; 00250 } 00251 DPRINTF(LOG_INFO, "largestParticleIndex = %i\n", largestParticleIndex); 00252 00253 /* Particles were found */ 00254 /* 00255 * Fill in report information for largest particle found 00256 */ 00257 success = frcParticleAnalysis(cameraImage, largestParticleIndex, trackReport); 00258 trackReport->imageTimestamp = imageTime; 00259 00260 /* clean up */ 00261 if (!success) {frcDispose(__FUNCTION__,cameraImage,histImage,NULL); return success;} 00262 00263 /* particle color statistics */ 00264 /* only if a color report requested */ 00265 if (colorReport != NULL) 00266 { 00267 /* first filter out the other particles */ 00268 ParticleFilterCriteria2 criteria; 00269 ParticleFilterOptions* options = NULL; 00270 Rect rect; 00271 int numParticles; 00272 success = frcParticleFilter(cameraImage, cameraImage, &criteria, 1, options, 00273 rect, &numParticles); 00274 if ( !success ) { 00275 DPRINTF(LOG_INFO, "frcParticleFilter errorCode %i", GetLastVisionError()); 00276 } 00277 00278 /* histogram the original image using the thresholded image as a mask */ 00279 int numClasses = 10; //how many classes? 00280 ColorHistogramReport* chrep = imaqColorHistogram2(histImage, numClasses, IMAQ_HSL, 00281 NULL, cameraImage); 00282 if (chrep == NULL) { 00283 DPRINTF(LOG_INFO, "NULL Color Histogram"); 00284 errorCode = GetLastVisionError(); 00285 } else { 00286 colorReport->particleHueMax = chrep->plane1.max; 00287 colorReport->particleHueMin = chrep->plane1.min; 00288 colorReport->particleHueMean = chrep->plane1.mean; 00289 colorReport->particleSatMax = chrep->plane2.max; 00290 colorReport->particleSatMin = chrep->plane2.min; 00291 colorReport->particleSatMean = chrep->plane2.mean; 00292 colorReport->particleLumMax = chrep->plane3.max; 00293 colorReport->particleLumMin = chrep->plane3.min; 00294 colorReport->particleLumMean = chrep->plane3.mean; 00295 colorReport->numberParticlesFound = numParticles; 00296 frcDispose(chrep); 00297 } 00298 } 00299 00300 /* clean up */ 00301 frcDispose(__FUNCTION__,cameraImage,histImage,NULL); 00302 00303 return success; 00304 } 00305 00306 00319 TrackingThreshold GetTrackingData(FrcHue hue, FrcLight light) 00320 { 00321 TrackingThreshold trackingData; 00322 00323 //set saturation & luminance 00324 switch (light) { 00325 default: 00326 case FLUORESCENT: 00327 trackingData.saturation.minValue = 100; 00328 trackingData.saturation.maxValue = 255; 00329 trackingData.luminance.minValue = 40; 00330 trackingData.luminance.maxValue = 255; 00331 if (hue == GREEN) trackingData.luminance.minValue = 100; 00332 if (hue == PINK) trackingData.saturation.minValue = 80; 00333 if (hue == PINK) trackingData.luminance.minValue = 60; 00334 if (hue == PINK) trackingData.luminance.maxValue = 155; 00335 break; 00336 case PASSIVE_LIGHT: 00337 trackingData.saturation.minValue = 50; 00338 trackingData.saturation.maxValue = 255; 00339 trackingData.luminance.minValue = 20; 00340 trackingData.luminance.maxValue = 255; 00341 break; 00342 case BRIGHT_LIGHT: 00343 trackingData.saturation.minValue = 0; 00344 trackingData.saturation.maxValue = 100; 00345 trackingData.luminance.minValue = 100; 00346 trackingData.luminance.maxValue = 255; 00347 break; 00348 case ACTIVE_LIGHT: 00349 trackingData.saturation.minValue = 0; 00350 trackingData.saturation.maxValue = 50; 00351 trackingData.luminance.minValue = 150; 00352 trackingData.luminance.maxValue = 255; 00353 break; 00354 case WHITE_LIGHT: 00355 trackingData.saturation.minValue = 0; 00356 trackingData.saturation.maxValue = 20; 00357 trackingData.luminance.minValue = 200; 00358 trackingData.luminance.maxValue = 255; 00359 break; 00360 } 00361 00362 //set hue 00363 switch (hue){ 00364 default: 00365 case WHITE: 00366 strcpy (trackingData.name, "WHITE"); 00367 trackingData.hue.minValue = 0; 00368 trackingData.hue.maxValue = 255; 00369 break; 00370 case ORANGE: 00371 strcpy (trackingData.name, "ORANGE"); 00372 trackingData.hue.minValue = 5; 00373 trackingData.hue.maxValue = 25; 00374 break; 00375 case YELLOW: 00376 strcpy (trackingData.name, "YELLOW"); 00377 trackingData.hue.minValue = 30; 00378 trackingData.hue.maxValue = 50; 00379 break; 00380 case GREEN: 00381 strcpy (trackingData.name, "GREEN"); 00382 if (light == FLUORESCENT) { 00383 trackingData.hue.minValue = 60; 00384 trackingData.hue.maxValue = 110; 00385 } else { 00386 trackingData.hue.minValue = 90; 00387 trackingData.hue.maxValue = 125; 00388 } 00389 break; 00390 case BLUE: 00391 strcpy (trackingData.name, "BLUE"); 00392 trackingData.hue.minValue = 140; 00393 trackingData.hue.maxValue = 170; 00394 break; 00395 case PURPLE: 00396 strcpy (trackingData.name, "PURPLE"); 00397 trackingData.hue.minValue = 180; 00398 trackingData.hue.maxValue = 200; 00399 break; 00400 case PINK: 00401 strcpy (trackingData.name, "PINK"); 00402 trackingData.hue.minValue = 210; 00403 trackingData.hue.maxValue = 250; 00404 break; 00405 case RED: 00406 strcpy (trackingData.name, "RED"); 00407 trackingData.hue.minValue = 240; 00408 trackingData.hue.maxValue = 255; 00409 break; 00410 } 00411 return(trackingData); 00412 } 00413 00414 00419 void PrintReport(ParticleAnalysisReport* myReport) 00420 { 00421 dprintf(LOG_INFO, "particle analysis:\n %s%i %s%i\n %s%lf\n %s%i %s%i\n %s%g %s%g\n %s%g\n %s%i %s%i\n %s%i %s%i\n", 00422 "imageHeight = ", myReport->imageHeight, 00423 "imageWidth = ", myReport->imageWidth, 00424 "imageTimestamp = ", myReport->imageTimestamp, 00425 "center_mass_x = ", myReport->center_mass_x, 00426 "center_mass_y = ", myReport->center_mass_y, 00427 "center_mass_x_normalized = ", myReport->center_mass_x_normalized, 00428 "center_mass_y_normalized = ", myReport->center_mass_y_normalized, 00429 "particleArea = ", myReport->particleArea, 00430 "boundingRectangleTop = ", myReport->boundingRect.top, 00431 "boundingRectangleLeft = ", myReport->boundingRect.left, 00432 "boundingRectangleHeight = ", myReport->boundingRect.height, 00433 "boundingRectangleWidth = ", myReport->boundingRect.width); 00434 00435 dprintf(LOG_INFO, "quality statistics: \n %s%g %s%g \n", 00436 "particleToImagePercent = ", myReport->particleToImagePercent, 00437 "particleQuality = ", myReport->particleQuality); 00438 } 00439 00444 void PrintReport(ColorReport* myReport) 00445 { 00446 dprintf(LOG_INFO, "particle ranges for %i particles: ", 00447 "numberParticlesFound = ", myReport->numberParticlesFound); 00448 ; 00449 dprintf(LOG_INFO, "\n %s%f %s%f %s%f\n %s%f %s%f %s%f\n %s%f %s%f %s%f\n -------", 00450 "particleHueMax = ", myReport->particleHueMax, 00451 "particleHueMin = ", myReport->particleHueMin, 00452 "particleHueMean = ", myReport->particleHueMean, 00453 "particleSatMax = ", myReport->particleSatMax, 00454 "particleSatMin = ", myReport->particleSatMin, 00455 "particleSatMean = ", myReport->particleSatMean, 00456 "particleLumMax = ", myReport->particleLumMax, 00457 "particleLumMin = ", myReport->particleLumMin, 00458 "particleLumMean = ", myReport->particleLumMean); 00459 00460 } 00461 00466 void PrintReport(TrackingThreshold* myReport) 00467 { 00468 dprintf(LOG_INFO, "name of color: %s", myReport->name); 00469 00470 dprintf(LOG_INFO, "\n %s%i %s%i\n %s%i %s%i\n %s%i %s%i\n -------", 00471 "hueMin = ", myReport->hue.minValue, 00472 "hueMax = ", myReport->hue.maxValue, 00473 "satMin = ", myReport->saturation.minValue, 00474 "satMax = ", myReport->saturation.maxValue, 00475 "lumMin = ", myReport->luminance.minValue, 00476 "lumMax = ", myReport->luminance.maxValue ); 00477 00478 } 00479 00480 00481
Generated on Thu Jan 12 2012 22:35:24 for WPILibC++ by
1.7.1