Exemplo n.º 1
0
/**
 * \brief  Increment counters used to determine module values
 * \param  img
 * \param  reg
 * \param  tally
 * \param  xOrigin
 * \param  yOrigin
 * \param  mapWidth
 * \param  mapHeight
 * \param  dir
 * \return void
 */
void
TallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, int tally[][24], int xOrigin, int yOrigin, int mapWidth, int mapHeight, DmtxDirection dir)
{
   int extent, weight;
   int travelStep;
   int symbolRow, symbolCol;
   int mapRow, mapCol;
   int lineStart, lineStop;
   int travelStart, travelStop;
   int *line, *travel;
   int jumpThreshold;
   int darkOnLight;
   int color;
   int statusPrev, statusModule;
   int tPrev, tModule;

   assert(dir == DmtxDirUp || dir == DmtxDirLeft || dir == DmtxDirDown || dir == DmtxDirRight);

   travelStep = (dir == DmtxDirUp || dir == DmtxDirRight) ? 1 : -1;

   /* Abstract row and column progress using pointers to allow grid
      traversal in all 4 directions using same logic */

   if((dir & DmtxDirHorizontal) != 0x00) {
      line = &symbolRow;
      travel = &symbolCol;
      extent = mapWidth;
      lineStart = yOrigin;
      lineStop = yOrigin + mapHeight;
      travelStart = (travelStep == 1) ? xOrigin - 1 : xOrigin + mapWidth;
      travelStop = (travelStep == 1) ? xOrigin + mapWidth : xOrigin - 1;
   }
   else {
      assert(dir & DmtxDirVertical);
      line = &symbolCol;
      travel = &symbolRow;
      extent = mapHeight;
      lineStart = xOrigin;
      lineStop = xOrigin + mapWidth;
      travelStart = (travelStep == 1) ? yOrigin - 1: yOrigin + mapHeight;
      travelStop = (travelStep == 1) ? yOrigin + mapHeight : yOrigin - 1;
   }


   darkOnLight = (int)(reg->offColor > reg->onColor);
   jumpThreshold = abs((int)(0.4 * (reg->offColor - reg->onColor) + 0.5));

   assert(jumpThreshold >= 0);

   for(*line = lineStart; *line < lineStop; (*line)++) {

      /* Capture tModule for each leading border module as normal but
         decide status based on predictable barcode border pattern */

      *travel = travelStart;
      color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane);
      tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor;

      statusModule = (travelStep == 1 || (*line & 0x01) == 0) ? DmtxModuleOnRGB : DmtxModuleOff;

      weight = extent;

      while((*travel += travelStep) != travelStop) {

         tPrev = tModule;
         statusPrev = statusModule;

         /* For normal data-bearing modules capture color and decide
            module status based on comparison to previous "known" module */

         color = ReadModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane);
         tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor;

         if(statusPrev == DmtxModuleOnRGB) {
            if(tModule < tPrev - jumpThreshold)
               statusModule = DmtxModuleOff;
            else
               statusModule = DmtxModuleOnRGB;
         }
         else if(statusPrev == DmtxModuleOff) {
            if(tModule > tPrev + jumpThreshold)
               statusModule = DmtxModuleOnRGB;
            else
               statusModule = DmtxModuleOff;
         }

         mapRow = symbolRow - yOrigin;
         mapCol = symbolCol - xOrigin;
         assert(mapRow < 24 && mapCol < 24);

         if(statusModule == DmtxModuleOnRGB)
            tally[mapRow][mapCol] += (2 * weight);

         weight--;
      }

      assert(weight == 0);
   }
}
Exemplo n.º 2
0
/**
 * @brief  XXX
 * @param  image
 * @param  reg
 * @return DMTX_SUCCESS | DMTX_FAILURE
 */
