コード例 #1
0
ファイル: Detector.cs プロジェクト: smart-make/zxing
        /// <summary>
        /// Computes the y dimension (number of modules in a column) of the PDF417 Code
        /// based on vertices of the codeword area and estimated module size.
        /// </summary>
        /// <param name="topLeft">     of codeword area </param>
        /// <param name="topRight">    of codeword area </param>
        /// <param name="bottomLeft">  of codeword area </param>
        /// <param name="bottomRight"> of codeword are </param>
        /// <param name="moduleWidth"> estimated module size </param>
        /// <returns> the number of modules in a row. </returns>
        private static int computeYDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint bottomRight, float moduleWidth)
        {
            int leftColumnDimension  = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleWidth);
            int rightColumnDimension = MathUtils.round(ResultPoint.distance(topRight, bottomRight) / moduleWidth);

            return((leftColumnDimension + rightColumnDimension) >> 1);
        }
コード例 #2
0
ファイル: Detector.cs プロジェクト: smart-make/zxing
        /// <summary>
        /// Computes the dimension (number of modules in a row) of the PDF417 Code
        /// based on vertices of the codeword area and estimated module size.
        /// </summary>
        /// <param name="topLeft">     of codeword area </param>
        /// <param name="topRight">    of codeword area </param>
        /// <param name="bottomLeft">  of codeword area </param>
        /// <param name="bottomRight"> of codeword are </param>
        /// <param name="moduleWidth"> estimated module size </param>
        /// <returns> the number of modules in a row. </returns>
        private static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint bottomRight, float moduleWidth)
        {
            int topRowDimension    = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleWidth);
            int bottomRowDimension = MathUtils.round(ResultPoint.distance(bottomLeft, bottomRight) / moduleWidth);

            return(((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17);
        }
コード例 #3
0
        /// <summary>
        /// <p>Estimates module size (pixels in a module) based on the Start and End
        /// finder patterns.</p>
        ///
        /// <param name="vertices">an array of vertices:</param>
        ///           vertices[0] x, y top left barcode
        ///           vertices[1] x, y bottom left barcode
        ///           vertices[2] x, y top right barcode
        ///           vertices[3] x, y bottom right barcode
        ///           vertices[4] x, y top left codeword area
        ///           vertices[5] x, y bottom left codeword area
        ///           vertices[6] x, y top right codeword area
        ///           vertices[7] x, y bottom right codeword area
        /// <returns>the module size.</returns>
        /// </summary>
        private static float computeModuleWidth(ResultPoint[] vertices)
        {
            float pixels1      = ResultPoint.distance(vertices[0], vertices[4]);
            float pixels2      = ResultPoint.distance(vertices[1], vertices[5]);
            float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
            float pixels3      = ResultPoint.distance(vertices[6], vertices[2]);
            float pixels4      = ResultPoint.distance(vertices[7], vertices[3]);
            float moduleWidth2 = (pixels3 + pixels4) / (18 * 2.0f);

            return((moduleWidth1 + moduleWidth2) / 2.0f);
        }
コード例 #4
0
ファイル: Detector.cs プロジェクト: smart-make/zxing
        /// <summary>
        /// <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int computeDimension(com.google.zxing.ResultPoint topLeft, com.google.zxing.ResultPoint topRight, com.google.zxing.ResultPoint bottomLeft, float moduleSize) throws com.google.zxing.NotFoundException
        private static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize)
        {
            int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
            int dimension            = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;

            switch (dimension & 0x03)     // mod 4
            {
            case 0:
                dimension++;
                break;

            // 1? do nothing
            case 2:
                dimension--;
                break;

            case 3:
                throw NotFoundException.NotFoundInstance;
            }
            return(dimension);
        }
