예제 #1
0
        public async Task Main()
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            TrainingApi trainingApi = new TrainingApi()
            {
                ApiKey = CustomVisionAPIKey
            };

            trainingApi.HttpClient.Timeout = TimeSpan.FromMinutes(TimeoutMins);

            if (!QuickTest)
            {
                Console.WriteLine($"Creating Custom Vision Project: {ProjectName}");
                var project = trainingApi.CreateProject(ProjectName);

                Console.WriteLine($"Scanning subfolders within: {ImagePath}");
                List <Tag> allTags = new List <Tag>();
                foreach (var folder in Directory.EnumerateDirectories(ImagePath))
                {
                    string folderName = Path.GetFileName(folder);
                    var    tagNames   = folderName.Contains(",") ? folderName.Split(',').Select(t => t.Trim()).ToArray() : new string[] { folderName };

                    // Create tag for each comma separated value in subfolder name
                    foreach (var tag in tagNames)
                    {
                        // Check we've not already created this tag from another subfolder
                        if (!allTags.Any(t => t.Name.Equals(tag)))
                        {
                            Console.WriteLine($"Creating Tag: {tag}");
                            var imageTag = trainingApi.CreateTag(project.Id, tag);
                            allTags.Add(imageTag);
                        }
                    }
                }

                foreach (var currentFolder in Directory.EnumerateDirectories(ImagePath))
                {
                    string folderName = Path.GetFileName(currentFolder);
                    var    tagNames   = folderName.Contains(",") ? folderName.Split(',').Select(t => t.Trim()).ToArray() : new string[] { folderName };

                    try
                    {
                        // Load the images to be uploaded from disk into memory
                        Console.WriteLine($"Uploading: {ImagePath}\\{folderName} images...");

                        var images     = Directory.GetFiles(currentFolder).ToList();
                        var folderTags = allTags.Where(t => tagNames.Contains(t.Name)).Select(t => t.Id).ToList();
                        var imageFiles = images.Select(img => new ImageFileCreateEntry(Path.GetFileName(img), File.ReadAllBytes(img), folderTags)).ToList();
                        var imageBatch = new ImageFileCreateBatch(imageFiles);
                        var summary    = await trainingApi.CreateImagesFromFilesAsync(project.Id, new ImageFileCreateBatch(imageFiles));

                        // List any images that didn't make it
                        foreach (var imageResult in summary.Images.Where(i => !i.Status.Equals("OK")))
                        {
                            Console.WriteLine($"{ImagePath}\\{folderName}\\{imageResult.SourceUrl}: {imageResult.Status}");
                        }

                        Console.WriteLine($"Uploaded {summary.Images.Where(i => i.Status.Equals("OK")).Count()}/{images.Count()} images successfully from {ImagePath}\\{folderName}");
                    }
                    catch (Exception exp)
                    {
                        Console.WriteLine($"Error processing {currentFolder}: {exp.Source}:{exp.Message}");
                    }
                }

                try
                {
                    // Train CV model and set iteration to the default
                    Console.WriteLine($"Training model");
                    var iteration = trainingApi.TrainProject(project.Id);
                    while (iteration.Status.Equals("Training"))
                    {
                        Thread.Sleep(1000);
                        iteration = trainingApi.GetIteration(project.Id, iteration.Id);
                        Console.WriteLine($"Model status: {iteration.Status}");
                    }

                    if (iteration.Status.Equals("Completed"))
                    {
                        iteration.IsDefault = true;
                        trainingApi.UpdateIteration(project.Id, iteration.Id, iteration);
                        Console.WriteLine($"Iteration: {iteration.Id} set as default");
                    }
                    else
                    {
                        Console.WriteLine($"Iteration status: {iteration.Status}");
                    }
                }
                catch (Exception exp)
                {
                    Console.WriteLine($"Error training model (check you have at least 5 images per tag and 2 tags)");
                    Console.WriteLine($"Error {exp.Source}: {exp.Message}");
                }
            }
            else
            {
                // Quick test existing (trained) model
                Console.WriteLine($"Custom Vision Quick test: {ProjectName} with image {ImagePath}");

                // Retrieve CV project
                var projects = trainingApi.GetProjects();
                var project  = projects.Where(p => p.Name.Equals(ProjectName)).FirstOrDefault();
                if (project == null)
                {
                    Console.WriteLine($"Can't find Custom Vision Project: {ProjectName}");
                    return;
                }

                // Read test image
                if (!File.Exists(ImagePath))
                {
                    Console.WriteLine($"Can't find image: {ImagePath}");
                    return;
                }

                var image = new MemoryStream(File.ReadAllBytes(ImagePath));

                // Get the default iteration to test against and check results
                var iterations       = trainingApi.GetIterations(project.Id);
                var defaultIteration = iterations.Where(i => i.IsDefault == true).FirstOrDefault();
                if (defaultIteration == null)
                {
                    Console.WriteLine($"No default iteration has been set");
                    return;
                }

                var result = trainingApi.QuickTestImage(project.Id, image, defaultIteration.Id);
                foreach (var prediction in result.Predictions)
                {
                    Console.WriteLine($"Tag: {prediction.Tag} Probability: {prediction.Probability}");
                }
            }

            // fin
            stopwatch.Stop();
            Console.WriteLine($"Done.");
            Console.WriteLine($"Total time: {stopwatch.Elapsed}");
        }