static int
MatrixRegionFindSize(DmtxImage *image, DmtxRegion *reg)
{
   int sizeIdx;
   int errors[30] = { 0 };
   int minErrorsSizeIdx;
   int row, col, symbolRows, symbolCols;
   double tOff, tOn, jumpThreshold;
   DmtxColor3 colorOn, colorOff;
   DmtxColor3 colorOnAvg, colorOffAvg;
   DmtxColor3 black = { 0.0, 0.0, 0.0 };
   DmtxGradient gradient, testGradient;
   int sizeIdxAttempts[] = { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,
                             13, 29, 12, 11, 10, 28, 27,  9, 25,  8,
                             26,  7,  6,  5,  4, 24,  3,  2,  1,  0 };
   int *ptr;

   /* First try all sizes to determine which sizeIdx with best contrast */
   ptr = sizeIdxAttempts;
   gradient.tMin = gradient.tMid = gradient.tMax = 0;
   do {
      sizeIdx = *ptr;
      symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx);
      symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx);

      colorOnAvg = colorOffAvg = black;

      for(row = 0, col = 0; col < symbolCols; col++) {
         colorOn = ReadModuleColor(image, reg, row, col, sizeIdx);
         colorOff = ReadModuleColor(image, reg, row-1, col, sizeIdx);
         dmtxColor3AddTo(&colorOnAvg, &colorOn);
         dmtxColor3AddTo(&colorOffAvg, &colorOff);
      }

      for(row = 0, col = 0; row < symbolRows; row++) {
         colorOn = ReadModuleColor(image, reg, row, col, sizeIdx);
         colorOff = ReadModuleColor(image, reg, row, col-1, sizeIdx);
         dmtxColor3AddTo(&colorOnAvg, &colorOn);
         dmtxColor3AddTo(&colorOffAvg, &colorOff);
      }

      dmtxColor3ScaleBy(&colorOnAvg, 1.0/(symbolRows + symbolCols));
      dmtxColor3ScaleBy(&colorOffAvg, 1.0/(symbolRows + symbolCols));

      testGradient.ray.p = colorOffAvg;
      dmtxColor3Sub(&testGradient.ray.c, &colorOnAvg, &colorOffAvg);
      if(dmtxColor3Mag(&testGradient.ray.c) < 20)
         continue;

      dmtxColor3Norm(&testGradient.ray.c);
      testGradient.tMin = 0;
      testGradient.tMax = dmtxDistanceAlongRay3(&testGradient.ray, &colorOnAvg);
      testGradient.tMid = (testGradient.tMin + testGradient.tMax) / 2.0;

      if(testGradient.tMax > gradient.tMax)
         gradient = testGradient;
   } while(*(ptr++) != 0);

   jumpThreshold = 0.4 * (gradient.tMax - gradient.tMin);
   if(jumpThreshold < 20)
      return DMTX_FAILURE;

   /* Start with largest possible pattern size and work downward.  If done
      in other direction then false positive is possible. */

   ptr = sizeIdxAttempts;
   minErrorsSizeIdx = *ptr;
   do {
      sizeIdx = *ptr;
      symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, sizeIdx);
      symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, sizeIdx);

      /* Test each pair of ON/OFF modules in the calibration bars */

      /* Top calibration row */
      row = symbolRows - 1;
      for(col = 0; col < symbolCols; col += 2) {
         colorOff = ReadModuleColor(image, reg, row, col + 1, sizeIdx);
         tOff = dmtxDistanceAlongRay3(&gradient.ray, &colorOff);
         colorOn = ReadModuleColor(image, reg, row, col, sizeIdx);
         tOn = dmtxDistanceAlongRay3(&gradient.ray, &colorOn);

         if(tOn - tOff < jumpThreshold)
            errors[sizeIdx]++;

         if(errors[sizeIdx] > errors[minErrorsSizeIdx])
            break;
      }

      /* Right calibration column */
      col = symbolCols - 1;
      for(row = 0; row < symbolRows; row += 2) {
         colorOff = ReadModuleColor(image, reg, row + 1, col, sizeIdx);
         tOff = dmtxDistanceAlongRay3(&gradient.ray, &colorOff);
         colorOn = ReadModuleColor(image, reg, row, col, sizeIdx);
         tOn = dmtxDistanceAlongRay3(&gradient.ray, &colorOn);

         if(tOn - tOff < jumpThreshold)
            errors[sizeIdx]++;

         if(errors[sizeIdx] > errors[minErrorsSizeIdx])
            break;
      }

      /* Track of which sizeIdx has the fewest errors */
      if(errors[sizeIdx] < errors[minErrorsSizeIdx])
         minErrorsSizeIdx = sizeIdx;

   } while(*(ptr++) != 0);

   reg->gradient = gradient;
   reg->sizeIdx = minErrorsSizeIdx;

   reg->symbolRows = dmtxGetSymbolAttribute(DmtxSymAttribSymbolRows, reg->sizeIdx);
   reg->symbolCols = dmtxGetSymbolAttribute(DmtxSymAttribSymbolCols, reg->sizeIdx);
   reg->mappingRows = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixRows, reg->sizeIdx);
   reg->mappingCols = dmtxGetSymbolAttribute(DmtxSymAttribMappingMatrixCols, reg->sizeIdx);

   if(errors[minErrorsSizeIdx] >= 4)
      return DMTX_FAILURE;

   return DMTX_SUCCESS;
}