Exemplo n.º 1
0
        /// <returns> number of rows we could safely skip during scanning, based on the first
        /// two finder patterns that have been located. In some cases their position will
        /// allow us to infer that the third pattern must lie below a certain point farther
        /// down in the image.
        /// </returns>
        private int findRowSkip()
        {
            int max = possibleCenters.Count;

            if (max <= 1)
            {
                return(0);
            }
            FinderPattern firstConfirmedCenter = null;

            foreach (var center in possibleCenters)
            {
                if (center.Count >= CENTER_QUORUM)
                {
                    if (firstConfirmedCenter == null)
                    {
                        firstConfirmedCenter = center;
                    }
                    else
                    {
                        // We have two confirmed centers
                        // How far down can we skip before resuming looking for the next
                        // pattern? In the worst case, only the difference between the
                        // difference in the x / y coordinates of the two centers.
                        // This is the case where you find top left last.
                        hasSkipped = true;
                        //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                        return((int)(Math.Abs(firstConfirmedCenter.X - center.X) - Math.Abs(firstConfirmedCenter.Y - center.Y)) / 2);
                    }
                }
            }
            return(0);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the z component of the cross product between vectors BC and BA.
        /// </summary>
        private static float crossProductZ(FinderPattern pointA, FinderPattern pointB, FinderPattern pointC)
        {
            float bX = pointB.x;
            float bY = pointB.y;

            return(((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX)));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Get square of distance between a and b.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        private static double squaredDistance(FinderPattern a, FinderPattern b)
        {
            double x = a.X - b.X;
            double y = a.Y - b.Y;

            return(x * x + y * y);
        }
Exemplo n.º 4
0
        /// <summary>
        ///   <p>This is called when a horizontal scan finds a possible alignment pattern. It will
        /// cross check with a vertical scan, and if successful, will, ah, cross-cross-check
        /// with another horizontal scan. This is needed primarily to locate the real horizontal
        /// center of the pattern in cases of extreme skew.
        /// And then we cross-cross-cross check with another diagonal scan.</p>
        /// If that succeeds the finder pattern location is added to a list that tracks
        /// the number of times each location has been nearly-matched as a finder pattern.
        /// Each additional find is more evidence that the location is in fact a finder
        /// pattern center
        /// </summary>
        /// <param name="stateCount">reading state module counts from horizontal scan</param>
        /// <param name="i">row where finder pattern may be found</param>
        /// <param name="j">end of possible finder pattern in row</param>
        /// <param name="pureBarcode">true if in "pure barcode" mode</param>
        /// <returns>
        /// true if a finder pattern candidate was found this time
        /// </returns>
        protected bool handlePossibleCenter(int[] stateCount, int i, int j, bool pureBarcode)
        {
            int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +
                                  stateCount[4];
            float?centerJ = centerFromEnd(stateCount, j);

            if (centerJ == null)
            {
                return(false);
            }
            float?centerI = crossCheckVertical(i, (int)centerJ.Value, stateCount[2], stateCountTotal);

            if (centerI != null)
            {
                // Re-cross check
                centerJ = crossCheckHorizontal((int)centerJ.Value, (int)centerI.Value, stateCount[2], stateCountTotal);
                if (centerJ != null &&
                    (!pureBarcode || crossCheckDiagonal((int)centerI, (int)centerJ, stateCount[2], stateCountTotal)))
                {
                    float estimatedModuleSize = stateCountTotal / 7.0f;
                    bool  found = false;
                    for (int index = 0; index < possibleCenters.Count; index++)
                    {
                        var center = possibleCenters[index];
                        // Look for about the same center and module size:
                        if (center.aboutEquals(estimatedModuleSize, centerI.Value, centerJ.Value))
                        {
                            possibleCenters.RemoveAt(index);
                            possibleCenters.Insert(index, center.combineEstimate(centerI.Value, centerJ.Value, estimatedModuleSize));

                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        var point = new FinderPattern(centerJ.Value, centerI.Value, estimatedModuleSize);

                        possibleCenters.Add(point);
                        if (resultPointCallback != null)
                        {
                            resultPointCallback(point);
                        }
                    }
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Orders an array of three ResultPoints in an order [A,B,C] such that AB &lt; AC and
        /// BC &lt; AC and the angle between BC and BA is less than 180 degrees.
        /// </summary>
        internal static void orderBestPatterns(FinderPattern[] patterns)
        {
            // Find distances between pattern centers
            float zeroOneDistance = distance(patterns[0], patterns[1]);
            float oneTwoDistance  = distance(patterns[1], patterns[2]);
            float zeroTwoDistance = distance(patterns[0], patterns[2]);

            FinderPattern pointA, pointB, pointC;

            // Assume one closest to other two is B; A and C will just be guesses at first
            if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance)
            {
                pointB = patterns[0];
                pointA = patterns[1];
                pointC = patterns[2];
            }
            else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance)
            {
                pointB = patterns[1];
                pointA = patterns[0];
                pointC = patterns[2];
            }
            else
            {
                pointB = patterns[2];
                pointA = patterns[0];
                pointC = patterns[1];
            }

            // Use cross product to figure out whether A and C are correct or flipped.
            // This asks whether BC x BA has a positive z component, which is the arrangement
            // we want for A, B, C. If it's negative, then we've got it flipped around and
            // should swap A and C.
            if (crossProductZ(pointA, pointB, pointC) < 0.0f)
            {
                FinderPattern temp = pointA;
                pointA = pointC;
                pointC = temp;
            }

            patterns[0] = pointA;
            patterns[1] = pointB;
            patterns[2] = pointC;
        }
Exemplo n.º 6
0
        /// <summary> <p>Estimates module size based on two finder patterns -- it uses
        /// {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
        /// width of each, measuring along the axis between their centers.</p>
        /// </summary>
        private float calculateModuleSizeOneWay(FinderPattern pattern, FinderPattern otherPattern)
        {
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.X, (int)pattern.Y, (int)otherPattern.X, (int)otherPattern.Y);
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.X, (int)otherPattern.Y, (int)pattern.X, (int)pattern.Y);

            if (Single.IsNaN(moduleSizeEst1))
            {
                return(moduleSizeEst2 / 7.0f);
            }
            if (Single.IsNaN(moduleSizeEst2))
            {
                return(moduleSizeEst1 / 7.0f);
            }
            // Average them, and divide by 7 since we've counted the width of 3 black modules,
            // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
            return((moduleSizeEst1 + moduleSizeEst2) / 14.0f);
        }
Exemplo n.º 7
0
        /// <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(FinderPattern topLeft, FinderPattern topRight, FinderPattern bottomLeft, float moduleSize, out int dimension)
        {
            int tltrCentersDimension = MathUtils.round(FinderPattern.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = MathUtils.round(FinderPattern.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);
        }
Exemplo n.º 8
0
 /// <summary> <p>Computes an average estimated module size based on estimated derived from the positions
 /// of the three finder patterns.</p>
 /// </summary>
 protected internal virtual float calculateModuleSize(FinderPattern topLeft, FinderPattern topRight, FinderPattern bottomLeft)
 {
     // Take the average
     return((calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f);
 }
Exemplo n.º 9
0
        /// <summary>
        /// Processes the finder pattern info.
        /// </summary>
        /// <param name="info">The info.</param>
        /// <returns></returns>
        protected internal virtual DetectorResult processFinderPatternInfo(FinderPatternInfo info)
        {
            FinderPattern topLeft    = info.TopLeft;
            FinderPattern topRight   = info.TopRight;
            FinderPattern bottomLeft = info.BottomLeft;

            float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);

            if (moduleSize < 1.0f)
            {
                return(null);
            }
            int dimension;

            if (!computeDimension(topLeft, topRight, bottomLeft, moduleSize, out dimension))
            {
                return(null);
            }
            Internal.Version provisionalVersion = Internal.Version.getProvisionalVersionForDimension(dimension);
            if (provisionalVersion == null)
            {
                return(null);
            }
            int modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7;

            AlignmentPattern alignmentPattern = null;

            // Anything above version 1 has an alignment pattern
            if (provisionalVersion.AlignmentPatternCenters.Length > 0)
            {
                // Guess where a "bottom right" finder pattern would have been
                float bottomRightX = topRight.X - topLeft.X + bottomLeft.X;
                float bottomRightY = topRight.Y - topLeft.Y + bottomLeft.Y;

                // Estimate that alignment pattern is closer by 3 modules
                // from "bottom right" to known top left location
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                int estAlignmentX = (int)(topLeft.X + correctionToTopLeft * (bottomRightX - topLeft.X));
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                int estAlignmentY = (int)(topLeft.Y + correctionToTopLeft * (bottomRightY - topLeft.Y));

                // Kind of arbitrary -- expand search radius before giving up
                for (int i = 4; i <= 16; i <<= 1)
                {
                    alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
                    if (alignmentPattern == null)
                    {
                        continue;
                    }
                    break;
                }
                // If we didn't find alignment pattern... well try anyway without it
            }

            PerspectiveTransform transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);

            BitMatrix bits = sampleGrid(image, transform, dimension);

            if (bits == null)
            {
                return(null);
            }

            ResultPoint[] points;
            if (alignmentPattern == null)
            {
                points = new ResultPoint[] { bottomLeft, topLeft, topRight };
            }
            else
            {
                points = new ResultPoint[] { bottomLeft, topLeft, topRight, alignmentPattern };
            }
            return(new DetectorResult(bits, points));
        }
Exemplo n.º 10
0
        /// <returns> the 3 best {@link FinderPattern}s from our list of candidates. The "best" are
        /// those that have been detected at least {@link #CENTER_QUORUM} times, and whose module
        /// size differs from the average among those patterns the least
        /// </returns>
        private FinderPattern[] selectBestPatterns()
        {
            int startSize = possibleCenters.Count;

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

            // Filter outlier possibilities whose module size is too different
            if (startSize > 3)
            {
                // But we can only afford to do so if we have at least 4 possibilities to choose from
                float totalModuleSize = 0.0f;
                float square          = 0.0f;
                foreach (var center in possibleCenters)
                {
                    float size = center.EstimatedModuleSize;
                    totalModuleSize += size;
                    square          += size * size;
                }
                float average = totalModuleSize / startSize;
                float stdDev  = (float)Math.Sqrt(square / startSize - average * average);

                possibleCenters.Sort(new FurthestFromAverageComparator(average));

                float limit = Math.Max(0.2f * average, stdDev);

                for (int i = 0; i < possibleCenters.Count && possibleCenters.Count > 3; i++)
                {
                    FinderPattern pattern = possibleCenters[i];
                    if (Math.Abs(pattern.EstimatedModuleSize - average) > limit)
                    {
                        possibleCenters.RemoveAt(i);
                        i--;
                    }
                }
            }

            if (possibleCenters.Count > 3)
            {
                // Throw away all but those first size candidate points we found.

                float totalModuleSize = 0.0f;
                foreach (var possibleCenter in possibleCenters)
                {
                    totalModuleSize += possibleCenter.EstimatedModuleSize;
                }

                float average = totalModuleSize / possibleCenters.Count;

                possibleCenters.Sort(new CenterComparator(average));

                //possibleCenters.subList(3, possibleCenters.Count).clear();
                possibleCenters = possibleCenters.GetRange(0, 3);
            }

            return(new[]
            {
                possibleCenters[0],
                possibleCenters[1],
                possibleCenters[2]
            });
        }
Exemplo n.º 11
0
 /// <summary> <p>Computes an average estimated module size based on estimated derived from the positions
 /// of the three finder patterns.</p>
 /// </summary>
 protected internal virtual float calculateModuleSize(FinderPattern topLeft, FinderPattern topRight, FinderPattern bottomLeft)
 {
    // Take the average
    return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
 }
Exemplo n.º 12
0
 /// <summary>
 /// Returns the z component of the cross product between vectors BC and BA.
 /// </summary>
 private static float crossProductZ(FinderPattern pointA, FinderPattern pointB, FinderPattern pointC)
 {
    float bX = pointB.x;
    float bY = pointB.y;
    return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
 }
Exemplo n.º 13
0
      /// <summary>
      /// Orders an array of three ResultPoints in an order [A,B,C] such that AB &lt; AC and
      /// BC &lt; AC and the angle between BC and BA is less than 180 degrees.
      /// </summary>
      internal static void orderBestPatterns(FinderPattern[] patterns)
      {
         // Find distances between pattern centers
         float zeroOneDistance = distance(patterns[0], patterns[1]);
         float oneTwoDistance = distance(patterns[1], patterns[2]);
         float zeroTwoDistance = distance(patterns[0], patterns[2]);

         FinderPattern pointA, pointB, pointC;
         // Assume one closest to other two is B; A and C will just be guesses at first
         if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance)
         {
            pointB = patterns[0];
            pointA = patterns[1];
            pointC = patterns[2];
         }
         else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance)
         {
            pointB = patterns[1];
            pointA = patterns[0];
            pointC = patterns[2];
         }
         else
         {
            pointB = patterns[2];
            pointA = patterns[0];
            pointC = patterns[1];
         }

         // Use cross product to figure out whether A and C are correct or flipped.
         // This asks whether BC x BA has a positive z component, which is the arrangement
         // we want for A, B, C. If it's negative, then we've got it flipped around and
         // should swap A and C.
         if (crossProductZ(pointA, pointB, pointC) < 0.0f)
         {
            FinderPattern temp = pointA;
            pointA = pointC;
            pointC = temp;
         }

         patterns[0] = pointA;
         patterns[1] = pointB;
         patterns[2] = pointC;
      }
