Пример #1
0
        public DataMatrixExtraction(Bitmap sourceImage, FinderPatternPair fpp)
        {
            this.fpp = fpp;

            PointF p1   = fpp.p1.X < fpp.p2.X ? fpp.p1.ToF() : fpp.p2.ToF();
            PointF p2   = fpp.p1.X < fpp.p2.X ? fpp.p2.ToF() : fpp.p1.ToF();
            PointF vect = PointOps.Mult(PointOps.Sub(p2, p1), 0.1f);
            float  unit = (float)PointOps.Distance(vect);

            PointF normX = PointOps.Normalize(vect);

            angX = Math.Atan2(normX.Y, normX.X);
            double angY  = angX - Math.PI / 2;
            PointF normY = new PointF((float)Math.Cos(angY), (float)Math.Sin(angY));

            topLeft     = PointOps.Add(p1, PointOps.Add(PointOps.Mult(normX, unit), PointOps.Mult(normY, unit)));
            bottomLeft  = PointOps.Add(p1, PointOps.Sub(PointOps.Mult(normX, unit), PointOps.Mult(normY, unit)));
            topRight    = PointOps.Add(p1, PointOps.Add(PointOps.Mult(normX, unit * 9), PointOps.Mult(normY, unit)));
            bottomRight = PointOps.Add(p1, PointOps.Sub(PointOps.Mult(normX, unit * 9), PointOps.Mult(normY, unit)));

            rotatedMatrix = new Bitmap((int)Math.Ceiling(unit * 8), (int)Math.Ceiling(unit * 2), PixelFormat.Format32bppArgb);
            Graphics rotG = Graphics.FromImage(rotatedMatrix);

            rotG.RotateTransform((float)(-angX * 180 / Math.PI));

            float diagonal = (float)PointOps.Distance(p1, p2);

            rotG.DrawImage(
                sourceImage,
                new RectangleF(-diagonal, -diagonal, diagonal * 2, diagonal * 2),
                new RectangleF(topLeft.X - diagonal, topLeft.Y - diagonal, diagonal * 2, diagonal * 2),
                GraphicsUnit.Pixel);
            rotG.Dispose();

            int[] cellSum = new int[DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount];
            unsafe {
                BitmapData bd  = rotatedMatrix.LockBits(ImageLockMode.ReadOnly);
                byte *     ptr = (byte *)bd.Scan0.ToPointer();

                for (int y = 0; y < rotatedMatrix.Height; y++)
                {
                    for (int x = 0; x < rotatedMatrix.Width; x++)
                    {
                        int cx = (int)Math.Floor((float)x * DataMatrixDrawer.columnCount / rotatedMatrix.Width);
                        int cy = (int)Math.Floor((float)y * DataMatrixDrawer.rowCount / rotatedMatrix.Height);
                        cellSum[cy * DataMatrixDrawer.columnCount + cx] += *ptr;
                        ptr += 4;
                    }
                }

                rotatedMatrix.UnlockBits(bd);
            }
            double threshold = ValueClustering.DivThreshold(cellSum);

            extractedData = new bool[DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount];
            for (int q = 0; q < DataMatrixDrawer.rowCount * DataMatrixDrawer.columnCount; q++)
            {
                extractedData[q] = cellSum[q] < threshold;
            }
        }
Пример #2
0
        static void StressTest()
        {
            int patternRadius    = 60;
            int minPatternRadius = 50;
            int maxPatternRadius = 70;
            int imgSize          = 3000;

            int N       = 100;
            int success = 0;
            int failure = 0;

            Random r    = new Random();
            double time = 0;

            for (int q = 0; q < N; q++)
            {
                uint   codeValue = (uint)r.Next();
                Bitmap codeImage = ARCodeUtil.BuildCode(codeValue, patternRadius);

                int   diag         = (int)PointOps.Distance(0, 0, codeImage.Width, codeImage.Height);
                Point codeLocation = new Point(
                    r.Next(imgSize - diag) + diag / 2,
                    r.Next(imgSize - diag) + diag / 2);

                Bitmap   sourceImage = new Bitmap(imgSize, imgSize, PixelFormat.Format32bppArgb);
                Graphics g           = Graphics.FromImage(sourceImage);
                g.FillRectangle(Brushes.White, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height));

                g.TranslateTransform(codeLocation.X, codeLocation.Y);
                g.RotateTransform((float)((r.NextDouble() - 0.5) * 2));
                g.TranslateTransform(-codeLocation.X, -codeLocation.Y);

                Point codeDrawLocation = new Point(
                    codeLocation.X - codeImage.Width / 2,
                    codeLocation.Y - codeImage.Height / 2);

                g.DrawImage(codeImage, codeDrawLocation);
                g.Dispose();

                Bitmap noisedImage = GetTestNoiseFilter().Apply(sourceImage);

                DateTime      stt            = DateTime.Now;
                Option <uint> extractedValue = ARCodeUtil.ExtractCode(noisedImage, minPatternRadius, maxPatternRadius);
                DateTime      end            = DateTime.Now;
                time += (end - stt).TotalMilliseconds;

                if (extractedValue.NonEmpty() && extractedValue.Get() == codeValue)
                {
                    success++;
                    Console.WriteLine("({0}/{1}) Success.", q + 1, N);
                }
                else
                {
                    failure++;
                    Console.WriteLine("({0}/{1}) Failure.", q + 1, N);
                }
            }
            Console.WriteLine("successes/failures: {0}/{1}", success, failure);
            Console.WriteLine("average recognition time: {0:F3} ms", time / N);
        }
