A Bounding Box helper class
Example #1
0
 public DetectionResult(BarcodeMetadata metadata, BoundingBox box)
 {
    Metadata = metadata;
    Box = box;
    ColumnCount = metadata.ColumnCount;
    DetectionResultColumns = new DetectionResultColumn[ColumnCount + 2];
 }
 public DetectionResult(BarcodeMetadata metadata, BoundingBox box)
 {
    this.Metadata = metadata;
    this.Box = box;
    this.ColumnCount = metadata.ColumnCount;
    this.DetectionResultColumns = new DetectionResultColumn[ColumnCount + 2];
 }
 /// <summary>
 /// Gets the row indicator column.
 /// </summary>
 /// <returns>The row indicator column.</returns>
 /// <param name="image">Image.</param>
 /// <param name="boundingBox">Bounding box.</param>
 /// <param name="startPoint">Start point.</param>
 /// <param name="leftToRight">If set to <c>true</c> left to right.</param>
 /// <param name="minCodewordWidth">Minimum codeword width.</param>
 /// <param name="maxCodewordWidth">Max codeword width.</param>
 private static DetectionResultRowIndicatorColumn getRowIndicatorColumn(BitMatrix image,
                                                                        BoundingBox boundingBox,
                                                                        ResultPoint startPoint,
                                                                        bool leftToRight,
                                                                        int minCodewordWidth,
                                                                        int maxCodewordWidth)
 {
    DetectionResultRowIndicatorColumn rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);
    for (int i = 0; i < 2; i++)
    {
       int increment = i == 0 ? 1 : -1;
       int startColumn = (int) startPoint.X;
       for (int imageRow = (int) startPoint.Y; imageRow <= boundingBox.MaxY &&
                                               imageRow >= boundingBox.MinY; imageRow += increment)
       {
          Codeword codeword = detectCodeword(image, 0, image.Width, leftToRight, startColumn, imageRow,
                                             minCodewordWidth, maxCodewordWidth);
          if (codeword != null)
          {
             rowIndicatorColumn.setCodeword(imageRow, codeword);
             if (leftToRight)
             {
                startColumn = codeword.StartX;
             }
             else
             {
                startColumn = codeword.EndX;
             }
          }
       }
    }
    return rowIndicatorColumn;
 }
Example #4
0
 /// <summary>
 /// Creates the specified box.
 /// </summary>
 /// <param name="box">The box.</param>
 /// <returns></returns>
 public static BoundingBox Create(BoundingBox box)
 {
     return new BoundingBox(box.image, box.TopLeft, box.BottomLeft, box.TopRight, box.BottomRight);
 }
