Beispiel #1
0
        public void Recognize()
        {
            var width  = _image.Width;
            var height = _image.Height;

            KeyValuePair <ulong[], ulong[]>[,] matrix = new KeyValuePair <ulong[], ulong[]> [width, height];

            for (var y = 0; y < height; y++)
            {
                IndexRow(y, width);
            }
            for (int x = 0; x < width; x++)
            {
                IndexColumn(x, height);
            }
            for (var y = 0; y < height; y++)
            {
                if (y == 574)
                {
                    var roww    = GetRow(y, width);
                    var levelss = _sequenceToItsLocalElementLevelsConverter.Convert(roww);
                    var l276    = levelss[276];
                    var l277    = levelss[277];
                    var l278    = levelss[278];
                }

                var row = SaveRow(y, width);

                var x     = 0;
                var stack = new Stack <ulong>();
                StopableSequenceWalker.WalkRight(row, _links.GetSource, _links.GetTarget, _links.IsPartialPoint,
                                                 enteredElement =>
                {
                    stack.Push(enteredElement);
                },
                                                 exitedElement =>
                {
                    stack.Pop();
                },
                                                 checkedElement => true,
                                                 element =>
                {
                    stack.Push(element);
                    var pair = new KeyValuePair <ulong[], ulong[]>(stack.ToArray(), default);
                    stack.Pop();
                    matrix[x++, y] = pair;
                    return(true);
                });
            }
            for (int x = 0; x < width; x++)
            {
                var column = SaveColumn(x, height);

                var y     = 0;
                var stack = new Stack <ulong>();
                StopableSequenceWalker.WalkRight(column, _links.GetSource, _links.GetTarget, _links.IsPartialPoint,
                                                 enteredElement =>
                {
                    stack.Push(enteredElement);
                },
                                                 exitedElement =>
                {
                    stack.Pop();
                },
                                                 checkedElement => true,
                                                 element =>
                {
                    var pair = matrix[x, y];
                    stack.Push(element);
                    pair = new KeyValuePair <ulong[], ulong[]>(pair.Key, stack.ToArray());
                    stack.Pop();
                    matrix[x, y++] = pair;
                    return(true);
                });
            }

            // Sort sequences by usages and frequency

            var linksByUsages    = new SortedDictionary <ulong, List <ulong> >();
            var linksByFrequency = new SortedDictionary <ulong, List <ulong> >();

            var any       = _links.Constants.Any;
            var @continue = _links.Constants.Continue;
            var query     = new Link <ulong>(any, any, any);

            _links.Each(link =>
            {
                var linkIndex = _links.GetIndex(link);
                var usages    = _links.Count(new ulong[] { any, linkIndex });
                if (!linksByUsages.TryGetValue(usages, out List <ulong> linksByUsageList))
                {
                    linksByUsageList = new List <ulong>();
                    linksByUsages.Add(usages, linksByUsageList);
                }
                linksByUsageList.Add(linkIndex);
                ulong frequency = GetFrequency(link);
                if (!linksByFrequency.TryGetValue(frequency, out List <ulong> linksByFrequencyList))
                {
                    linksByFrequencyList = new List <ulong>();
                    linksByFrequency.Add(frequency, linksByFrequencyList);
                }
                linksByFrequencyList.Add(linkIndex);
                return(@continue);
            }, query);

            // Build matrix of levels on 2D plane (as in optimal variant algorithm)

            var levels = new ulong[width, height];

            var topBottom = 0UL;
            var leftRight = 0UL;
            var bottomTop = 0UL;
            var rightLeft = 0UL;

            var lastX = width - 1;
            var lastY = height - 1;

            // We do not calculate edges to simplify the algorithm
            for (int y = 1; y < lastY; y++)
            {
                for (int x = 1; x < lastX; x++)
                {
                    topBottom = GetFrequency(matrix[x, y - 1].Key[0], matrix[x, y].Key[0]);
                    leftRight = GetFrequency(matrix[x - 1, y].Key[0], matrix[x, y].Key[0]);
                    bottomTop = GetFrequency(matrix[x, y].Key[0], matrix[x, y + 1].Key[0]);
                    rightLeft = GetFrequency(matrix[x, y].Key[0], matrix[x + 1, y].Key[0]);

                    levels[x, y] = Math.Max(Math.Max(topBottom, leftRight), Math.Max(bottomTop, rightLeft));
                }
            }

            // Print levels matrix

            //for (int y = 1; y < lastY; y++)
            //{
            //    for (int x = 1; x < lastX; x++)
            //    {
            //        Console.Write("{0:0000}", levels[x, y]);
            //        Console.Write(' ');
            //    }
            //    Console.WriteLine();
            //}

            // Black and white (split to two colors)

            var contrastedLevels = new ulong[width, height];

            var minimum = ulong.MaxValue;
            var maximum = ulong.MinValue;

            for (int y = 1; y < lastY; y++)
            {
                for (int x = 1; x < lastX; x++)
                {
                    var level = levels[x, y];
                    minimum = minimum > level ? level : minimum;
                }
            }

            for (int y = 1; y < lastY; y++)
            {
                for (int x = 1; x < lastX; x++)
                {
                    var level = levels[x, y];
                    maximum = maximum < level ? level : maximum;
                }
            }

            var middle = (maximum + minimum) / 2;

            for (int y = 1; y < lastY; y++)
            {
                for (int x = 1; x < lastX; x++)
                {
                    contrastedLevels[x, y] = levels[x, y] > middle ? 0UL : 1UL; // the most frequent should be background (zero)
                }
            }

            // Print contrasted levels matrix

            //for (int y = 1; y < lastY; y++)
            //{
            //    for (int x = 1; x < lastX; x++)
            //    {
            //        Console.Write("{0:0}", contrastedLevels[x, y]);
            //    }
            //    Console.WriteLine();
            //}

            var outputImagePath = Path.ChangeExtension(_sourceImagePath, ".bf.png");

            using (var outputImage = new MagickImage(MagickColor.FromRgba(0, 0, 0, 255), width, height))
            {
                var pixels = outputImage.GetPixels();
                for (int y = 1; y < lastY; y++)
                {
                    for (int x = 1; x < lastX; x++)
                    {
                        if (contrastedLevels[x, y] > 0)
                        {
                            pixels.SetPixel(x, y, new byte[] { 255, 255, 255, 255 });
                        }
                    }
                    Console.WriteLine();
                }
                outputImage.Write(outputImagePath);
            }

            // Get the largest repeated patterns with lowest frequency (level)
        }