コード例 #5
0
        private static ResultPoint[] GetBarCodeRect(Point[] scanLine, ResultPoint[] whiterect, float dx)
        {
            ResultPoint pt0 = new ResultPoint(scanLine[0].X, scanLine[0].Y); // Начало линии сканирования (заканчивается за 3 штрихполоски до начала штрихкода)
            ResultPoint pt1 = new ResultPoint(scanLine[1].X, scanLine[1].Y); // Конец линии сканирования (заканчивается за 3 штрихполоски до конца штрихкода)

            // whiterect п/у ограничивающий одну или несколько полосок штрих кода,
            // сделаем его направленным, повернем вдоль скан линии, чтобы можно было ширину расширить
            whiterect = RotateRect(whiterect, scanLine);

            // Проекция точки x,y на найденную полоску штрихкода.
            ResultPoint proj = Projection(pt1, whiterect[1], whiterect[0]);
            float       vLen = ResultPoint.distance(pt1, proj);
            ResultPoint v    = new ResultPoint(pt1.X - proj.X, pt1.Y - proj.Y);

            // Вектор b перпендикулярный вектору a против часовой стрелки равен  b = (-ay, ax).
            // Найдем правую нормаль к вертикальной полоске
            float       height = ResultPoint.distance(whiterect[1], whiterect[0]);
            ResultPoint vOrto  = new ResultPoint(-(whiterect[1].Y - whiterect[0].Y) / height, (whiterect[1].X - whiterect[0].X) / height);

            var lastBarCodeLine = new ResultPoint[2] {
                new ResultPoint(whiterect[0].X + v.X - vOrto.X * dx, whiterect[0].Y + v.Y - vOrto.Y * dx),
                new ResultPoint(whiterect[1].X + v.X - vOrto.X * dx, whiterect[1].Y + v.Y - vOrto.Y * dx)
            };

            ResultPoint proj0            = Projection(pt0, whiterect[1], whiterect[0]);
            ResultPoint v0               = new ResultPoint(pt0.X - proj0.X, pt0.Y - proj0.Y);
            var         firstBarCodeLine = new ResultPoint[2] {
                new ResultPoint(whiterect[0].X + v0.X + vOrto.X * dx, whiterect[0].Y + v0.Y + vOrto.Y * dx),
                new ResultPoint(whiterect[1].X + v0.X + vOrto.X * dx, whiterect[1].Y + v0.Y + vOrto.Y * dx)
            };

            return(new ResultPoint[] {
                firstBarCodeLine[0],
                firstBarCodeLine[1],
                lastBarCodeLine[0],
                lastBarCodeLine[1]
            });
        }
コード例 #6
0
ファイル: Detector.cs プロジェクト: ibeae/ThinkAway.net
        /// <summary> <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
        protected internal static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize)
        {
            int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
            int dimension            = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;

            switch (dimension & 0x03)
            {
            // mod 4
            case 0:
                dimension++;
                break;
            // 1? do nothing

            case 2:
                dimension--;
                break;

            case 3:
                throw ReaderException.Instance;
            }
            return(dimension);
        }
コード例 #7
0
ファイル: Detector.cs プロジェクト: luismfonseca/appy-bpi
        /// <summary> <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
        private static bool computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize, out int dimension)
        {
            int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);

            dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
            switch (dimension & 0x03)
            {
            // mod 4
            case 0:
                dimension++;
                break;

            // 1? do nothing
            case 2:
                dimension--;
                break;

            case 3:
                return(true);
            }
            return(true);
        }
