Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Modules/SpecialVision/BarCodeReader.cpp

Go to the documentation of this file.
00001 /**
00002 * @file BarCodeReader.cpp
00003 * 
00004 * Implementation of class BarCodeReader
00005 *
00006 * @author <A href=mailto:goehring@informatik.hu-berlin.de>Daniel Göhring</A>
00007 */
00008 
00009 #include "BarCodeReader.h"
00010 #include "Tools/Debugging/DebugImages.h"
00011 #include "Tools/Debugging/DebugDrawings.h"
00012 #include "Representations/Perception/SensorData.h"
00013 
00014 
00015 
00016 
00017 BarCodeReader::BarCodeReader(const SpecialVisionInterfaces& interfaces)
00018 : SpecialVision(interfaces)
00019 {
00020 }
00021 
00022 void BarCodeReader::execute()
00023 {
00024   //image;
00025 
00026 
00027   /** Declaration */
00028   // brightness values
00029 
00030   int avg;    // average brightness,is it necessary ???
00031   int max;   // max. brightness
00032   int min;   // min. brightness
00033   int upperInt;   // white bar lower boundary y - channel
00034   int lowerInt;   // black bar upper boundary y - channel
00035   
00036   
00037   // scan position values
00038   
00039   int l1;         // scan line variable
00040   int start;  // current scan column variable
00041   int over;   // black to white border column variable
00042   int fin;    // white to black border column variable - first block position
00043 
00044   
00045   // barcode properties, which must fulfill certain comstraints
00046   
00047   //int whiteDist = 3; //minimal expected white pixels between two black bars
00048   //int whiteCount = 0; // counts the white pixels 
00049   int width = 0;    // current bar distance
00050   int widthref = 0; // previous bar cluster length (from old start to next start)
00051   double succRat = 1.1; //width ratio tolerance between two succeeding blocks   //Var ends
00052 
00053 
00054   // barcode calculated values 
00055 
00056   int barValue[9];  // bit value interpreted while scanning
00057   int value = -1;   // calculated code value - if scanning succeeded
00058 
00059   
00060   // flags
00061 
00062   int brk = 0;    // scan error flag
00063 
00064 
00065   // Tools: PSD sensor
00066 
00067 //  double s = sensorData.data[SensorData::psd];
00068 
00069 
00070   
00071   /** Just for debugging */
00072   
00073   DECLARE_DEBUG_IMAGE(imageProcessorGradients); 
00074   INIT_DEBUG_IMAGE(imageProcessorGradients, image);
00075 
00076   ColorClassImage colIm;
00077   colorTable.generateColorClassImage(image,colIm);
00078 
00079   
00080     
00081   /** Scanbarcode starts */
00082   
00083   //OUTPUT(idText, text, "  LOS "); // 2 do: Channel check !!!
00084 
00085   
00086 
00087   for (l1 = 6; l1 < 144; l1 += 12) {
00088 
00089   /** Setting values */
00090 
00091   //reset brightness values  
00092   
00093   avg = 0;     // average brightness
00094   max = -1;    // max. brightness
00095   min = -1;    // min. brightness
00096 
00097   
00098   // scan position values
00099 
00100   start = 0;  // current scan column variable
00101   over = 0;   // black to white border column variable
00102   fin = 0;    // white to black border column variable - first block position
00103 
00104   
00105   // barcode properties, which must fulfill certain comstraints
00106 
00107   //whiteCount = 0;  // counts the white pixels 
00108   width = 0;    // current bar distance
00109   widthref = 0; // previous bar cluster length (from old start to next start)
00110 
00111 
00112   // barcode calculated values 
00113 
00114   {for (int a = 0; a < 9; a++) {
00115     barValue[a] = -1;
00116     }
00117   }
00118   
00119   value = -1;
00120 
00121   // Error flag 
00122   
00123   brk = 0;    // if error, then switched to 1
00124 
00125 
00126   /** Calculate the y-channel boundaries min, max and avg */
00127 
00128   { for (int x = 62; x < 82; x++) {   // take a sample from the middle of the scan line
00129       
00130       avg += image.image[l1][0][x];
00131 
00132      // OUTPUT(idText, text, "Number: "<<x<<"  Wert " << image.image[l1][0][x] ); 
00133 
00134       if ((max == -1) || (max < image.image[l1][0][x])) {
00135           max = image.image[l1][0][x];
00136       }
00137 
00138       if ((min == -1) || (min > image.image[l1][0][x])) {
00139           min = image.image[l1][0][x];
00140       }
00141 
00142     }
00143   }
00144     
00145   avg /= 20;
00146 
00147   // min, max and avg calculated
00148   
00149   
00150   // set the error flag if illumination is not sufficient
00151   
00152   if ((max - min) < 50) {
00153     brk = 1;
00154   }
00155 
00156   
00157   // calculate the white and respectively black intervall boundary values
00158 
00159   upperInt = min + (max-min)*2/3;    // white bar lower boundary y - channel
00160   lowerInt = min + (max-min)*1/3;    // black bar upper boundary y - channel
00161   
00162 
00163   // DEBUG
00164   //OUTPUT(idText, text, "  min Helligkeit " << min  );  
00165   //OUTPUT(idText, text, "  avg Helligkeit " << avg  );  
00166   //OUTPUT(idText, text, "  max Helligkeit " << max  );  
00167 
00168   
00169 
00170   
00171 // scanning begins at leftmost position
00172   
00173 // scan for pixel not belonging to the code sheet
00174 
00175   while (((start+5) < image.cameraInfo.resolutionWidth) &&
00176          ((image.image[l1][0][start  ] <= upperInt) ||
00177           (image.image[l1][0][start+1] <= upperInt) ||
00178           (image.image[l1][0][start+2] <= upperInt) ||
00179           (image.image[l1][0][start+3] <= upperInt) ||
00180           (image.image[l1][0][start+4] <= upperInt))) {
00181               start++;
00182           } 
00183   
00184 // now at the beginning of the first white lane
00185   
00186  
00187 // scan for pixel until reaching the first black bar
00188   
00189   while ((((start+1) < image.cameraInfo.resolutionWidth) && (image.image[l1][0][start] > upperInt))) {
00190               start++;
00191             }
00192  
00193   //whiteCount = 0;
00194 
00195   //OUTPUT(idText, text, "first black after " << start << " imw " << image.cameraInfo.resolutionWidth);
00196   
00197 
00198   
00199 
00200 // found the black first bar
00201 
00202 
00203 /** now loop eight times for the expected 8 code bars */
00204        
00205   
00206   for (int b = 0; b < 9; b++) {
00207         
00208       DEBUG_IMAGE_SET_PIXEL_GREEN(imageProcessorGradients, start, l1);  
00209       CIRCLE(sketch, start, l1, 4, 1, 1, Drawings::red);
00210 
00211       fin = start; // remember the start of the black line in 'fin'
00212 
00213       
00214       // measure the black line thickness
00215 
00216       while ((((start+1) < image.cameraInfo.resolutionWidth) && (image.image[l1][0][start  ] <= lowerInt)) ||
00217              (((start+2) < image.cameraInfo.resolutionWidth) && (image.image[l1][0][start+1] <= lowerInt)))     
00218       {   
00219           start++;
00220       }
00221 
00222       // remember the end of the black lane in 'over'
00223       
00224       over = start;
00225 
00226 
00227       // measure the white line thickness
00228 
00229       while (((start + 3) < image.cameraInfo.resolutionWidth) && (
00230                 (image.image[l1][0][start  ] > upperInt) ||
00231                 (image.image[l1][0][start+1] > upperInt) ||
00232                 (image.image[l1][0][start+2] > upperInt)))
00233       { 
00234           start++;
00235       }
00236 
00237       
00238       // calculate the cluster thickness
00239       
00240       
00241       if (b == 8) 
00242       {
00243         width = over - fin;
00244         //whiteCount = 0;
00245       }
00246       else
00247       {
00248         width = start - fin;
00249         //whiteCount = 0;
00250       }
00251       
00252       // check if the cluster thickness is almost similar to the last cluster thickness
00253 
00254       if ((widthref == 0) || ((widthref <= width*succRat) && (widthref*succRat > width))) {
00255            widthref = width;
00256       }
00257       
00258       // if not - set error flag
00259       
00260       else {
00261            brk = 1;
00262            //OUTPUT(idText, text, "  Unequal border widths " << b+1 );
00263 
00264       }
00265 
00266       // calculate the cluster's bit value from the black/white ratio in the cluster
00267 
00268       if ((over - fin) < 0.40 * width)   
00269         {barValue[b] = 1;}    // we got a one
00270 
00271       else 
00272       if ((over - fin) > 0.60 * width)   
00273         {barValue[b] = 0;}    // we got a zero
00274 
00275       else
00276       {
00277         brk = 1;              // not a number - set error flag
00278       }
00279 
00280       //OUTPUT(idText, text, "  Bar Number " << b+1 << " at " << start << " value " << barValue[b]);
00281 
00282   }
00283 
00284 
00285   /** Checksum check*/
00286   
00287   if (((((barValue[0] + barValue[1] + barValue[2])%2)  == barValue[6]) ||
00288       (((barValue[3] + barValue[4] + barValue[5])%2)  == barValue[7])) && (brk == 0)  )
00289   {
00290     value = barValue[0]*32+barValue[1]*16+barValue[2]*8+barValue[3]*4+
00291             barValue[4]*2+barValue[5];
00292 
00293   // if CC passed -  calculate value
00294 
00295             //OUTPUT(idText, text, "  Value " << value  );  
00296             specialPercept.barCodeId = value;
00297   }  
00298   else
00299   {
00300             specialPercept.barCodeId = -1;
00301   // if not - set error flag and calculate nothing  
00302     
00303     //OUTPUT(idText, text, " Checksum error ");
00304 
00305     brk = 1;
00306   }
00307  
00308   
00309  if (!brk) {  
00310    
00311    /* if we got a value we can leave, otherwise make a further attempt in a
00312       new line  */
00313      break;
00314     }
00315   } 
00316 
00317 
00318   
00319 
00320   //OUTPUT(idText, text, "BarCodeReader::execute()");
00321 
00322   // DEBUG
00323   
00324   DEBUG_DRAWING_FINISHED(sketch);
00325   SEND_DEBUG_IMAGE(imageProcessorGradients);
00326 
00327 
00328 }
00329 
00330 /*
00331 * Change log :
00332 * 
00333 * $Log: BarCodeReader.cpp,v $
00334 * Revision 1.1.1.1  2004/05/22 17:22:25  cvsadm
00335 * created new repository GT2004_WM
00336 *
00337 * Revision 1.3  2004/03/08 02:11:53  roefer
00338 * Interfaces should be const
00339 *
00340 * Revision 1.2  2003/12/15 11:46:13  juengel
00341 * Introduced CameraInfo
00342 *
00343 * Revision 1.1  2003/10/06 14:10:13  cvsadm
00344 * Created GT2004 (M.J.)
00345 *
00346 * Revision 1.3  2003/09/26 15:27:48  juengel
00347 * Renamed DataTypes to representations.
00348 *
00349 * Revision 1.2  2003/09/01 10:20:11  juengel
00350 * DebugDrawings clean-up 2
00351 * DebugImages clean-up
00352 * MessageIDs clean-up
00353 * Stopwatch clean-up
00354 *
00355 * Revision 1.1.1.1  2003/07/02 09:40:24  cvsadm
00356 * created new repository for the competitions in Padova from the 
00357 * tamara CVS (Tuesday 2:00 pm)
00358 *
00359 * removed unused solutions
00360 *
00361 * Revision 1.9  2003/05/12 10:29:24  dueffert
00362 * unused variable warnings removed
00363 *
00364 * Revision 1.8  2003/03/31 16:54:48  goehring
00365 * Improved BarCodeReader with less Errors
00366 *
00367 * Revision 1.7  2003/03/06 11:37:17  dueffert
00368 * unused variable warning removed
00369 *
00370 * Revision 1.6  2003/02/21 18:32:04  roefer
00371 * pColorTable -> colorTable finished
00372 *
00373 * Revision 1.5  2003/02/18 21:29:17  osterhues
00374 * Changed all instances of ColorTable64 to new base class ColorTable
00375 *
00376 * Revision 1.4  2003/02/17 10:46:50  dueffert
00377 * warnings removed
00378 *
00379 * Revision 1.3  2003/02/07 19:26:45  goehring
00380 * Added Comments
00381 *
00382 * Revision 1.2  2003/02/05 19:20:30  goehring
00383 * BarCodeReader - Prototype
00384 *
00385 * Revision 1.1  2003/01/29 10:37:21  juengel
00386 * Added BarCodeReader.
00387 *
00388 *
00389 */

Generated on Thu Sep 23 19:57:32 2004 for GT2004 by doxygen 1.3.6