Exemplo n.º 14
0
 /// <returns>
 /// distance between two points
 /// </returns>
 public static float distance(FinderPattern pattern1, FinderPattern pattern2)
 {
    return ZXing.Common.Detector.MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);
 }
Exemplo n.º 15
0
        internal virtual FinderPatternInfo find(IDictionary <DecodeHintType, object> hints)
        {
            bool tryHarder   = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
            bool pureBarcode = hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE);
            int  maxI        = image.Height;
            int  maxJ        = image.Width;
            // We are looking for black/white/black/white/black modules in
            // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far

            // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
            // image, and then account for the center being 3 modules in size. This gives the smallest
            // number of pixels the center could be, so skip this often. When trying harder, look for all
            // QR versions regardless of how dense they are.
            int iSkip = (3 * maxI) / (4 * MAX_MODULES);

            if (iSkip < MIN_SKIP || tryHarder)
            {
                iSkip = MIN_SKIP;
            }

            bool done = false;

            int[] stateCount = new int[5];
            for (int i = iSkip - 1; i < maxI && !done; i += iSkip)
            {
                // Get a row of black/white values
                stateCount[0] = 0;
                stateCount[1] = 0;
                stateCount[2] = 0;
                stateCount[3] = 0;
                stateCount[4] = 0;
                int currentState = 0;
                for (int j = 0; j < maxJ; j++)
                {
                    if (image[j, i])
                    {
                        // Black pixel
                        if ((currentState & 1) == 1)
                        {
                            // Counting white pixels
                            currentState++;
                        }
                        stateCount[currentState]++;
                    }
                    else
                    {
                        // White pixel
                        if ((currentState & 1) == 0)
                        {
                            // Counting black pixels
                            if (currentState == 4)
                            {
                                // A winner?
                                if (foundPatternCross(stateCount))
                                {
                                    // Yes
                                    bool confirmed = handlePossibleCenter(stateCount, i, j, pureBarcode);
                                    if (confirmed)
                                    {
                                        // Start examining every other line. Checking each line turned out to be too
                                        // expensive and didn't improve performance.
                                        iSkip = 2;
                                        if (hasSkipped)
                                        {
                                            done = haveMultiplyConfirmedCenters();
                                        }
                                        else
                                        {
                                            int rowSkip = findRowSkip();
                                            if (rowSkip > stateCount[2])
                                            {
                                                // Skip rows between row of lower confirmed center
                                                // and top of presumed third confirmed center
                                                // but back up a bit to get a full chance of detecting
                                                // it, entire width of center of finder pattern

                                                // Skip by rowSkip, but back off by stateCount[2] (size of last center
                                                // of pattern we saw) to be conservative, and also back off by iSkip which
                                                // is about to be re-added
                                                i += rowSkip - stateCount[2] - iSkip;
                                                j  = maxJ - 1;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        stateCount[0] = stateCount[2];
                                        stateCount[1] = stateCount[3];
                                        stateCount[2] = stateCount[4];
                                        stateCount[3] = 1;
                                        stateCount[4] = 0;
                                        currentState  = 3;
                                        continue;
                                    }
                                    // Clear state to start looking again
                                    currentState  = 0;
                                    stateCount[0] = 0;
                                    stateCount[1] = 0;
                                    stateCount[2] = 0;
                                    stateCount[3] = 0;
                                    stateCount[4] = 0;
                                }
                                else
                                {
                                    // No, shift counts back by two
                                    stateCount[0] = stateCount[2];
                                    stateCount[1] = stateCount[3];
                                    stateCount[2] = stateCount[4];
                                    stateCount[3] = 1;
                                    stateCount[4] = 0;
                                    currentState  = 3;
                                }
                            }
                            else
                            {
                                stateCount[++currentState]++;
                            }
                        }
                        else
                        {
                            // Counting white pixels
                            stateCount[currentState]++;
                        }
                    }
                }
                if (foundPatternCross(stateCount))
                {
                    bool confirmed = handlePossibleCenter(stateCount, i, maxJ, pureBarcode);
                    if (confirmed)
                    {
                        iSkip = stateCount[0];
                        if (hasSkipped)
                        {
                            // Found a third one
                            done = haveMultiplyConfirmedCenters();
                        }
                    }
                }
            }

            FinderPattern[] patternInfo = selectBestPatterns();
            if (patternInfo == null)
            {
                return(null);
            }

            FinderPattern.orderBestPatterns(patternInfo);

            return(new FinderPatternInfo(patternInfo));
        }
Exemplo n.º 16
0
 /// <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(FinderPattern topLeft, FinderPattern topRight, FinderPattern bottomLeft, float moduleSize, out int dimension)
 {
    int tltrCentersDimension = MathUtils.round(FinderPattern.distance(topLeft, topRight) / moduleSize);
    int tlblCentersDimension = MathUtils.round(FinderPattern.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;
 }
Exemplo n.º 17
0
        /// <returns> the 3 best {@link FinderPattern}s from our list of candidates. The "best" are
        /// those have similar module size and form a shape closer to a isosceles right triangle.
        /// </returns>
        private FinderPattern[] selectBestPatterns()
        {
            int startSize = possibleCenters.Count;

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

            possibleCenters.Sort(moduleComparator);

            double distortion = Double.MaxValue;

            double[]        squares      = new double[3];
            FinderPattern[] bestPatterns = new FinderPattern[3];

            for (int i = 0; i < possibleCenters.Count - 2; i++)
            {
                FinderPattern fpi           = possibleCenters[i];
                float         minModuleSize = fpi.EstimatedModuleSize;

                for (int j = i + 1; j < possibleCenters.Count - 1; j++)
                {
                    FinderPattern fpj      = possibleCenters[j];
                    double        squares0 = squaredDistance(fpi, fpj);

                    for (int k = j + 1; k < possibleCenters.Count; k++)
                    {
                        FinderPattern fpk           = possibleCenters[k];
                        float         maxModuleSize = fpk.EstimatedModuleSize;
                        if (maxModuleSize > minModuleSize * 1.4f)
                        {
                            // module size is not similar
                            continue;
                        }

                        squares[0] = squares0;
                        squares[1] = squaredDistance(fpj, fpk);
                        squares[2] = squaredDistance(fpi, fpk);
                        Array.Sort(squares);

                        // a^2 + b^2 = c^2 (Pythagorean theorem), and a = b (isosceles triangle).
                        // Since any right triangle satisfies the formula c^2 - b^2 - a^2 = 0,
                        // we need to check both two equal sides separately.
                        // The value of |c^2 - 2 * b^2| + |c^2 - 2 * a^2| increases as dissimilarity
                        // from isosceles right triangle.
                        double d = Math.Abs(squares[2] - 2 * squares[1]) + Math.Abs(squares[2] - 2 * squares[0]);
                        if (d < distortion)
                        {
                            distortion      = d;
                            bestPatterns[0] = fpi;
                            bestPatterns[1] = fpj;
                            bestPatterns[2] = fpk;
                        }
                    }
                }
            }

            if (distortion == Double.MaxValue)
            {
                return(null);
            }

            return(bestPatterns);
        }
Exemplo n.º 18
0
 /// <summary> <p>Estimates module size based on two finder patterns -- it uses
 /// {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
 /// width of each, measuring along the axis between their centers.</p>
 /// </summary>
 private float calculateModuleSizeOneWay(FinderPattern pattern, FinderPattern otherPattern)
 {
    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
    float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.X, (int)pattern.Y, (int)otherPattern.X, (int)otherPattern.Y);
    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
    float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.X, (int)otherPattern.Y, (int)pattern.X, (int)pattern.Y);
    if (Single.IsNaN(moduleSizeEst1))
    {
       return moduleSizeEst2 / 7.0f;
    }
    if (Single.IsNaN(moduleSizeEst2))
    {
       return moduleSizeEst1 / 7.0f;
    }
    // Average them, and divide by 7 since we've counted the width of 3 black modules,
    // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
    return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
 }
Exemplo n.º 19
0
 /// <returns>
 /// distance between two points
 /// </returns>
 public static float distance(FinderPattern pattern1, FinderPattern pattern2)
 {
     return(ZXing.Common.Detector.MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y));
 }