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 }