Ejemplo n.º 1
0
        static async Task <int> Main(string[] args)
        {
            try
            {
                //
                // Parse options
                //

                Options = new AppOptions();

                Options.Parse(args);

                if (Options.ShowList)
                {
                    var devices = await FrameSource.GetSourceNamesAsync();

                    Log.WriteLine("Available cameras:");

                    foreach (var device in devices)
                    {
                        Log.WriteLine(device);
                    }
                }

                if (Options.Exit)
                {
                    return(-1);
                }

                if (!Options.UseImages)
                {
                    if (string.IsNullOrEmpty(Options.DeviceId))
                    {
                        throw new ApplicationException("Please use --device to specify which camera to use");
                    }
                }

                try
                {
                    string sv            = AnalyticsInfo.VersionInfo.DeviceFamilyVersion;
                    ulong  v             = ulong.Parse(sv);
                    ulong  v1            = (v & 0xFFFF000000000000L) >> 48;
                    ulong  v2            = (v & 0x0000FFFF00000000L) >> 32;
                    ulong  v3            = (v & 0x00000000FFFF0000L) >> 16;
                    ulong  v4            = (v & 0x000000000000FFFFL);
                    var    systemVersion = $"{v1}.{v2}.{v3}.{v4}";

                    _stats.CurrentVideoDeviceId = Options.DeviceId;
                    _stats.Platform             = $"{AnalyticsInfo.VersionInfo.DeviceFamily} - {System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") ?? "Unknown"} - {systemVersion}";
                }
                catch (Exception)
                {
                }


                //
                // Init module client
                //

                if (Options.UseEdge)
                {
                    Log.WriteLine($"{AppOptions.AppName} module starting.");
                    await BlockTimer("Initializing Azure IoT Edge", async() => await InitEdge());
                }

                cts = new CancellationTokenSource();
                AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel();
                Console.CancelKeyPress += (sender, cpe) => cts.Cancel();

                //
                // Load model
                //

                ScoringModel model = null;
                await BlockTimer($"Loading modelfile '{Options.ModelPath}' on the {(Options.UseGpu ? "GPU" : "CPU")}",
                                 async() =>
                {
                    var d    = Directory.GetCurrentDirectory();
                    var path = d + "\\" + Options.ModelPath;
                    StorageFile modelFile = await AsAsync(StorageFile.GetFileFromPathAsync(path));
                    model = await ScoringModel.CreateFromStreamAsync(modelFile, Options.UseGpu);
                });

                _stats.OnnxModelLoaded  = true;
                _stats.CurrentOnnxModel = Options.ModelPath;
                _stats.IsGpu            = Options.UseGpu;

                // WebServer Code


                HttpServer httpsv            = null;
                bool       HttpServerStarted = false;

                if (Options.RunForever)
                {
                    try
                    {
                        Log.WriteLine($"Start HTTP Server on port : " + Options.WebServerPort.ToString());
                        httpsv = new HttpServer(Options.WebServerPort);
                        httpsv.Start();
                        httpsv.OnGet += HttpsvOnOnGet;

                        HttpServerStarted = true;
                        Log.WriteLine($"- HTTP Server Started.");
                        Log.WriteLine($"");
                    }
                    catch (Exception e)
                    {
                        HttpServerStarted = false;
                        Log.WriteLine($"Exiting - Websockets Server Failed to start : " + e.Message);
                    }
                }


                //
                // Open camera
                //

                FrameSource     frameSource     = null;
                ImageFileSource imageFileSource = null;

                if (Options.UseImages)
                {
                    imageFileSource = new ImageFileSource();
                    imageFileSource.ScanUpdateQueue(Options.ImagePath);
                }
                else
                {
                    frameSource = new FrameSource();
                    await frameSource.StartAsync(Options.DeviceId, Options.UseGpu);
                }

                _stats.DeviceInitialized = true;
                SetLatestStatsPayload(JsonConvert.SerializeObject(_stats));

                //
                // Main loop
                //
                do
                {
                    ScoringOutput outcome   = null;
                    int           evalticks = 0;
                    Log.WriteLineVerbose("Getting frame...");

                    byte[]      data          = new byte[] { };
                    byte[]      annotatedData = new byte[] { };
                    MessageBody message       = null;

                    //
                    // Use Image File Source or fall back to Webcam Source if not specified
                    //
                    if (Options.UseImages)
                    {
                        var(fileName, sbmp) = await imageFileSource.GetNextImageAsync(Options.ImagePath, cts.Token);

                        using (var vf = VideoFrame.CreateWithSoftwareBitmap(sbmp))
                        {
                            ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(vf);


                            _stats.TotalFrames = _stats.TotalFrames + 1;

                            //
                            // Evaluate model
                            //

                            var ticksTaken = await BlockTimer($"Running the model",
                                                              async() =>
                            {
                                var input = new ScoringInput()
                                {
                                    data = imageTensor
                                };
                                outcome = await model.EvaluateAsync(input);
                            });

                            evalticks = ticksTaken;

                            message = ResultsToMessage(outcome);
                            message.metrics.evaltimeinms = evalticks;
                            _stats.TotalEvaluations      = _stats.TotalEvaluations + 1;
                            message.imgSrc = fileName;

                            string summaryText = "";

                            if (message.results.Length > 0)
                            {
                                summaryText = $"Matched : {message.results[0].label} - Confidence ={message.results[0].confidence.ToString("P")} - Eval Time {message.metrics.evaltimeinms} ms";
                            }
                            data = await ImageUtils.GetConvertedImage(sbmp);

                            annotatedData = await ImageUtils.AnnotateImage(sbmp, $"Current Image : {fileName ?? "-"}", summaryText);
                        }
                    }
                    else
                    {
                        using (var frame = await frameSource.GetFrameAsync())
                        {
                            var inputImage = frame.VideoMediaFrame.GetVideoFrame();
                            ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage);

                            _stats.TotalFrames = _stats.TotalFrames + 1;

                            //
                            // Evaluate model
                            //
                            var ticksTaken = await BlockTimer("Running the model",
                                                              async() =>
                            {
                                var input = new ScoringInput()
                                {
                                    data = imageTensor
                                };
                                outcome = await model.EvaluateAsync(input);
                            });

                            evalticks = ticksTaken;

                            message = ResultsToMessage(outcome);
                            message.metrics.evaltimeinms = evalticks;
                            _stats.TotalEvaluations      = _stats.TotalEvaluations + 1;

                            string summaryText = "";

                            if (message.results.Length > 0)
                            {
                                summaryText = $"Matched : {message.results[0].label} - Confidence ={message.results[0].confidence.ToString("P")} - Eval Time {message.metrics.evaltimeinms} ms";
                            }
                            data = await ImageUtils.GetConvertedImage(inputImage.SoftwareBitmap);

                            annotatedData = await ImageUtils.AnnotateImage(inputImage.SoftwareBitmap, $"Current Webcam : {Options.DeviceId ?? "-"}", summaryText);
                        }
                    }

                    if (message != null)
                    {
                        //
                        // Print results
                        //
                        message.metrics.evaltimeinms = evalticks;
                        var json = JsonConvert.SerializeObject(message,
                                                               new JsonSerializerSettings
                        {
                            //won't print null imgSrc if null
                            NullValueHandling = NullValueHandling.Ignore
                        });
                        Log.WriteLineRaw($"Inferenced: {json}");

                        if (Options.UseWebServer)
                        {
                            //
                            // Update the latest webserver payload snapshots with data from inferencing
                            //
                            UpdateWebServerPayloads(message, data, annotatedData);
                        }

                        //
                        // Send results to Edge
                        //


                        if (Options.UseEdge)
                        {
                            var eventMessage = new Message(Encoding.UTF8.GetBytes(json));
                            await ioTHubModuleClient.SendEventAsync("resultsOutput", eventMessage);

                            // Let's not totally spam Edge :)
                            await Task.Delay(500);
                        }
                        else if (Options.UseImages)
                        {
                            //slow it down a little..
                            await Task.Delay(TimeSpan.FromSeconds(5));
                        }
                    }
                }while (Options.RunForever && !cts.Token.IsCancellationRequested);

                if (frameSource != null)
                {
                    await frameSource.StopAsync();
                }


                if (HttpServerStarted)
                {
                    try
                    {
                        Log.WriteLine($"- Stopping Web Server.");
                        httpsv.OnGet -= HttpsvOnOnGet;
                        httpsv.Stop();
                        httpsv = null;
                        Log.WriteLine($"- Web Server Stopped.");
                    }
                    catch (Exception)
                    {
                    }
                }

                return(0);
            }
            catch (Exception ex)
            {
                Log.WriteLineException(ex);
                return(-1);
            }
        }