コード例 #8
0
        /// <summary>
        /// </summary>
        /// <returns>the 3 best <see cref="FinderPattern" />s from our list of candidates. The "best" are
        ///         those that have been detected at least CENTER_QUORUM times, and whose module
        ///         size differs from the average among those patterns the least
        /// </returns>
        private FinderPattern[][] selectMultipleBestPatterns()
        {
            List <FinderPattern> possibleCenters = PossibleCenters;
            int size = possibleCenters.Count;

            if (size < 3)
            {
                // Couldn't find enough finder patterns
                return(null);
            }

            /*
             * Begin HE modifications to safely detect multiple codes of equal size
             */
            if (size == 3)
            {
                return(new FinderPattern[][]
                {
                    new FinderPattern[]
                    {
                        possibleCenters[0],
                        possibleCenters[1],
                        possibleCenters[2]
                    }
                });
            }

            // Sort by estimated module size to speed up the upcoming checks
            possibleCenters.Sort(new ModuleSizeComparator());

            /*
             * Now lets start: build a list of tuples of three finder locations that
             *  - feature similar module sizes
             *  - are placed in a distance so the estimated module count is within the QR specification
             *  - have similar distance between upper left/right and left top/bottom finder patterns
             *  - form a triangle with 90° angle (checked by comparing top right/bottom left distance
             *    with pythagoras)
             *
             * Note: we allow each point to be used for more than one code region: this might seem
             * counterintuitive at first, but the performance penalty is not that big. At this point,
             * we cannot make a good quality decision whether the three finders actually represent
             * a QR code, or are just by chance layouted so it looks like there might be a QR code there.
             * So, if the layout seems right, lets have the decoder try to decode.
             */

            List <FinderPattern[]> results = new List <FinderPattern[]>(); // holder for the results

            for (int i1 = 0; i1 < (size - 2); i1++)
            {
                FinderPattern p1 = possibleCenters[i1];
                if (p1 == null)
                {
                    continue;
                }

                for (int i2 = i1 + 1; i2 < (size - 1); i2++)
                {
                    FinderPattern p2 = possibleCenters[i2];
                    if (p2 == null)
                    {
                        continue;
                    }

                    // Compare the expected module sizes; if they are really off, skip
                    float vModSize12 = (p1.EstimatedModuleSize - p2.EstimatedModuleSize) /
                                       Math.Min(p1.EstimatedModuleSize, p2.EstimatedModuleSize);
                    float vModSize12A = Math.Abs(p1.EstimatedModuleSize - p2.EstimatedModuleSize);
                    if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT)
                    {
                        // break, since elements are ordered by the module size deviation there cannot be
                        // any more interesting elements for the given p1.
                        break;
                    }

                    for (int i3 = i2 + 1; i3 < size; i3++)
                    {
                        FinderPattern p3 = possibleCenters[i3];
                        if (p3 == null)
                        {
                            continue;
                        }

                        // Compare the expected module sizes; if they are really off, skip
                        float vModSize23 = (p2.EstimatedModuleSize - p3.EstimatedModuleSize) /
                                           Math.Min(p2.EstimatedModuleSize, p3.EstimatedModuleSize);
                        float vModSize23A = Math.Abs(p2.EstimatedModuleSize - p3.EstimatedModuleSize);
                        if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT)
                        {
                            // break, since elements are ordered by the module size deviation there cannot be
                            // any more interesting elements for the given p1.
                            break;
                        }

                        FinderPattern[] test = { p1, p2, p3 };
                        ResultPoint.orderBestPatterns(test);

                        // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal
                        FinderPatternInfo info = new FinderPatternInfo(test);
                        float             dA   = ResultPoint.distance(info.TopLeft, info.BottomLeft);
                        float             dC   = ResultPoint.distance(info.TopRight, info.BottomLeft);
                        float             dB   = ResultPoint.distance(info.TopLeft, info.TopRight);

                        // Check the sizes
                        float estimatedModuleCount = (dA + dB) / (p1.EstimatedModuleSize * 2.0f);
                        if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE ||
                            estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE)
                        {
                            continue;
                        }

                        // Calculate the difference of the edge lengths in percent
                        float vABBC = Math.Abs((dA - dB) / Math.Min(dA, dB));
                        if (vABBC >= 0.1f)
                        {
                            continue;
                        }

                        // Calculate the diagonal length by assuming a 90° angle at topleft
                        float dCpy = (float)Math.Sqrt((double)dA * dA + (double)dB * dB);
                        // Compare to the real distance in %
                        float vPyC = Math.Abs((dC - dCpy) / Math.Min(dC, dCpy));

                        if (vPyC >= 0.1f)
                        {
                            continue;
                        }

                        // All tests passed!
                        results.Add(test);
                    } // end iterate p3
                }     // end iterate p2
            }         // end iterate p1

            if (results.Count != 0)
            {
                return(results.ToArray());
            }

            // Nothing found!
            return(null);
        }
コード例 #9
0
 // L2 distance
 private static int distance(ResultPoint a, ResultPoint b)
 {
     return(MathUtils.round(ResultPoint.distance(a, b)));
 }