Example #5
0
 /// <summary>
 /// Merge two Bounding Boxes, getting the left corners of left, and the right corners of right
 /// (Images should be the same)
 /// </summary>
 /// <param name="leftBox">Left.</param>
 /// <param name="rightBox">Right.</param>
 internal static BoundingBox merge(BoundingBox leftBox, BoundingBox rightBox)
 {
     if (leftBox == null)
         return rightBox;
     if (rightBox == null)
         return leftBox;
     return new BoundingBox(leftBox.image, leftBox.TopLeft, leftBox.BottomLeft, rightBox.TopRight, rightBox.BottomRight);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
 /// </summary>
 /// <param name="box">Box.</param>
 public BoundingBox(BoundingBox box)
     : this(box.Image, box.TopLeft,box.BottomLeft, box.TopRight, box.BottomRight)
 {
 }
 /// <summary>
 /// Merge two Bounding Boxes, getting the left corners of left, and the right corners of right
 /// (Images should be the same)
 /// </summary>
 /// <param name="left">Left.</param>
 /// <param name="right">Right.</param>
 internal static BoundingBox Merge(BoundingBox left, BoundingBox right)
 {
     if (left == null)
         return right;
     if (right == null)
         return left;
     return new BoundingBox(left.Image, left.TopLeft, left.BottomLeft, right.TopRight, right.BottomRight);
 }
      // TODO convert this to a dictionary? Dictionary<imageRow, Codeword> ??

      /// <summary>
      /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.DetectionResultColumn"/> class.
      /// </summary>
      /// <param name="box">The Bounding Box around the column (in the BitMatrix)</param>
      public DetectionResultColumn(BoundingBox box)
      {
         this.Box = BoundingBox.Create(box);
         this.Codewords = new Codeword[Box.MaxY - Box.MinY + 1];
      }
 /// <summary>
 /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.DetectionResultRowIndicatorColumn"/> class.
 /// </summary>
 /// <param name="box">Box.</param>
 /// <param name="isLeft">If set to <c>true</c> is left.</param>
 public DetectionResultRowIndicatorColumn(BoundingBox box, bool isLeft)
    : base(box)
 {
    this.IsLeft = isLeft;
 }
        /// <summary>
        /// Decode the specified image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth
        /// and maxCodewordWidth.
        /// TODO: don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern
        /// columns. That way width can be deducted from the pattern column.
        /// This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider 
        /// than it should be. This can happen if the scanner used a bad blackpoint.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="imageTopLeft">Image top left.</param>
        /// <param name="imageBottomLeft">Image bottom left.</param>
        /// <param name="imageTopRight">Image top right.</param>
        /// <param name="imageBottomRight">Image bottom right.</param>
        /// <param name="minCodewordWidth">Minimum codeword width.</param>
        /// <param name="maxCodewordWidth">Max codeword width.</param>
        public static DecoderResult Decode(BitMatrix image,
                                           ResultPoint imageTopLeft,
                                           ResultPoint imageBottomLeft,
                                           ResultPoint imageTopRight,
                                           ResultPoint imageBottomRight,
                                           int minCodewordWidth,
                                           int maxCodewordWidth)
        {
            BoundingBox boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);
            DetectionResultRowIndicatorColumn leftRowIndicatorColumn = null;
            DetectionResultRowIndicatorColumn rightRowIndicatorColumn = null;
            DetectionResult detectionResult = null;
            for (int i = 0; i < 2; i++)
            {
                if (imageTopLeft != null)
                {
                    leftRowIndicatorColumn = GetRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);
                    //Log.WriteLine("Before setRowNumbers\n" + leftRowIndicatorColumn);
                    leftRowIndicatorColumn.SetRowNumbers();
                    //Log.WriteLine("After setRowNumbers\n" + leftRowIndicatorColumn);
                }
                if (imageTopRight != null)
                {
                    rightRowIndicatorColumn = GetRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);
                    //Log.WriteLine("Before setRowNumbers\n" + rightRowIndicatorColumn);
                    rightRowIndicatorColumn.SetRowNumbers();
                    //Log.WriteLine("After setRowNumbers\n" + rightRowIndicatorColumn);
                }
                detectionResult = Merge(leftRowIndicatorColumn, rightRowIndicatorColumn);
                if (detectionResult == null)
                {
                    // TODO Based on Owen's Comments in <see cref="ZXing.ReaderException"/>, this method has been modified to continue silently
                    // if a barcode was not decoded where it was detected instead of throwing a new exception object.
                    // return null;
                    throw ReaderException.Instance;
                }
                if (i == 0 &&
                    (detectionResult.Box.MinY < boundingBox.MinY || detectionResult.Box.MaxY > boundingBox.MaxY))
                {
                    boundingBox = detectionResult.Box;
                } else
                {
                    detectionResult.Box = boundingBox;
                    break;
                }
            }
            int maxBarcodeColumn = detectionResult.ColumnCount + 1;
            detectionResult.DetectionResultColumns[0] = leftRowIndicatorColumn;

            detectionResult.DetectionResultColumns[maxBarcodeColumn] = rightRowIndicatorColumn;
            
            bool leftToRight = leftRowIndicatorColumn != null;
            for (int barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++)
            {
                int barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;
                if (detectionResult.DetectionResultColumns[barcodeColumn] != null)
                {
                    // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.
                    continue;
                }
                DetectionResultColumn detectionResultColumn;
                if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn)
                {
                    detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn == 0);
                } else
                {
                    detectionResultColumn = new DetectionResultColumn(boundingBox);
                }
                detectionResult.DetectionResultColumns[barcodeColumn] = detectionResultColumn;
                int startColumn = -1;
                int previousStartColumn = startColumn;
                // TODO start at a row for which we know the start position, then detect upwards and downwards from there.
                for (int imageRow = boundingBox.MinY; imageRow <= boundingBox.MaxY; imageRow++)
                {
                    startColumn = GetStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);
                    if (startColumn < 0 || startColumn > boundingBox.MaxX)
                    {
                        if (previousStartColumn == -1)
                        {
                            continue;
                        }
                        startColumn = previousStartColumn;
                    }
                    Codeword codeword = DetectCodeword(image, boundingBox.MinX, boundingBox.MaxX, leftToRight,
                                                       startColumn, imageRow, minCodewordWidth, maxCodewordWidth);
                    if (codeword != null)
                    {
                        detectionResultColumn.SetCodeword(imageRow, codeword);
                        previousStartColumn = startColumn;
                        minCodewordWidth = Math.Min(minCodewordWidth, codeword.Width);
                        maxCodewordWidth = Math.Max(maxCodewordWidth, codeword.Width);
                    }
                }
            }
            return CreateDecoderResult(detectionResult);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.DetectionResultRowIndicatorColumn"/> class.
 /// </summary>
 /// <param name="box">Box.</param>
 /// <param name="isLeft">If set to <c>true</c> is left.</param>
 public DetectionResultRowIndicatorColumn(BoundingBox box, bool isLeft)
     : base(box)
 {
     this.IsLeft = isLeft;
     this.Codewords = new Codeword[box.MaxY - box.MinY + 1];
 }