Beispiel #1
0
                public void ShouldNotSetTheAttributesWhenTheyAreNotSpecified()
                {
                    using (var image = new MagickImage())
                    {
                        var settings = new MorphologySettings();

                        ArtifactsHelper.SetImageArtifacts(image, settings);

                        Assert.Empty(image.ArtifactNames);
                    }
                }
            public void ShouldNotSetTheAttributesWhenTheyAreNotSpecified()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings();

                    settings.SetImageArtifacts(image);

                    EnumerableAssert.IsEmpty(image.ArtifactNames);
                }
            }
Beispiel #3
0
        private void Joins_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selected = (State.Join?)Joins.SelectedItem;

            if (selected != null)
            {
                var join   = selected.Value;
                var image1 = AppState.Image(join.Image1);
                var image2 = AppState.Image(join.Image2);

                /*
                 * var newWidth = 10;
                 * var newHeight = 10;
                 */

                Task.Run(() =>
                {
                    var resize       = 0.25;
                    var resizeAmount = new Percentage(resize * 100);
                    image1           = image1.Clone();
                    var settings     = new MorphologySettings
                    {
                        Channels        = Channels.Alpha,
                        Method          = MorphologyMethod.Distance,
                        Kernel          = Kernel.Euclidean,
                        KernelArguments = "1,20!"
                    };

                    /*
                     * image1.Alpha(AlphaOption.Set);
                     * image1.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                     * image1.Morphology(settings);
                     */

                    image2 = image2.Clone();

                    /*
                     * image2.Alpha(AlphaOption.Set);
                     * image2.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                     * image2.Morphology(settings);
                     */

                    var images  = new MagickImageCollection();
                    image2.Page = new MagickGeometry($"{ToOffset(join.JoinPoint.X)}{ToOffset(join.JoinPoint.Y)}");
                    images.Add(image1);
                    images.Add(image2);
                    var result = images.Merge();
                    result.Resize(resizeAmount);

                    DisplayImage(Viewer, result);
                    //DisplayImage(Viewer, image2);
                });
            }
        }
Beispiel #4
0
            public void ShouldNotSetTheAttributesWhenTheyAreNotSpecified()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings();

                    settings.SetImageArtifacts(image);

                    Assert.IsNull(image.GetArtifact("convolve:bias"));
                    Assert.IsNull(image.GetArtifact("convolve:scale"));
                }
            }
Beispiel #5
0
            public void ShouldSetConvolveScale()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings()
                    {
                        ConvolveScale = new MagickGeometry(1, 2, 3, 4),
                    };

                    settings.SetImageArtifacts(image);

                    Assert.AreEqual("3x4+1+2", image.GetArtifact("convolve:scale"));
                }
            }
Beispiel #6
0
            public void ShouldSetConvolveBias()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings()
                    {
                        ConvolveBias = new Percentage(70),
                    };

                    settings.SetImageArtifacts(image);

                    Assert.AreEqual("70%", image.GetArtifact("convolve:bias"));
                }
            }
Beispiel #7
0
            public void ShouldSetConvolveScale()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings
                    {
                        ConvolveScale = new MagickGeometry(1, 2, 3, 4),
                    };

                    settings.SetImageArtifacts(image);
                    settings.RemoveImageArtifacts(image);

                    Assert.Empty(image.ArtifactNames);
                }
            }
Beispiel #8
0
            public void ShouldSetConvolveBias()
            {
                using (var image = new MagickImage())
                {
                    var settings = new MorphologySettings
                    {
                        ConvolveBias = new Percentage(70),
                    };

                    settings.SetImageArtifacts(image);
                    settings.RemoveImageArtifacts(image);

                    Assert.Empty(image.ArtifactNames);
                }
            }
Beispiel #9
0
                public void ShouldSetConvolveScale()
                {
                    using (var image = new MagickImage())
                    {
                        var settings = new MorphologySettings
                        {
                            ConvolveScale = new MagickGeometry(1, 2, 3, 4),
                        };

                        ArtifactsHelper.SetImageArtifacts(image, settings);

                        Assert.Single(image.ArtifactNames);
                        Assert.Equal("3x4+1+2", image.GetArtifact("convolve:scale"));
                    }
                }