예제 #2
0
        static void Main(string[] args)
        {
            var keys = GetApiKeys();

            var trainingApi = new TrainingApi {
                ApiKey = keys.TrainingKey
            };
            var predictionEndpoint = new PredictionEndpoint {
                ApiKey = keys.PredictionKey
            };

            var projects    = trainingApi.GetProjects();
            var herbProject = projects.FirstOrDefault(p => p.Name == "Herbs");

            Console.WriteLine("Press 1 to predict and 2 to train:");
            var pathChoice = Console.ReadLine();

            if ("1".Equals(pathChoice))
            {
                Console.WriteLine("Press 1 to predict on a URL or 2 to predict on a local file:");
                var predictType = Console.ReadLine();

                if ("1".Equals(predictType))
                {
                    Console.WriteLine("Input the URL to an image to test:");
                    var imageUrl = Console.ReadLine();

                    if (herbProject != null)
                    {
                        var result = predictionEndpoint.PredictImageUrl(herbProject.Id, new Microsoft.Cognitive.CustomVision.Prediction.Models.ImageUrl(imageUrl));

                        PrintResults(result);
                    }
                }
                else
                {
                    Console.WriteLine("Input path to image to test:");
                    var imagePath = Console.ReadLine();

                    if (!File.Exists(imagePath))
                    {
                        Console.WriteLine("File does not exist. Press enter to exit.");
                        Console.ReadLine();
                        return;
                    }

                    Console.WriteLine("Image predictions:");

                    var imageFile = File.OpenRead(imagePath);

                    if (herbProject != null)
                    {
                        var result = predictionEndpoint.PredictImage(herbProject.Id, imageFile);

                        PrintResults(result);
                    }
                    else
                    {
                        Console.WriteLine("Project doesn't exist.");
                    }
                }

                Console.ReadLine();
            }
            else
            {
                Console.WriteLine("Input path to image to train model with:");
                var imagePath = Console.ReadLine();

                Console.WriteLine("What tag would you give this image? Rosemary, cilantro, or basil?");
                var imageTag = Console.ReadLine();

                var capitilizedTag = char.ToUpper(imageTag.First()) + imageTag.Substring(1).ToLower();

                if (!File.Exists(imagePath))
                {
                    Console.WriteLine("File does not exist. Press enter to exit.");
                    Console.ReadLine();
                    return;
                }

                var imageFile = File.OpenRead(imagePath);

                var tags = trainingApi.GetTags(herbProject.Id);

                var matchedTag = tags.Tags.FirstOrDefault(t => t.Name == capitilizedTag);

                var memoryStream = new MemoryStream();
                imageFile.CopyTo(memoryStream);

                var fileCreateEntry = new ImageFileCreateEntry(imageFile.Name, memoryStream.ToArray());
                var fileCreateBatch = new ImageFileCreateBatch {
                    Images = new List <ImageFileCreateEntry> {
                        fileCreateEntry
                    }, TagIds = new List <Guid> {
                        matchedTag.Id
                    }
                };

                var result = trainingApi.CreateImagesFromFiles(herbProject.Id, fileCreateBatch);

                var resultImage = result.Images.FirstOrDefault();

                switch (resultImage.Status)
                {
                case "OKDuplicate":
                    Console.WriteLine("Image is already used for training. Please use another to train with");
                    Console.ReadLine();
                    break;

                default:
                    break;
                }

                var iteration = trainingApi.TrainProject(herbProject.Id);

                while (iteration.Status != "Completed")
                {
                    System.Threading.Thread.Sleep(1000);

                    iteration = trainingApi.GetIteration(herbProject.Id, iteration.Id);
                }

                iteration.IsDefault = true;
                trainingApi.UpdateIteration(herbProject.Id, iteration.Id, iteration);
                Console.WriteLine("Done training!");

                Console.ReadLine();
            }
        }
