static void Main(string[] args) { // You can either add your training key here, pass it on the command line, or type it in when the program runs string trainingKey = GetTrainingKey("<your key here>", args); // Create the Api, passing in a credentials object that contains the training key TrainingApiCredentials trainingCredentials = new TrainingApiCredentials(trainingKey); TrainingApi trainingApi = new TrainingApi(trainingCredentials); // Create a new project Console.WriteLine("Creating new project:"); var project = trainingApi.CreateProject("Bike Type"); // Make two tags in the new project var MbikesTag = trainingApi.CreateTag(project.Id, "Mountain"); var RbikesTag = trainingApi.CreateTag(project.Id, "Racing"); // Add some images to the tags Console.WriteLine("\\tUploading images"); LoadImagesFromDisk(); // Images can be uploaded one at a time foreach (var image in MbikesImages) { trainingApi.CreateImagesFromData(project.Id, image, new List <string> () { MbikesTag.Id.ToString() }); } // Or uploaded in a single batch trainingApi.CreateImagesFromData(project.Id, RbikesImages, new List <Guid> () { RbikesTag.Id }); // Now there are images with tags start training the project Console.WriteLine("\\tTraining"); var iteration = trainingApi.TrainProject(project.Id); // The returned iteration will be in progress, and can be queried periodically to see when it has completed while (iteration.Status == "Training") { Thread.Sleep(1000); // Re-query the iteration to get it's updated status iteration = trainingApi.GetIteration(project.Id, iteration.Id); } // The iteration is now trained. Make it the default project endpoint iteration.IsDefault = true; trainingApi.UpdateIteration(project.Id, iteration.Id, iteration); Console.WriteLine("Done!\\n"); // Now there is a trained endpoint, it can be used to make a prediction // Get the prediction key, which is used in place of the training key when making predictions var account = trainingApi.GetAccountInfo(); var predictionKey = account.Keys.PredictionKeys.PrimaryKey; // Create a prediction endpoint, passing in a prediction credentials object that contains the obtained prediction key PredictionEndpointCredentials predictionEndpointCredentials = new PredictionEndpointCredentials(predictionKey); PredictionEndpoint endpoint = new PredictionEndpoint(predictionEndpointCredentials); // Make a prediction against the new project Console.WriteLine("Making a prediction:"); var result = endpoint.PredictImage(project.Id, testImage); // Loop over each prediction and write out the results foreach (var c in result.Predictions) { Console.WriteLine($"\\t{c.Tag}: {c.Probability:P1}"); } Console.ReadKey(); }
private static void CreateTheModel(string trainingSetPath, Project project) { var trainingKey = ConfigurationManager.AppSettings["CustomVision_TrainingKey"]; var trainingApi = new TrainingApi() { ApiKey = trainingKey }; var trainingModel = new List <Model>(); bool performImageAugmentation = true; try { performImageAugmentation = Convert.ToBoolean(ConfigurationManager.AppSettings["PerformImageAugmentation"]); } catch { } int widthHeight = 299; try { widthHeight = Convert.ToInt32(ConfigurationManager.AppSettings["WidthHeight"]); } catch { } int padImages = 10; try { padImages = Convert.ToInt32(ConfigurationManager.AppSettings["PadImages"]); } catch { } var trainingSet = Directory.GetDirectories(trainingSetPath); foreach (var subdirectory in trainingSet) { var dir = new DirectoryInfo(subdirectory); var name = dir.Name; Console.WriteLine($"\tAdding Tag - {name}"); var tag = trainingApi.CreateTag(project.Id, name); var images = Directory.GetFiles($"{subdirectory}").Select(f => { trainingModel.Add(new Model() { Label = name, Path = f }); return(new MemoryStream(File.ReadAllBytes(f))); }).ToList(); foreach (var image in images) { try { Console.WriteLine($"\tUploading image with tag: {tag.Name}"); if (performImageAugmentation) { // flip from RGB to BGR System.Drawing.Bitmap img = new System.Drawing.Bitmap(image); Image <Bgr, byte> ogImg = new Image <Bgr, byte>(img); // perform Intensity Image Equalization Image <Ycc, byte> ycrcb = ogImg.Convert <Ycc, byte>(); ycrcb._EqualizeHist(); ogImg = ycrcb.Convert <Bgr, byte>(); //replace original image with equalized image int top = 0; int bottom = 0; int left = 0; int right = 0; if (img.Width != img.Height) { // we need to pad our image if the width and height aren't set already in a previous smart crop step if (img.Width < img.Height) { int dif = img.Height - img.Width; left = dif / 2; right = dif - left; } if (img.Height < img.Width) { int dif = img.Width - img.Height; top = dif / 2; bottom = dif - top; } } if (padImages > 0) { top += padImages; bottom += padImages; left += padImages; right += padImages; } if ((top > 0) || (bottom > 0) || (left > 0) || (right > 0)) { Image <Bgr, byte> padImg = new Image <Bgr, byte>(img.Width + left + right, img.Height + top + bottom); CvInvoke.CopyMakeBorder(ogImg, padImg, top, bottom, left, right, Emgu.CV.CvEnum.BorderType.Constant, new MCvScalar(255, 255, 255)); // pad the image with a white background ogImg = padImg; } if (ogImg.Width != widthHeight) { // resize the padded image ogImg = ogImg.Resize(widthHeight, widthHeight, Emgu.CV.CvEnum.Inter.Linear); } trainStream(ogImg.ToBitmap(), trainingApi, project.Id, tag.Id.ToString()); for (var i = 0; i < 3; i++) { if ((new Random().Next(1, 11)) <= 5) { // 50% of the time flip the image horizontally before rotation ogImg = ogImg.Flip(Emgu.CV.CvEnum.FlipType.Horizontal); } trainStream(ogImg.Rotate(new Random().Next(-45, 45), new Bgr(255, 255, 255)).ToBitmap(), trainingApi, project.Id, tag.Id.ToString()); // rotate with a white background } } else { trainingApi.CreateImagesFromData(project.Id, image, new List <string>() { tag.Id.ToString() }); } } catch (Exception e) { //kill exception and carry on Console.WriteLine(e); } } } try { using (TextWriter writer = new StreamWriter($"{trainingSetPath}\\trainingModel.csv")) { var csv = new CsvWriter(writer); csv.WriteRecords(trainingModel); } } catch (Exception e) { Console.WriteLine(e); } }
static void Main(string[] args) { // Add your training & prediction key from the settings page of the portal string trainingKey = "<enter your training key here>"; string predictionKey = "<enter your prediction key here>"; // Create the Api, passing in the training key TrainingApi trainingApi = new TrainingApi() { ApiKey = trainingKey }; // Find the object detection domain var domains = trainingApi.GetDomains(); var objDetectionDomain = domains.FirstOrDefault(d => d.Type == "ObjectDetection"); // Create a new project Console.WriteLine("Creating new project:"); var project = trainingApi.CreateProject("My New Project", null, objDetectionDomain.Id); // Make two tags in the new project var forkTag = trainingApi.CreateTag(project.Id, "fork"); var scissorsTag = trainingApi.CreateTag(project.Id, "scissors"); Dictionary <string, double[]> fileToRegionMap = new Dictionary <string, double[]>() { // A bounding box is specified in normalized coordinates using pixels of the object in the image. // Normalized Left = Left / Width (in Pixels) // Normalized Top = Top / Height (in Pixels) // Normalized Bounding Box Width = (Right - Left) / Width (in Pixels) // Normalized Bounding Box Height = (Bottom - Top) / Height (in Pixels) // FileName, Left, Top, Width, Height { "scissors_1", new double[] { 0.4007353, 0.194068655, 0.259803921, 0.6617647 } }, { "scissors_2", new double[] { 0.426470578, 0.185898721, 0.172794119, 0.5539216 } }, { "scissors_3", new double[] { 0.289215684, 0.259428144, 0.403186262, 0.421568632 } }, { "scissors_4", new double[] { 0.343137264, 0.105833367, 0.332107842, 0.8055556 } }, { "scissors_5", new double[] { 0.3125, 0.09766343, 0.435049027, 0.71405226 } }, { "scissors_6", new double[] { 0.379901975, 0.24308826, 0.32107842, 0.5718954 } }, { "scissors_7", new double[] { 0.341911763, 0.20714055, 0.3137255, 0.6356209 } }, { "scissors_8", new double[] { 0.231617644, 0.08459154, 0.504901946, 0.8480392 } }, { "scissors_9", new double[] { 0.170343131, 0.332957536, 0.767156839, 0.403594762 } }, { "scissors_10", new double[] { 0.204656869, 0.120539248, 0.5245098, 0.743464053 } }, { "scissors_11", new double[] { 0.05514706, 0.159754932, 0.799019635, 0.730392158 } }, { "scissors_12", new double[] { 0.265931368, 0.169558853, 0.5061275, 0.606209159 } }, { "scissors_13", new double[] { 0.241421565, 0.184264734, 0.448529422, 0.6830065 } }, { "scissors_14", new double[] { 0.05759804, 0.05027781, 0.75, 0.882352948 } }, { "scissors_15", new double[] { 0.191176474, 0.169558853, 0.6936275, 0.6748366 } }, { "scissors_16", new double[] { 0.1004902, 0.279036, 0.6911765, 0.477124184 } }, { "scissors_17", new double[] { 0.2720588, 0.131977156, 0.4987745, 0.6911765 } }, { "scissors_18", new double[] { 0.180147052, 0.112369314, 0.6262255, 0.6666667 } }, { "scissors_19", new double[] { 0.333333343, 0.0274019931, 0.443627447, 0.852941155 } }, { "scissors_20", new double[] { 0.158088237, 0.04047389, 0.6691176, 0.843137264 } }, { "fork_1", new double[] { 0.145833328, 0.3509314, 0.5894608, 0.238562092 } }, { "fork_2", new double[] { 0.294117659, 0.216944471, 0.534313738, 0.5980392 } }, { "fork_3", new double[] { 0.09191177, 0.0682516545, 0.757352948, 0.6143791 } }, { "fork_4", new double[] { 0.254901975, 0.185898721, 0.5232843, 0.594771266 } }, { "fork_5", new double[] { 0.2365196, 0.128709182, 0.5845588, 0.71405226 } }, { "fork_6", new double[] { 0.115196079, 0.133611143, 0.676470637, 0.6993464 } }, { "fork_7", new double[] { 0.164215669, 0.31008172, 0.767156839, 0.410130739 } }, { "fork_8", new double[] { 0.118872553, 0.318251669, 0.817401946, 0.225490168 } }, { "fork_9", new double[] { 0.18259804, 0.2136765, 0.6335784, 0.643790841 } }, { "fork_10", new double[] { 0.05269608, 0.282303959, 0.8088235, 0.452614367 } }, { "fork_11", new double[] { 0.05759804, 0.0894935, 0.9007353, 0.3251634 } }, { "fork_12", new double[] { 0.3345588, 0.07315363, 0.375, 0.9150327 } }, { "fork_13", new double[] { 0.269607842, 0.194068655, 0.4093137, 0.6732026 } }, { "fork_14", new double[] { 0.143382356, 0.218578458, 0.7977941, 0.295751631 } }, { "fork_15", new double[] { 0.19240196, 0.0633497, 0.5710784, 0.8398692 } }, { "fork_16", new double[] { 0.140931368, 0.480016381, 0.6838235, 0.240196079 } }, { "fork_17", new double[] { 0.305147052, 0.2512582, 0.4791667, 0.5408496 } }, { "fork_18", new double[] { 0.234068632, 0.445702642, 0.6127451, 0.344771236 } }, { "fork_19", new double[] { 0.219362751, 0.141781077, 0.5919118, 0.6683006 } }, { "fork_20", new double[] { 0.180147052, 0.239820287, 0.6887255, 0.235294119 } } }; // Add all images for fork var imagePath = Path.Combine("Images", "fork"); var imageFileEntries = new List <ImageFileCreateEntry>(); foreach (var fileName in Directory.EnumerateFiles(imagePath)) { var region = fileToRegionMap[Path.GetFileNameWithoutExtension(fileName)]; imageFileEntries.Add(new ImageFileCreateEntry(fileName, File.ReadAllBytes(fileName), null, new List <Region>(new Region[] { new Region(forkTag.Id, region[0], region[1], region[2], region[3]) }))); } trainingApi.CreateImagesFromFiles(project.Id, new ImageFileCreateBatch(imageFileEntries)); // Add all images for scissors imagePath = Path.Combine("Images", "scissors"); imageFileEntries = new List <ImageFileCreateEntry>(); foreach (var fileName in Directory.EnumerateFiles(imagePath)) { var region = fileToRegionMap[Path.GetFileNameWithoutExtension(fileName)]; imageFileEntries.Add(new ImageFileCreateEntry(fileName, File.ReadAllBytes(fileName), null, new List <Region>(new Region[] { new Region(scissorsTag.Id, region[0], region[1], region[2], region[3]) }))); } trainingApi.CreateImagesFromFiles(project.Id, new ImageFileCreateBatch(imageFileEntries)); // Now there are images with tags start training the project Console.WriteLine("\tTraining"); var iteration = trainingApi.TrainProject(project.Id); // The returned iteration will be in progress, and can be queried periodically to see when it has completed while (iteration.Status == "Training") { Thread.Sleep(1000); // Re-query the iteration to get its updated status iteration = trainingApi.GetIteration(project.Id, iteration.Id); } // The iteration is now trained. Make it the default project endpoint iteration.IsDefault = true; trainingApi.UpdateIteration(project.Id, iteration.Id, iteration); Console.WriteLine("Done!\n"); // Now there is a trained endpoint, it can be used to make a prediction // Create a prediction endpoint, passing in the obtained prediction key PredictionEndpoint endpoint = new PredictionEndpoint() { ApiKey = predictionKey }; // Make a prediction against the new project Console.WriteLine("Making a prediction:"); var imageFile = Path.Combine("Images", "test", "test_image.jpg"); using (var stream = File.OpenRead(imageFile)) { var result = endpoint.PredictImage(project.Id, File.OpenRead(imageFile)); // Loop over each prediction and write out the results foreach (var c in result.Predictions) { Console.WriteLine($"\t{c.TagName}: {c.Probability:P1} [ {c.BoundingBox.Left}, {c.BoundingBox.Top}, {c.BoundingBox.Width}, {c.BoundingBox.Height} ]"); } } Console.ReadKey(); }
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); } }
protected override async Task <CreateImageSummaryModel> UploadImagesByTagsAsync(IEnumerable <Image> images, Guid projectId, ICollection <Guid> tagIds) { var imageArray = images.ToList(); Func <Task <CreateImageSummaryModel> > createImagesFromUrls = async() => await TrainingApi.CreateImagesFromUrlsAsync( projectId, new ImageUrlCreateBatch(tagIds : tagIds.ToList(), urls : imageArray.Select(x => x.Path).ToList())); return(await RetryHelper.RetryFuncAsync( createImagesFromUrls, new[] { typeof(HttpOperationException), typeof(TaskCanceledException) }, RetryTimes)); }
public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req, TraceWriter log) { try { var allTags = new List <string>(); var json = req.Content.ReadAsStringAsync().Result; var jobj = JObject.Parse(json); var tags = (JArray)jobj["tags"]; var term = jobj["term"].ToString(); var projectId = jobj["projectId"].ToString(); var trainingKey = jobj["trainingKey"].ToString(); var offset = 0; if (jobj["offset"] != null) { offset = (int)jobj["offset"]; } var imageUrls = await SearchForImages(term, offset); var api = new TrainingApi(new TrainingApiCredentials(trainingKey)); var project = api.GetProject(Guid.Parse(projectId)); var tagModels = new List <ImageTagModel>(); var existingTags = api.GetTags(project.Id); foreach (string tag in tags) { ImageTagModel model = existingTags.Tags.SingleOrDefault(t => t.Name == tag); if (model == null) { model = api.CreateTag(project.Id, tag.Trim()); } tagModels.Add(model); } var batch = new ImageUrlCreateBatch(tagModels.Select(m => m.Id).ToList(), imageUrls); var summary = api.CreateImagesFromUrls(project.Id, batch); //if(!summary.IsBatchSuccessful) // return req.CreateErrorResponse(HttpStatusCode.BadRequest, "Image batch was unsuccessful"); //Traing the classifier and generate a new iteration, that we'll set as the default var iteration = api.TrainProject(project.Id); while (iteration.Status == "Training") { Thread.Sleep(1000); iteration = api.GetIteration(project.Id, iteration.Id); } iteration.IsDefault = true; api.UpdateIteration(project.Id, iteration.Id, iteration); return(req.CreateResponse(HttpStatusCode.OK, iteration.Id)); } catch (Exception e) { var exception = e.GetBaseException(); return(req.CreateErrorResponse(HttpStatusCode.BadRequest, exception.Message)); } async Task <List <string> > SearchForImages(string term, int offset) { var client = new HttpClient(); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "c2adf0e5c057447ea9e0f50cc5202251"); var uri = $"https://api.cognitive.microsoft.com/bing/v7.0/images/search?count=50&q={term}&offset={offset}"; var json = await client.GetStringAsync(uri); var jobj = JObject.Parse(json); var arr = (JArray)jobj["value"]; var list = new List <string>(); foreach (var result in arr) { list.Add(result["contentUrl"].ToString()); } return(list); } }