Beispiel #10
0
                public void ShouldSetConvolveBias()
                {
                    using (var image = new MagickImage())
                    {
                        var settings = new MorphologySettings
                        {
                            ConvolveBias = new Percentage(70),
                        };

                        ArtifactsHelper.SetImageArtifacts(image, settings);

                        Assert.Single(image.ArtifactNames);
                        Assert.Equal("70%", image.GetArtifact("convolve:bias"));
                    }
                }
Beispiel #11
0
        public string ProcessImage(string imagePath)
        {
            string fileName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".png";

            MagickImage img = new MagickImage(imagePath);

            img = (MagickImage)img.Clone();
            var settings = new MorphologySettings();

            settings.Channels        = Channels.Alpha;
            settings.Method          = MorphologyMethod.Distance;
            settings.Kernel          = Kernel.Euclidean;
            settings.KernelArguments = "1,10!";

            img.Alpha(AlphaOption.Set);
            img.VirtualPixelMethod = VirtualPixelMethod.Transparent;
            img.Morphology(settings);
            img.Write(fileName);

            return(fileName);
        }
Beispiel #12
0
        private void btnProcessImage_Click(object sender, EventArgs e)
        {
            MagickImage img = new MagickImage(picImageCaptcha.ImageLocation);

            img = (MagickImage)img.Clone();
            var settings = new MorphologySettings();

            settings.Channels        = Channels.Alpha;
            settings.Method          = MorphologyMethod.Distance;
            settings.Kernel          = Kernel.Euclidean;
            settings.KernelArguments = "1,10!";

            img.Alpha(AlphaOption.Set);
            img.VirtualPixelMethod = VirtualPixelMethod.Transparent;
            img.Morphology(settings);
            img.Write(Application.StartupPath + Path.GetFileName(picImageCaptcha.ImageLocation));

            Image image = new Bitmap(Application.StartupPath + Path.GetFileName(picImageCaptcha.ImageLocation));

            picImageCaptcha.Image         = image;
            picImageCaptcha.ImageLocation = Application.StartupPath + Path.GetFileName(picImageCaptcha.ImageLocation);

            //using (var image = new MagickImage(picImageCaptcha.ImageLocation))
            //{
            //    // -alpha off ) ^
            //    image.Alpha(AlphaOption.Off);

            //    using (var images = new MagickImageCollection())
            //    {
            //        // ( -clone 0
            //        var tmp1 = image.Clone();

            //        // -morphology close rectangle:1x50
            //        tmp1.Morphology(MorphologyMethod.Close, "rectangle:1x50");

            //        // -negate
            //        tmp1.Negate();

            //        // +write tmp1.png ) ^
            //        tmp1.Write(Application.StartupPath + "\\tmp1.png");

            //        images.Add(tmp1);

            //        // ( -clone 0
            //        var tmp2 = image.Clone();

            //        // -morphology close rectangle:50x1
            //        tmp2.Morphology(MorphologyMethod.Close, "rectangle:50x1");

            //        // -negate
            //        tmp2.Negate();

            //        // +write tmp2.png ) ^
            //        tmp2.Write(Application.StartupPath + "\\tmp2.png");

            //        images.Add(tmp2);

            //        // -evaluate-sequence add
            //        using (var tmp3 = images.Evaluate(EvaluateOperator.Add))
            //        {
            //            // +write tmp3.png ) ^
            //            tmp3.Write(Application.StartupPath + "\\tmp3.png");

            //            // -compose plus -composite ^
            //            image.Composite(tmp3, CompositeOperator.Plus);

            //            // result.png
            //            image.Write(Application.StartupPath + Path.GetFileName(picImageCaptcha.ImageLocation));
            //        }
            //    }
            //}
        }