コード例 #10
0
        /// <summary>
        /// Найти штрихкод code128 и его ограничивающий п/у
        /// </summary>
        /// <param name="fileName">Имя файла с картинкой png, jpeg</param>
        public static BarcodeResult ScanCode128(Image img, string debugFileName = null)
        {
            BarcodeResult barcodeResult = null;

            Bitmap bmp = new Bitmap(img);

            // create a barcode reader instance
            var reader = new BarcodeReader();

            reader.Options.ReturnCodabarStartEnd = true;
            reader.Options.TryHarder             = true;
            reader.Options.PossibleFormats       = new BarcodeFormat[] { BarcodeFormat.CODE_128 };
            reader.AutoRotate = true;

            // Сейчас код ищет только один штрихкод.
            // Найти несколько штрихкодов можно с помощью метода DecodeMultiple, но по умолчанию возвращаются только разные штрихкоды.
            // Если мы хотим получить положение одного и того же штрихкода вставленного несколько раз, то нужно будет переписывать метод DecodeMultiple.
            // Есть ещё проблема с разноповернутыми штрихкодами если их несколько, то распознаются только однонаправленные,
            // возможно стоит вручную поворачивать и перезапускать алгоритм.
            //
            int scannerOrientation = 0;
            var result             = reader.Decode(bmp);

            if (result != null)
            {
                barcodeResult      = new BarcodeResult();
                barcodeResult.Code = result.Text;
                barcodeResult.Type = BarcodeType.ToString(result.BarcodeFormat);
                try
                {
                    var orient = result.ResultMetadata[ResultMetadataType.ORIENTATION];
                    scannerOrientation = (int)orient; // only vertical/horizontal
                }
                catch (Exception /*ex*/)
                {
                }

                if (result.ResultPoints.Length >= 2)
                {
                    //
                    var luminanceSource = new ZXing.BitmapLuminanceSource(bmp);
                    var binarizer       = new ZXing.Common.HybridBinarizer(luminanceSource);
                    var bitMatrix       = binarizer.BlackMatrix;

                    // result.ResultPoints - точкии линии сканера, для которой был распознан штрих код
                    // для barcode128 эти точки находятся внутри штрихкода видимо за start и stop элементами.
                    // нам нужно получить по этим точкам ограничивающий п/у для всего штрихкода
                    // но это точки в координатах повернутого листа на scannerOrientation градусов,
                    // поэтому преобразуем их в начальную и конечную координату сканера в координатак картинки img
                    Point[] scanLine = GetScanLine(result.ResultPoints, scannerOrientation, img.Width, img.Height, bitMatrix);

                    // Возьмем конечную точку скан линии
                    int x = scanLine[1].X;
                    int y = scanLine[1].Y;

                    // Вычислим магический белый квадрат - предположительное место штрихкода.
                    // Искать будет с точки x,y, возвращает 4 точки, типа ограничивающего штрих код белую п/у.
                    // Использующийся алгоритм не до конца понятен, возвращает п/у содержащий одну, несколько полосок, или весь штрих код.
                    // Поэтому единственная полезная информация которая может быть извлечена высота штрихкода (координаты одной вертикальной полосы)
                    var whiterectDetector = ZXing.Common.Detector.WhiteRectangleDetector.Create(bitMatrix, 1, x, y);
                    var whiteRect         = whiterectDetector.detect();
                    if (whiteRect == null)
                    {
                        return(barcodeResult);                   // не удалось вычислить ограничивающий п/у.
                    }
                    // Посчитаем длину первой черной полоски после правой конечной точки scan линии.
                    int blackLineWidth = CalcBlackLineWidth(bitMatrix, scanLine);

                    // Вычислим по имеющимся данным ограничивающий п/у для штрихкода
                    int           dx          = blackLineWidth * 3; // 3 полоски по бокам добавим (для 128 баркода)
                    ResultPoint[] barcodeRect = GetBarCodeRect(scanLine, whiteRect, dx);

                    // Вычислим п/у для создания штрихкода и его ориентацию(поворот).
                    // (п/у без поворота, от левой нижней точки и его угол поворота в градусах)
                    //barcodeResult.Left = (int)barcodeRect[1].X;
                    //barcodeResult.Bottom = (int)barcodeRect[1].Y;
                    //barcodeResult.Right = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                    //barcodeResult.Top = barcodeResult.Bottom - (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);
                    barcodeResult.Left   = (int)barcodeRect[0].X;
                    barcodeResult.Top    = (int)barcodeRect[0].Y;
                    barcodeResult.Right  = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                    barcodeResult.Bottom = barcodeResult.Top + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);

                    /*                    }
                     *                                      else if (scannerOrientation == 180)
                     *                                      {
                     *                                          barcodeResult.Left = (int)barcodeRect[0].X;
                     *                                          barcodeResult.Bottom = (int)barcodeRect[0].Y;
                     *                                          barcodeResult.Right = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                     *                                          barcodeResult.Top = barcodeResult.Bottom - (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);
                     *                                      }*/

                    //barcodeResult.Orientation = -Orientation(barcodeRect[0], barcodeRect[2]);
                    barcodeResult.Orientation = Orientation(barcodeRect[0], barcodeRect[2]);

                    if (!string.IsNullOrEmpty(debugFileName))
                    {
                        // Закрасим область белым, чтобы можно было ещё искать barcode
                        var g = Graphics.FromImage(img);
                        g.FillPolygon(new SolidBrush(Color.Pink), ToDrawingRect(barcodeRect));

                        DebugSaveImage(debugFileName,
                                       img,
                                       barcodeRect,
                                       whiteRect,
                                       scanLine);
                    }
                }
            }
            return(barcodeResult);
        }