예제 #3
0
        public static async Task TrainAsync(ParsingOptions options)
        {
            // Create the Api, passing in the training key
            var trainingApi = new TrainingApi {
                ApiKey = options.TrainingKey
            };
            CognitiveServiceTrainerStorage storageImages = new CognitiveServiceTrainerStorage();

            if (options.Delete)
            {
                try
                {
                    await DeleteImagesAndTagsAsync(options, trainingApi);

                    storageImages.DeleteDB();
                    Console.WriteLine("Images and tags successfully deleted.");
                }
                catch
                {
                }
                if (string.IsNullOrEmpty(options.Folder))
                {
                    return;
                }
            }

            var fullFolder = Path.GetFullPath(options.Folder);

            if (!Directory.Exists(fullFolder))
            {
                Console.WriteLine($"Error: folder \"{fullFolder}\" does not exist.");
                Console.WriteLine(string.Empty);
                return;
            }

            try
            {
                //await DeleteImagesAndTagsAsync(options, trainingApi);
                foreach (var dir in Directory.EnumerateDirectories(fullFolder).Where(f => !Path.GetFileName(f).StartsWith("!")))
                {
                    var tagName = Path.GetFileName(dir).ToLower();
                    Console.WriteLine($"\nCheck latest images uploaded '{tagName}'...");
                    IList <Microsoft.Cognitive.CustomVision.Training.Models.Image> imagesAlreadyExists    = new List <Microsoft.Cognitive.CustomVision.Training.Models.Image>();
                    IList <Microsoft.Cognitive.CustomVision.Training.Models.Image> imagesAlreadyExistsTmp = new List <Microsoft.Cognitive.CustomVision.Training.Models.Image>();
                    int skip = 0;
                    while ((imagesAlreadyExistsTmp = await trainingApi.GetTaggedImagesAsync(options.ProjectId, tagIds: new[] { tagName }, take: 50, skip: skip)).Any())
                    {
                        skip += 50;
                        foreach (var item in imagesAlreadyExistsTmp)
                        {
                            imagesAlreadyExists.Add(item);
                        }
                    }

                    Console.WriteLine($"\nCreating tag '{tagName}'...");
                    var tagExist = storageImages.FindTag(tagName, options.ProjectId);
                    Tag tag      = null;
                    if (tagExist == null)
                    {
                        tag = await trainingApi.CreateTagAsync(options.ProjectId, tagName);

                        storageImages.InsertTag(new Storage.Collections.StorageTag {
                            IdCustomVision = tag.Id, TagName = tag.Name, ProjectId = options.ProjectId
                        });
                    }
                    else
                    {
                        if (trainingApi.GetTag(tagExist.ProjectId, tagExist.IdCustomVision) == null)
                        {
                            await trainingApi.DeleteTagAsync(options.ProjectId, tagExist.IdCustomVision);

                            tag = await trainingApi.CreateTagAsync(options.ProjectId, tagName);

                            storageImages.InsertTag(new Storage.Collections.StorageTag {
                                IdCustomVision = tag.Id, TagName = tag.Name, ProjectId = options.ProjectId
                            });
                        }
                        else
                        {
                            tag = new Tag(tagExist.IdCustomVision, tagName);
                        }
                    }

                    var images = Directory.EnumerateFiles(dir, "*.*", SearchOption.AllDirectories)
                                 .Where(s => s.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase) ||
                                        s.EndsWith(".jpeg", StringComparison.InvariantCultureIgnoreCase) ||
                                        s.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase) ||
                                        s.EndsWith(".bmp", StringComparison.InvariantCultureIgnoreCase)).ToList();

                    List <ImageDto> tempImages = new List <ImageDto>();
                    for (int i = 0; i < images.Count; i++)
                    {
                        Stream imageToUpload = null;
                        string image         = images.ElementAt(i);
                        var    imageName     = Path.GetFileName(image);
                        var    storageImage  = storageImages.FindImage(image, options.ProjectId);
                        if (storageImage == null || !imagesAlreadyExists.Any(x => x.Id == storageImage.IdCustomVision))
                        {
                            // Resizes the image before sending it to the service.
                            using (var input = new MemoryStream(File.ReadAllBytes(image)))
                            {
                                if (options.Width.GetValueOrDefault() > 0 || options.Height.GetValueOrDefault() > 0)
                                {
                                    imageToUpload = await ResizeImageAsync(input, options.Width.GetValueOrDefault(), options.Height.GetValueOrDefault());
                                }
                                else
                                {
                                    imageToUpload = input;
                                }

                                tempImages.Add(new ImageDto
                                {
                                    FullName = image,
                                    FileName = imageName,
                                    Content  = imageToUpload.ToByteArray(),
                                    Tag      = tag
                                });
                                imageToUpload.Dispose();
                            }
                        }
                        else
                        {
                            Console.WriteLine($"Image already exist {imageName}...");
                        }
                        //Persist batch images
                        if (tempImages.Count % 32 == 0 && tempImages.Any() || (i == images.Count - 1))
                        {
                            await UploadImagesAsync(tempImages);

                            tempImages.Clear();
                            tempImages.Capacity = 0;
                        }
                    }
                }

                // Now there are images with tags start training the project
                Console.WriteLine("\nTraining...");
                var iteration = await trainingApi.TrainProjectAsync(options.ProjectId);

                // The returned iteration will be in progress, and can be queried periodically to see when it has completed
                while (iteration.Status == "Training")
                {
                    await Task.Delay(1000);

                    // Re-query the iteration to get it's updated status
                    iteration = trainingApi.GetIteration(options.ProjectId, iteration.Id);
                }

                // The iteration is now trained. Make it the default project endpoint
                iteration.IsDefault = true;
                trainingApi.UpdateIteration(options.ProjectId, iteration.Id, iteration);

                Console.WriteLine("Training completed.\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\nUnexpected error: {ex.GetBaseException()?.Message}.\n");
            }



            async Task UploadImagesAsync(List <ImageDto> images)
            {
                ImageFileCreateBatch imageFileCreateBatch = new ImageFileCreateBatch();

                imageFileCreateBatch.Images = new List <ImageFileCreateEntry>();
                foreach (var img in images)
                {
                    imageFileCreateBatch.Images.Add(new ImageFileCreateEntry
                    {
                        Name     = img.FullName,
                        TagIds   = new [] { img.Tag.Id },
                        Contents = img.Content
                    });
                    Console.WriteLine($"Uploading image {img.FileName}...");
                }
                await Policy
                .Handle <Exception>()
                .WaitAndRetryAsync(retries)
                .ExecuteAsync(async() =>
                {
                    ImageCreateSummary reponseCognitiveService = await trainingApi.CreateImagesFromFilesAsync(options.ProjectId, imageFileCreateBatch);
                    if (reponseCognitiveService.Images != null)
                    {
                        for (int i = 0; i < reponseCognitiveService.Images.Count; i++)
                        {
                            var img = reponseCognitiveService.Images.ElementAt(i);
                            // https://docs.microsoft.com/en-us/rest/api/cognitiveservices/customvisiontraining/createimagesfrompredictions/createimagesfrompredictions
                            if ((img.Status == "OK" || img.Status == "OKDuplicate") && img.Image != null)
                            {
                                var uploadedImage = img.Image;
                                var tagsToStore   = uploadedImage.Tags?
                                                    .Select(x => new Storage.Collections.StorageImageTag()
                                {
                                    Created = x.Created,
                                    TagId   = x.TagId
                                }).ToList();
                                storageImages.InsertImage(new Storage.Collections.StorageImage()
                                {
                                    ProjectId      = options.ProjectId,
                                    FullFileName   = imageFileCreateBatch.Images.ElementAt(i).Name,
                                    IdCustomVision = uploadedImage.Id,
                                    ImageUri       = uploadedImage.ImageUri,
                                    Created        = uploadedImage.Created,
                                    Height         = uploadedImage.Height,
                                    Tags           = tagsToStore,
                                    ThumbnailUri   = uploadedImage.ThumbnailUri,
                                    Width          = uploadedImage.Width
                                });
                            }
                            else
                            {
                                Console.WriteLine($"API bad response: {img.Status }");
                                throw new InvalidOperationException($"API bad response: {img.Status }");
                            }
                        }
                    }
                });

                await Task.Delay(500);
            }
        }