Beispiel #13
0
        public async Task DoNetwork()
        {
            OpenCL.IsEnabled = false;
            var cacheFile = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\stitch_cache.json";

            State state = new State();

            try
            {
                state = JsonConvert.DeserializeObject <State>(File.ReadAllText(cacheFile));
                Console.WriteLine($"Using state from {cacheFile}");
            } catch
            {
                Console.WriteLine("Couldn't load cache");
            }
            //state = new State();
            AppState = state;


            var workerPool = new LimitedConcurrencyLevelTaskScheduler(Math.Max(Environment.ProcessorCount - 2, 1)); // / 2, 1));
            //var workerPool = new LimitedConcurrencyLevelTaskScheduler(1);
            var snapshotState = new ActionBlock <State>((s) =>
            {
                var content = "";
                s.Lock(lockedState => content = JsonConvert.SerializeObject(lockedState));
                WriteAllTextWithBackup(cacheFile, content);
                this.Dispatcher.Invoke(() => Joins.ItemsSource = AppState.Joins);
            }, new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = 1
            });

            state.ChangeListener = snapshotState;

            var blockOptions = new ExecutionDataflowBlockOptions
            {
                TaskScheduler          = workerPool,
                MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded // Handled by underlying scheduler
            };

            //var sourceDir = "C:/Users/Xavier/Source/ori-tracker/MapStitcher/Screenshots";
            var sourceDir = "C:/Users/Xavier/Source/ori-tracker/MapStitcher/4KScreenshots";

            /*
             * IMagickImage image1 = new MagickImage(System.IO.Path.GetFullPath($"{sourceDir}/../Temp/forlorn-1.png"));
             * image1 = image1.Clone();
             * var settings = new MorphologySettings
             * {
             *  Channels = Channels.Alpha,
             *  Method = MorphologyMethod.Distance,
             *  Kernel = Kernel.Euclidean,
             *  KernelArguments = "1,50!"
             * };
             *
             * image1.Alpha(AlphaOption.Set);
             * image1.VirtualPixelMethod = VirtualPixelMethod.Transparent;
             * image1.Morphology(settings);
             * image1.Write(System.IO.Path.GetFullPath($"{sourceDir}/../Temp/forlorn-test.png"));
             */

            /*
             * MagickImage image1 = new MagickImage($"{sourceDir}/sorrow-1.png");
             * MagickImage image2 = new MagickImage($"{sourceDir}/sorrow-2.png");
             */

            /*
             * var sourceFiles = new List<string>
             * {
             *  $"{sourceDir}\\387290_20180314160604_1.png",
             * };
             */
            var sourceFiles = Directory.GetFiles(sourceDir, "*.png");

            /*
             * var sourceFiles = new List<string>
             * {
             *  $"{sourceDir}\\forlorn-1.png",
             *  $"{sourceDir}\\forlorn-2.png",
             *  $"{sourceDir}\\forlorn-3.png",
             * };
             */
            //state.ClearJoins();

            /*
             * state.ClearNeedle(new NeedleKey { Key = $"{sourceDir}/forlorn-3.png", Gravity = Gravity.West });
             * state.ClearJoin($"{sourceDir}/forlorn-2.png", $"{sourceDir}/forlorn-3.png");
             * state.ClearJoin($"{sourceDir}/forlorn-1.png", $"{sourceDir}/forlorn-3.png");
             * state.ClearJoin($"{sourceDir}/forlorn-2.png", $"{sourceDir}/forlorn-1.png");
             */
            this.Dispatcher.Invoke(() => SourceImages.ItemsSource = SourceImages2.ItemsSource = sourceFiles);
            this.Dispatcher.Invoke(() => Joins.ItemsSource        = AppState.Joins);
            UpdateUI();

            var loadFromDiskBlock = new TransformBlock <string, string>(path =>
            {
                // TODO: Make this a load and crop task
                var task = new StitchTask($"Load and crop {System.IO.Path.GetFileName(path)}");
                this.Dispatcher.Invoke(() => Tasks.Add(task));
                state.GetOrAddImage(path, () =>
                {
                    var image        = new MagickImage(path);
                    var originalSize = new Size(image.Width, image.Height);
                    int sideMargin   = (int)(image.Width * 0.15); // The sides have a subtle animated mask over them. 280px wide on 1920px resolution. Crop them out.
                    int topMargin    = (int)(image.Height * 0.17);
                    int bottomMargin = (int)(image.Height * 0.15);
                    var bounds       = new MagickGeometry(sideMargin, topMargin, image.Width - sideMargin * 2, image.Height - bottomMargin - topMargin);
                    image.Crop(bounds);
                    image.RePage();
                    //image.Write("C:\\Users\\Xavier\\Source\\ori-tracker\\MapStitcher\\Temp\\" + System.IO.Path.GetFileName(path));
                    return(image);
                });
                task.Complete("Done", false);
                return(path);
            }, blockOptions);

            var gravities = new TransformManyBlock <string, NeedleKey>(path =>
            {
                return(allGravities.Select(g => new NeedleKey()
                {
                    Key = path, Gravity = g
                }));
            }, blockOptions);

            var findNeedleBlock = new TransformBlock <NeedleKey, NeedleKey>(needle =>
            {
                var task = new FindNeedleTask(state, needle);
                this.Dispatcher.Invoke(() => Tasks.Add(task));
                task.Run();
                return(needle);
            }, blockOptions);

            var findJoinBlock = new TransformBlock <SearchKey, string>(t =>
            {
                var haystack = t.Item1;
                var needle   = t.Item2;

                var task = new SearchTask(state, haystack, needle);
                this.Dispatcher.Invoke(() => Tasks.Add(task));

                task.Run();

                completedSearchTasks++;
                return(haystack); // TODO: Figure out best thing to propagate. Maybe when match found?
            }, blockOptions);

            var broadcaster = new BroadcastBlock <string>(null);
            var cartesian   = new CartesianProductBlock <string, NeedleKey>();

            var propagate = new DataflowLinkOptions {
                PropagateCompletion = true
            };
            var headBlock = loadFromDiskBlock;

            headBlock.LinkTo(broadcaster, propagate);
            broadcaster.LinkTo(gravities, propagate);
            gravities.LinkTo(findNeedleBlock, propagate);

            // Don't propagate completion from left/right sources for cartesian join. It should
            // complete when _both_ are done (which is it's default behaviour)
            broadcaster.LinkTo(cartesian.Left, propagate);
            findNeedleBlock.LinkTo(cartesian.Right, propagate);

            var countTotals = new TransformManyBlock <Tuple <string, NeedleKey>, SearchKey>(t =>
            {
                var haystack = t.Item1;
                var needle   = t.Item2;
                var none     = Enumerable.Empty <SearchKey>();

                if (haystack == needle.Key || !state.GetNeedle(needle).MeetsThreshold())
                {
                    return(none);
                }

                var existingJoins  = state.Joins;
                var connectedJoins = new HashSet <HashSet <string> >();

                foreach (var join in existingJoins)
                {
                    var found = false;
                    foreach (var connectedSubset in connectedJoins)
                    {
                        if (connectedSubset.Contains(join.Image1) || connectedSubset.Contains(join.Image2))
                        {
                            connectedSubset.Add(join.Image1);
                            connectedSubset.Add(join.Image2);
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        var newSubset = new HashSet <string>();
                        newSubset.Add(join.Image1);
                        newSubset.Add(join.Image2);
                        connectedJoins.Add(newSubset);
                    }
                }
                connectedJoins.Aggregate(new HashSet <HashSet <string> >(), (acc, x) => {
                    var found = false;
                    foreach (var connectedSubset in acc)
                    {
                        if (connectedSubset.Overlaps(x))
                        {
                            connectedSubset.UnionWith(x);
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        acc.Add(x);
                    }
                    return(acc);
                });

                if (connectedJoins.Any(x => x.Contains(haystack) && x.Contains(needle.Key)))
                {
                    Console.WriteLine("Two images already connected via transitive joins, skipping");
                    return(none);
                }
                totalSearchTasks++;
                return(Enumerable.Repeat(SearchKey.Create(t.Item1, t.Item2), 1));
            }, new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = 1
            });

            cartesian.LinkTo(countTotals, propagate);
            countTotals.LinkTo(findJoinBlock, propagate);

            var sink = new ActionBlock <string>(s => { });

            findJoinBlock.LinkTo(sink, propagate);

            foreach (var file in sourceFiles)
            {
                headBlock.Post(file);
            }
            headBlock.Complete();

            await sink.Completion.ContinueWith(_ =>
            {
                Console.WriteLine("Pipeline Finished");

                /*
                 * this.Dispatcher.Invoke(() => TaskGrid.ItemsSource = Tasks.Where(x =>
                 * {
                 *  if (x is SearchTask)
                 *  {
                 *      var task = (SearchTask)x;
                 *      return task.Name.Contains("Found");
                 *      return task.searchResult.MeetsThreshold();
                 *      return task.searchResult.Distance < 2500;
                 *  }
                 *  return false;
                 * }));
                 */
                Dictionary <string, Point> completedJoins = new Dictionary <string, Point>();

                var remainingJoins = new List <State.Join>(state.Joins);
                var rejects        = new List <State.Join>();
                var images         = new MagickImageCollection();
                var lastCycleCount = 0;

                var morphologySettings = new MorphologySettings
                {
                    Channels        = Channels.Alpha,
                    Method          = MorphologyMethod.Distance,
                    Kernel          = Kernel.Euclidean,
                    KernelArguments = "1,50!"
                };

                while (remainingJoins.Count > 0 && remainingJoins.Count != lastCycleCount)
                {
                    lastCycleCount = remainingJoins.Count;
                    foreach (var join in remainingJoins)
                    {
                        if (completedJoins.Count == 0)
                        {
                            var tempPath  = System.IO.Path.GetTempFileName();
                            var tempPath2 = System.IO.Path.GetTempFileName();
                            // Initial seed
                            var i1 = state.Image(join.Image1).Clone();
                            var i2 = state.Image(join.Image2).Clone();

                            i1.Alpha(AlphaOption.Set);
                            i1.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                            i1.Morphology(morphologySettings);
                            i1.Write(tempPath);
                            i1.Dispose();
                            i1 = new MagickImage(tempPath);
                            i1.BackgroundColor = new MagickColor(18, 18, 18);

                            i2.Alpha(AlphaOption.Set);
                            i2.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                            i2.Morphology(morphologySettings);
                            i2.Write(tempPath2);
                            i2.Dispose();
                            i2 = new MagickImage(tempPath2);

                            i2.Page = new MagickGeometry($"{ToOffset(join.JoinPoint.X)}{ToOffset(join.JoinPoint.Y)}");
                            images.Add(i1);
                            images.Add(i2);

                            completedJoins.Add(join.Image1, new Point(0, 0));
                            completedJoins.Add(join.Image2, join.JoinPoint);
                            File.Delete(tempPath);
                            File.Delete(tempPath2);
                        }
                        else
                        {
                            Point offset = join.JoinPoint;
                            if (completedJoins.ContainsKey(join.Image1) && completedJoins.ContainsKey(join.Image2))
                            {
                                // NOOP
                            }
                            else if (completedJoins.ContainsKey(join.Image1))
                            {
                                completedJoins.TryGetValue(join.Image1, out offset);

                                var tempPath  = System.IO.Path.GetTempFileName();
                                var i2        = state.Image(join.Image2).Clone();
                                var joinPoint = new Point(join.JoinPoint.X + offset.X, join.JoinPoint.Y + offset.Y);
                                i2.Alpha(AlphaOption.Set);
                                i2.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                                i2.Morphology(morphologySettings);
                                i2.Write(tempPath);
                                //i2.Dispose();
                                //i2 = new MagickImage(tempPath);
                                i2.Page = new MagickGeometry($"{ToOffset(joinPoint.X)}{ToOffset(joinPoint.Y)}");
                                images.Add(i2);
                                File.Delete(tempPath);
                                completedJoins.Add(join.Image2, joinPoint);
                            }
                            else if (completedJoins.ContainsKey(join.Image2))
                            {
                                completedJoins.TryGetValue(join.Image2, out offset);

                                var tempPath  = System.IO.Path.GetTempFileName();
                                var i1        = state.Image(join.Image1).Clone();
                                var joinPoint = new Point(offset.X - join.JoinPoint.X, offset.Y - join.JoinPoint.Y);

                                i1.Alpha(AlphaOption.Set);
                                i1.VirtualPixelMethod = VirtualPixelMethod.Transparent;
                                i1.Morphology(morphologySettings);
                                i1.Write(tempPath);
                                //i1.Dispose();
                                //i1 = new MagickImage(tempPath);

                                i1.Page = new MagickGeometry($"{ToOffset(joinPoint.X)}{ToOffset(joinPoint.Y)}");

                                images.Add(i1);
                                File.Delete(tempPath);
                                completedJoins.Add(join.Image1, joinPoint);
                            }
                            else
                            {
                                rejects.Add(join);
                            }
                        }
                    }
                    remainingJoins = rejects.ToList();
                    rejects.Clear();
                }
                if (images.Any())
                {
                    var merged = images.Merge();

                    //merged.BackgroundColor = new MagickColor(0, 0, 0);
                    //merged.Alpha(AlphaOption.Remove);
                    //merged.Alpha(AlphaOption.Off);
                    merged.Write("C:\\Users\\Xavier\\Source\\ori-tracker\\MapStitcher\\Temp\\map.png");
                    DisplayImage(Viewer, merged);
                    Console.WriteLine("Done Compositing");
                }
            });
        }