Esempio n. 1
0
        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)
            {
                throw ReaderException.Instance;
            }
            int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
            Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
            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

                float correctionToTopLeft = 1.0f - 3.0f/modulesBetweenFPCenters;

                var estAlignmentX = (int) (topLeft.X + correctionToTopLeft*(bottomRightX - topLeft.X));

                var 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)
                {
                    try
                    {

                        alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);
                        break;
                    }
                    catch (ReaderException)
                    {
                        // try next round
                    }
                }
                // 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);

            ResultPoint[] points;
            if (alignmentPattern == null)
            {
                points = new ResultPoint[] {bottomLeft, topLeft, topRight};
            }
            else
            {
                points = new ResultPoint[] {bottomLeft, topLeft, topRight, alignmentPattern};
            }
            return new DetectorResult(bits, points);
        }
        /// <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);
        }
Esempio n. 3
0
		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)
			{
				throw ReaderException.Instance;
			}
			int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
			Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
			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 / 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)
				{
					try
					{
						//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'"
						alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);
						break;
					}
					catch (ReaderException)
					{
						// try next round
					}
				}
				// 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);

		    ResultPoint[] points = alignmentPattern == null ? new ResultPoint[]{bottomLeft, topLeft, topRight} : new ResultPoint[]{bottomLeft, topLeft, topRight, alignmentPattern};
			return new DetectorResult(bits, points);
		}