3

We want to use the StitchEngine.dll from Microsofts Image Composite Editor (ICE) in one of our C# projects. There is minimal evidence, that people already accomplished this task, e.g. Richard in this SO question Getting an "InvalidCastException" when passing a Rectangle ValueType in c#. So, our question is, if somebody could provide a minimal working example, i.e. loading two images, stitching them, and exporting the resulting image.

At the moment, we are already stuck at the loading (or initialization) part. We have investigated the StitchEngineWrapper and StitchProjectInfo classes, but could not figure out, how exactly to load images. The StitchEngineWrapper.AddImageCacheLocations(IReadOnlyList<string> imageCacheLocations) method did not work for us!? The List<ImageInfo> StitchProjectInfo.SourceImages property is not accessible!? Using ILSpy didn't help us either.

Every hint in the right direction is much appreciated! Hopefully, Richard will see this question.

HansHirse
  • 18,010
  • 10
  • 38
  • 67
  • A minimal example is [available here](https://social.microsoft.com/Forums/en-US/7120f888-e214-4736-be38-972f98d7b9ce/implementing-ice-in-vbnet?forum=ice). Code looks good and simple to convert to C#, he merely suffered from the same bug that the SO user found. Do keep in mind that almost nobody is using it, buggy unmaintained MSR projects like that have a knack for disappearing without trace. – Hans Passant Mar 02 '19 at 17:45
  • I know that post, it's the only other source, I know. Nevertheless, as stated in my question, the method `AddImageCacheLocations` doesn't work for us. – HansHirse Mar 02 '19 at 19:34
  • 1
    You'll just get more code samples and you'll have to keep repeating "doesn't work". Being intentionally vague is a useless way to get help. Post the code you tried, state the .NET version you target, describe any error or exception you see. – Hans Passant Mar 02 '19 at 22:54
  • 1
    @HansPassant First, the target group of my question were exactly these few people, who are familiar with the `StitchEngine.dll` from ICE. Therefore, I wanted to keep my question as short as possible. I highly doubted, that there would be any other people willing to introduce themselves into the topic, since it's very specific. I could've posted two or three lines of code, which we thought they would be the entry point of the pipeline, and an error code, which our research revealed to be application specific. So, nobody than the aforementioned experts would've benefited from this ... [1/4] – HansHirse Mar 04 '19 at 06:42
  • 1
    @HansPassant information, but these are also the people, who don't need this information to give help. Second, your first comment wasn't helpful at all: I agree, that I could've included the link by myself to prevent it posted by someone, but you only stated "code looks good" without verifying that it's actually working. The rest was unrelated opinion. I was somehow annoyed, because of the "know-it-all" attitude of your comment, thus my short reply. Third, your second comment is an untenable accusation! There've been no code samples, I could've tested or comment on. As stated above, ... [2/4] – HansHirse Mar 04 '19 at 06:42
  • 1
    @HansPassant I haven't been "intentionally vague", sometimes one can't give a lot of information if you're stuck at the very beginning. That's why I wrote every hint is appreciated. Fourth, as a SO user with nearly 800k reputation, you should keep in mind, that your opinion can and will influence others. After your quite harsh comments, my question received downvotes. Against your personal opinion, ICE is not just a "buggy MSR project", but a widely used tool, and if you would've done some research on "automizing ICE", you would've seen that there are quite a few people interested in ... [3/4] – HansHirse Mar 04 '19 at 06:42
  • 1
    @HansPassant an API or something comparable. By now, Simon's answer seems to be the only code example for successfully using the `StitchEngine.dll` in an C# project. So, even if you think, I didn't provide enough information for my question to be "good", the topic itself is definitely relevant. And even if people keep downvoting my question (for whatever reasons), I hope Simon's answer will get a lot of upvotes. Sorry for the long monologue, but not every "newbie" on SO is a student asking for how to write a for loop. [4/4] – HansHirse Mar 04 '19 at 06:42

1 Answers1

3

ICE is a state machine running in the background, so you have to wait for each step completion before going to the next one. Here is a sample Console C# app that should work, provided you added at least two valid images (test with the UI first):

class Program
{
    static void Main(string[] args)
    {
        using (var stitch = new StitchEngineWrapper()) // using Microsoft.Research.ICE.Stitching;
        {
            var taskCompleted = new AutoResetEvent(false);
            stitch.ProgressChanged += (s, e) => Console.Write(".");
            stitch.TaskCompleted += (s, e) =>
            {
                Console.WriteLine();
                taskCompleted.Set();
            };

            var pi = new StitchProjectInfo();
            pi.SourceImages.Add(new ImageInfo(@"c:\myPath\lenna1.jpg", null));
            pi.SourceImages.Add(new ImageInfo(@"c:\myPath\lenna2.jpg", null));
            if (!stitch.InitializeFromProjectInfo(pi) || stitch.HasLastError)
            {
                Console.WriteLine("Initialization failed.");
                if (stitch.HasLastError)
                {
                    Console.WriteLine("Error 0x" + stitch.LastError.ToString("x8") + ": " + stitch.LastErrorMessage);
                }
                return;
            }
            Console.WriteLine("Initialization ok.");

            stitch.StartAligning();
            taskCompleted.WaitOne(Timeout.Infinite);
            if (stitch.AlignedCount < 2 || stitch.HasLastError)
            {
                Console.WriteLine("Alignement failed. Wrong input.");
                Console.WriteLine("Error 0x" + stitch.LastError.ToString("x8") + ": " + stitch.LastErrorMessage);
                return;
            }
            Console.WriteLine("Alignement ok.");

            stitch.StartCompositing();
            taskCompleted.WaitOne(Timeout.Infinite);
            if (stitch.HasLastError)
            {
                Console.WriteLine("Composition failed.");
                Console.WriteLine("Error 0x" + stitch.LastError.ToString("x8") + ": " + stitch.LastErrorMessage);
                return;
            }
            Console.WriteLine("Composition ok.");

            stitch.StartProjecting();
            taskCompleted.WaitOne(Timeout.Infinite);
            if (stitch.HasLastError)
            {
                Console.WriteLine("Projection failed.");
                Console.WriteLine("Error 0x" + stitch.LastError.ToString("x8") + ": " + stitch.LastErrorMessage);
                return;
            }
            Console.WriteLine("Projection ok.");

            var options = new OutputOptions(ExportFormat.JPEG, 75, true, false, false);
            stitch.StartExporting(@"c:\myPath\stitched.jpg", stitch.ResetCropRect, 1, options, false);
            taskCompleted.WaitOne(Timeout.Infinite);
            Console.WriteLine("Export ok.");
        }
    }
}

Here is a sample Lenna stiched (note images Y-offset and overlap):

left:

enter image description here

right:

enter image description here

stitched:

enter image description here

Note black artifacts and funny hair on the right due to stitching

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Amazing! I did a fast test at home using two images from my panorama collection, and it worked like a charm. Tomorrow, I will use your code as a base for our task. There's a lot of specific options, we'll need to set, but I guess that'll be no problem, since we now have the basic pipeline. I will also give you some more detailed feedback, since I have no time at the moment. Nevertheless, I highly appreciate your answer, and I'm more than pleased to award the bounty! :-) – HansHirse Mar 03 '19 at 13:17
  • So, I could expand your solution to fit our task perfectly. Again, many thanks for your efforts! Personally, I'd be interested, how you figured out, how the pipeline works (especially the state machine part), just to know, how and where to look, if I'm in such a situation again. Maybe, you can give a few hints. – HansHirse Mar 04 '19 at 05:51