Пример #3
0
        private static List <Point3> LocatePeaks(int[,,] hough, int patternCount, List <Point3> foundPeaks, int minPatternSize)
        {
            int max  = int.MinValue;
            int maxX = 0;
            int maxY = 0;
            int maxZ = 0;

            for (int z = 0; z < hough.GetLength(0); z++)
            {
                for (int y = 0; y < hough.GetLength(1); y++)
                {
                    for (int x = 0; x < hough.GetLength(2); x++)
                    {
                        Point3 neighbourPeak = foundPeaks.Find(p => PointOps.Distance(x, y, p.X, p.Y) < minPatternSize);
                        if (neighbourPeak == null && hough[z, y, x] > max)
                        {
                            max  = hough[z, y, x];
                            maxX = x;
                            maxY = y;
                            maxZ = z;
                        }
                    }
                }
            }
            foundPeaks.Add(new Point3(maxX, maxY, maxZ));
            if (patternCount == 1)
            {
                return(foundPeaks);
            }
            else
            {
                return(LocatePeaks(hough, patternCount - 1, foundPeaks, minPatternSize));
            }
        }
Пример #4
0
        /*
         * Locates top-left cell corner at `x` column and `y` row.
         */
        public PointF GetTopLeftCellCorner(int x, int y)
        {
            PointF p = origin;

            for (int q = 0; q < x; q++)
            {
                p = PointOps.Add(p, PointOps.Mult(horizontalNormal, columnWidths[q]));
            }
            for (int q = 0; q < y; q++)
            {
                p = PointOps.Add(p, PointOps.Mult(verticalNormal, rowHeights[q]));
            }
            return(p);
        }
Пример #5
0
        public LineNormalization(List <LineF> horizLines, List <LineF> vertLines, Bitmap src)
        {
            List <double> angles = new List <double>();

            angles.AddRange(horizLines.Select(ln => PointOps.LineAngle(ln)));
            angles.AddRange(vertLines.Select(ln => PointOps.LineAngle(ln)));
            angles.Sort();

            angle = angles[angles.Count / 2];

            normHorizLines   = horizLines.Select(ln => PointOps.RotateLine(ln, angle - PointOps.LineAngle(ln))).ToList();
            normVertLines    = vertLines.Select(ln => PointOps.RotateLine(ln, angle - PointOps.LineAngle(ln))).ToList();
            normRotVertLines = normVertLines.Select(ln =>
                                                    new LineF(new PointF(src.Width - 1 - ln.p1.Y, ln.p1.X), new PointF(src.Width - 1 - ln.p2.Y, ln.p2.X))).ToList();
        }
Пример #6
0
        private static List <Point> CaclulateOffsetTable(int patternRadius, Func <int, int, bool> testPixel)
        {
            List <Point> pts    = new List <Point>();
            PointF       center = new PointF(0, 0);

            for (int cy = -patternRadius; cy <= patternRadius; cy++)
            {
                for (int cx = -patternRadius; cx <= patternRadius; cx++)
                {
                    PointF p     = new PointF(cx, cy);
                    float  r     = (float)PointOps.Distance(p, center) / patternRadius;
                    PointF prevP = new PointF(cx - 1, cy);
                    float  prevR = (float)PointOps.Distance(prevP, center) / patternRadius;
                    if (testPixel(FinderCircleDrawer.GetPixelAtRadius(prevR), FinderCircleDrawer.GetPixelAtRadius(r)))
                    {
                        pts.Add(new Point(cx, cy));
                    }
                }
            }
            return(pts);
        }
Пример #7
0
        /*
         * Draw a table on provided graphics canvas with provided pen.
         */
        public void DrawTable(Graphics g, Pen p)
        {
            PointF row = PointOps.Mult(horizontalNormal, totalWidth);
            PointF r   = origin;

            g.DrawLine(p, r, PointOps.Add(r, row));
            for (int q = 0; q < rowHeights.Count; q++)
            {
                r = PointOps.Add(r, PointOps.Mult(verticalNormal, rowHeights[q]));
                g.DrawLine(p, r, PointOps.Add(r, row));
            }

            PointF col = PointOps.Mult(verticalNormal, totalHeight);
            PointF c   = origin;

            g.DrawLine(p, c, PointOps.Add(c, col));
            for (int q = 0; q < columnWidths.Count; q++)
            {
                c = PointOps.Add(c, PointOps.Mult(horizontalNormal, columnWidths[q]));
                g.DrawLine(p, c, PointOps.Add(c, col));
            }
        }
Пример #8
0
        public static Bitmap GetFinderCircleImage(int radius)
        {
            Bitmap img = new Bitmap(radius * 2 + 1, radius * 2 + 1, PixelFormat.Format32bppArgb);

            unsafe {
                BitmapData bd  = img.LockBits(ImageLockMode.WriteOnly);
                uint *     ptr = (uint *)bd.Scan0.ToPointer();

                PointF center = new PointF(radius, radius);

                for (int y = 0; y < img.Height; y++)
                {
                    for (int x = 0; x < img.Width; x++)
                    {
                        PointF p = new PointF(x, y);
                        float  r = (float)PointOps.Distance(p, center) / radius;

                        int px = GetPixelAtRadius(r);
                        if (px == 1)
                        {
                            *ptr = 0xff000000;
                        }
                        else if (px == -1)
                        {
                            *ptr = 0xffffffff;
                        }

                        ptr++;
                    }
                }

                img.UnlockBits(bd);
            }

            return(img);
        }
Пример #9
0
 public float PictureY(PointF p)
 {
     return(PointOps.DotProduct(p, invVertNormal));
 }
Пример #10
0
 public float PictureX(PointF p)
 {
     return(PointOps.DotProduct(p, invHorizNormal));
 }
Пример #11
0
 public float TableY(PointF p)
 {
     return(PointOps.DotProduct(p, vertNormal));
 }
Пример #12
0
 public float TableX(PointF p)
 {
     return(PointOps.DotProduct(p, horizNormal));
 }