/// this method labels or unlables an image public void LabelImage(string label) { // case : removing tag from tagged image if (Images[CurrentIndex].isTagged && Images[CurrentIndex].Tag == label) { Images[CurrentIndex].isTagged = false; Images[CurrentIndex].Tag = string.Empty; TaggedImages.Remove(Images[CurrentIndex]); CurrentTaggedCount = TaggedImages.Count; CurrentProgress = (int)(((float)TaggedImages.Count / Images.Count) * 100); PerTagCount[label]--; } // case : change tag of tagged image else if (Images[CurrentIndex].isTagged) { PerTagCount[Images[CurrentIndex].Tag]--; Images[CurrentIndex].Tag = label; PerTagCount[label]++; } // case : tag untagged image else { Images[CurrentIndex].isTagged = true; Images[CurrentIndex].Tag = label; TaggedImages.Add(Images[CurrentIndex]); CurrentTaggedCount = TaggedImages.Count; CurrentProgress = (int)(((float)TaggedImages.Count / Images.Count) * 100); PerTagCount[label]++; } // wanted to call these from mainWindow but doesn't update immediately there don't know why.... _mainWindow.CheckButtonStatus(); _mainWindow.updateCountText(); }
/// Main view model, which takes width and height of screen to set limits to image size public MainWindowViewModel(int width, int height, MainWindow window) { // get ref of main window _mainWindow = window; // get cancellation token token = tokenSource.Token; // get all the image files and fill the different lists foreach (var file in Directory.EnumerateFiles(ImageLabeling.input_path) .Where(x => ImageLabeling.extensions.Any(ext => ext == Path.GetExtension(x).ToLower())).OrderBy(x => x)) { Files.Add(file); FileNames.Add(Path.GetFileName(file)); Images.Add(new ImageLabel() { Filename = Path.GetFileName(file), Filepath = file, Image = new Image() { Source = new Bitmap(file), MaxWidth = width * 0.9, MaxHeight = height * 0.9, Stretch = Avalonia.Media.Stretch.Uniform }, isTagged = false, Tag = String.Empty }); } // init the currentX properties and per tag count CurrentIndex = 0; CurrentProgress = 0; CurrentFileName = FileNames[CurrentIndex]; foreach (var clas in ImageLabeling.classes) { PerTagCount[clas] = 0; } // if resuming, read csv, get class names and tagged images if (ImageLabeling.isResuming) { string line; // we already checked that the file exists and contains a valid header in startButton handler using (System.IO.StreamReader file = new System.IO.StreamReader(Path.Combine(ImageLabeling.output_path, ImageLabeling.csv_name))) { // loop through the lines to read the records if there are while ((line = file.ReadLine()) != null) { var splits = line.Split(","); // this is header, skip it if (splits[0] == "Filepath") { continue; } var image = Images.Where(x => x.Filepath == splits[0]).First(); image.isTagged = true; for (int i = 1; i < splits.Length; i++) { if (splits[i] == "1") { image.Tag = ImageLabeling.classes[i - 1]; } } TaggedImages.Add(image); PerTagCount[image.Tag]++; } } CurrentTaggedCount = TaggedImages.Count; // update the current index to be that of the first untagged image for (int i = 0; i < Files.Count; i++) { if (!TaggedImages.Select(x => x.Filepath).Contains(Files[i])) { break; } else { CurrentIndex++; } } // if all images are tagged, set index to first image if (CurrentIndex == Files.Count) { CurrentIndex = 0; } CurrentFileName = FileNames[CurrentIndex]; CurrentProgress = (int)(((float)TaggedImages.Count / Images.Count) * 100); // delete all the copied images foreach (var directory in Directory.EnumerateDirectories(ImageLabeling.output_path)) { foreach (var file in Directory.EnumerateFiles(directory)) { File.Delete(file); } } } // create the folders else { Directory.CreateDirectory(ImageLabeling.output_path); foreach (var clas in ImageLabeling.classes) { Directory.CreateDirectory(Path.Combine(ImageLabeling.output_path, clas)); } } // start new thread for automatic CSV writing every minute Task.Run(() => WriteCSV(), token); }