diff --git a/Implementation/Common/ScreenshotScanner.cs b/Implementation/Common/ScreenshotScanner.cs
index cb05d27..a6f43a7 100644
--- a/Implementation/Common/ScreenshotScanner.cs
+++ b/Implementation/Common/ScreenshotScanner.cs
@@ -42,9 +42,4 @@ public class ScreenshotScanner
Lookup.Add(kv.Word, kv.Image);
}
}
-
- public virtual void Clear()
- {
- Lookup.Clear();
- }
}
\ No newline at end of file
diff --git a/Implementation/GUI/Views/ImageView.xaml b/Implementation/GUI/Views/ImageView.xaml
index 6fe2454..89b4cab 100644
--- a/Implementation/GUI/Views/ImageView.xaml
+++ b/Implementation/GUI/Views/ImageView.xaml
@@ -161,52 +161,6 @@
x:Name="EnableThreshold"
Content="Apply Threshold"
IsChecked="{Binding ProcessorConfig.EnableThresholding}" />
-
-
-
-
-
-
-
- Block Width:
-
-
-
-
-
-
-
-
-
-
-
- Block Height:
-
-
-
-
-
-
@@ -229,13 +183,6 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/Implementation/GUI/Views/ImageView.xaml.cs b/Implementation/GUI/Views/ImageView.xaml.cs
index 96a83cf..624b030 100644
--- a/Implementation/GUI/Views/ImageView.xaml.cs
+++ b/Implementation/GUI/Views/ImageView.xaml.cs
@@ -25,19 +25,6 @@ public partial class ImageView : Window
InitializeComponent();
}
- private void SldThreshold1_OnDragCompleted(object sender, DragCompletedEventArgs args)
- {
- var vm = ViewModel;
- vm.ProcessorConfig.ThresholdWidth = (int)Math.Round(((Slider)sender).Value);
- }
-
- private void SldThreshold2_OnDragCompleted(object sender, DragCompletedEventArgs args)
- {
- var vm = ViewModel;
- vm.ProcessorConfig.ThresholdHeight = (int)Math.Round(((Slider)sender).Value);
- }
-
-
private void SldBorder_OnDragCompleted(object sender, DragCompletedEventArgs e)
{
var vm = ViewModel;
diff --git a/Implementation/GUI/Views/ImageViewModel.cs b/Implementation/GUI/Views/ImageViewModel.cs
index e2909d1..91119cb 100644
--- a/Implementation/GUI/Views/ImageViewModel.cs
+++ b/Implementation/GUI/Views/ImageViewModel.cs
@@ -22,271 +22,277 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
+using Ocr.Tesseract.Extensions;
namespace Ocr.Gui.Views;
internal class ImageViewModel : INotifyPropertyChanged
{
- ///
- /// The internally used
- ///
- public ScreenshotScanner Scanner { get; private set; }
+ ///
+ /// Tesseract engine configuration
+ ///
+ public static readonly ITesseractConfiguration TesseractConfig =
+ new TesseractScreenshotConfiguration
+ {
+ DataPath = "tessdata",
+ Languages = new[] { "eng", "deu" }
+ };
- ///
- /// Tesseract engine configuration
- ///
- public static readonly ITesseractConfiguration TesseractConfig =
- new TesseractScreenshotConfiguration
- {
- DataPath = "tessdata",
- Languages = new[] { "eng", "deu" }
- };
+ public ScreenshotProcessorConfiguration ProcessorConfig { get; } = new();
- public ScreenshotProcessorConfiguration ProcessorConfig { get; } = new();
-
- ///
- /// expression for extracting whole words from scan results
- ///
- public static readonly Regex WordRegex = new(
- @"[\w'\-]{2,}",
- RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase
- );
-
- public ImageViewModel()
- {
- Scanner = new ScreenshotScanner(MakeProcessor());
- ProcessorConfig.PropertyChanged += (sender, args) => Task.Run(UpdateImage);
-
- OpenFileCommand = new Command(OpenFile);
- SaveEditedImageCommand = new Command(SaveEditedImage);
- }
-
- public ImageViewModel(MagickImage image) : this()
- {
- Image = image;
- }
-
- private IProcessorChain MakeProcessor()
- {
- var threshold =
- new ThresholdAdaptiveProcessor(
- ProcessorConfig.ThresholdWidth,
- ProcessorConfig.ThresholdHeight
- );
-
- var preprocessing = new ProcessorChainConfiguration()
- .Use(new CloneImageProcessor())
- .Use(new ResizeProcessor(FilterType.Lanczos2Sharp, PixelInterpolateMethod.Mesh))
- .Use(new NormalizeProcessor())
- .Use(threshold)
- .Use(new AddBorderProcessor(ProcessorConfig.Border))
- .Use(new BinarizeProcessor())
- .Complete(new NegateCloneProcessor());
-
- var postprocessing = new ProcessorChainConfiguration()
- .Use(new ConfidenceFilter(50))
- .Use(new ToLowerProcessor())
- .Use(new DuplicateFilter())
- .Complete(new RegexFilter(WordRegex));
-
- var scan = new TesseractProcessor(TesseractConfig);
-
- return new ProcessorChainConfiguration()
- .Use(preprocessing)
- .Use(new ProcessingEvent(OnProcessing))
- .Use(scan)
- .Use(new ProcessingEvent(OnProcessed))
- .Complete(postprocessing);
- }
-
- #region Overrides of Scanner
-
- ///
- protected void OnProcessing(IProcessor sender, ICollection inputs)
- {
- Application.Current.Dispatcher.Invoke(() =>
- {
- foreach (var image in inputs)
- {
- Edited.Add(image);
- }
- });
- }
-
- ///
- protected void OnProcessed(IProcessor sender, ICollection inputs)
- {
- ScannedText = $"[{inputs.Count} words] " + string.Join(' ', inputs);
- }
-
- ///
- public void Clear()
- {
- Scanner.Clear();
- Application.Current.Dispatcher.Invoke(() =>
- {
- ScannedText = string.Empty;
- Words.Clear();
- Edited.Clear();
- }
+ ///
+ /// expression for extracting whole words from scan results
+ ///
+ public static readonly Regex WordRegex = new(
+ @"[\w'\-]{2,}",
+ RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase
);
- }
- #endregion
-
- #region File Handling
-
- private void OpenFile()
- {
- var dialog = new OpenFileDialog()
+ public ImageViewModel()
{
- InitialDirectory = Directory.GetCurrentDirectory()
- };
- if (dialog.ShowDialog() == true)
- {
- Image = new MagickImage(dialog.FileName);
- UpdateImage();
- }
- }
+ ProcessorConfig.PropertyChanged += (sender, args) => Task.Run(UpdateImage);
- private void SaveEditedImage()
- {
- var basePath = AppDomain.CurrentDomain.BaseDirectory;
-
- for (var i = 0; i < Edited.Count; i++)
- {
- Edited[i].Write(Path.Combine(basePath, $"edited_{i}.png"));
+ OpenFileCommand = new Command(OpenFile);
+ SaveEditedImageCommand = new Command(SaveEditedImage);
}
- Log.Information($"Saved image to '{basePath}'");
- System.Diagnostics.Process.Start(
- "explorer.exe",
- Path.GetDirectoryName(basePath) ?? string.Empty
- );
- }
-
- #endregion
-
- #region Updating data
-
- private void UpdateConfidence()
- {
- Confidence = Scanner.Lookup.Keys.Any()
- ? Scanner.Lookup.Keys.Sum(key => key.Confidence) / Scanner.Lookup.Keys.Count
- : 0;
- }
-
- private void UpdateImage()
- {
- Task.Run(() =>
+ public ImageViewModel(MagickImage image) : this()
{
- IsIdle = false;
-
- Clear();
- if (Image != null)
- {
- Scanner.Process(new[] { Image });
- }
-
- UpdateWords();
- UpdateConfidence();
-
- IsIdle = true;
- });
- }
-
- private void UpdateWords()
- {
- Application.Current.Dispatcher.Invoke(() =>
- {
- foreach (var word in Scanner.Lookup.Keys)
- {
- Words.Add(word);
- }
- });
- }
-
- #endregion
-
- #region Properties
-
- private float _confidence;
- private MagickImage? _image;
- private bool _isIdle;
-
- private string _scannedText = string.Empty;
-
- public string ScannedText
- {
- get => _scannedText;
- set
- {
- if (value == _scannedText)
- {
- return;
- }
-
- _scannedText = value;
- OnPropertyChanged();
+ Image = image;
}
- }
- public bool IsIdle
- {
- get => _isIdle;
- set
+ private IProcessorChain MakeProcessor()
{
- if (value == _isIdle)
- {
- return;
- }
+ var threshold =
+ new ThresholdAdaptiveProcessor(
+ ProcessorConfig.ThresholdWidth,
+ ProcessorConfig.ThresholdHeight
+ );
- _isIdle = value;
- OnPropertyChanged();
+ var chainConfig = new ProcessorChainConfiguration()
+ .Use(new CloneImageProcessor());
+
+ if (ProcessorConfig.EnableResizing)
+ {
+ chainConfig
+ .Use(new ResizeProcessor(FilterType.Lanczos2Sharp, PixelInterpolateMethod.Mesh))
+ .Use(new ProcessingEvent(OnProcessing));
+ }
+
+ chainConfig = chainConfig
+ .Use(new NormalizeProcessor())
+ .Use(new ProcessingEvent(OnProcessing));
+
+ if (ProcessorConfig.EnableThresholding)
+ {
+ chainConfig = chainConfig
+ .Use(threshold)
+ .Use(new ProcessingEvent(OnProcessing));
+ }
+
+ var preprocessing = chainConfig
+ .Use(new AddBorderProcessor(ProcessorConfig.Border))
+ .Use(new BinarizeProcessor())
+ .Use(new ProcessingEvent(OnProcessing))
+ .Complete(new NegateCloneProcessor());
+
+ var postprocessing = new ProcessorChainConfiguration()
+ .Use(new ConfidenceFilter(50))
+ .Use(new ToLowerProcessor())
+ .Use(new DuplicateFilter())
+ .Complete(new RegexFilter(WordRegex));
+
+ var scan = new TesseractProcessor(TesseractConfig);
+
+ return new ProcessorChainConfiguration()
+ .Use(preprocessing)
+ .Use(scan)
+ .Use(new ProcessingEvent(OnProcessed))
+ .Complete(postprocessing);
}
- }
- public float Confidence
- {
- get => _confidence;
- set
+ #region Overrides of Scanner
+
+ ///
+ protected void OnProcessing(IProcessor sender, ICollection inputs)
{
- _confidence = value;
- OnPropertyChanged();
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ foreach (var image in inputs)
+ {
+ Edited.Add(image.CloneImage());
+ }
+ });
}
- }
- public ObservableCollection Edited { get; } = new();
-
- public MagickImage? Image
- {
- get => _image;
- set
+ ///
+ protected void OnProcessed(IProcessor sender, ICollection inputs)
{
- _image = value;
- OnPropertyChanged();
+ var wordStr = string.Join("\", \"", inputs);
+ ScannedText = $"{inputs.Count} words:{Environment.NewLine}[ \"{wordStr}\" ]";
}
- }
- public ObservableCollection Words { get; } = new();
+ ///
+ public void Clear()
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ ScannedText = string.Empty;
+ Words.Clear();
+ Edited.Clear();
+ }
+ );
+ }
- #endregion Properties
+ #endregion
- #region Commands
+ #region File Handling
- public ICommand OpenFileCommand { get; private set; }
- public ICommand SaveEditedImageCommand { get; private set; }
+ private void OpenFile()
+ {
+ var dialog = new OpenFileDialog()
+ {
+ InitialDirectory = Directory.GetCurrentDirectory()
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ Image = new MagickImage(dialog.FileName);
+ UpdateImage();
+ }
+ }
- #endregion Commands
+ private void SaveEditedImage()
+ {
+ var basePath = AppDomain.CurrentDomain.BaseDirectory;
- #region INotifyPropertyChanged
+ for (var i = 0; i < Edited.Count; i++)
+ {
+ Edited[i].Write(Path.Combine(basePath, $"edited_{i}.png"));
+ }
- public event PropertyChangedEventHandler? PropertyChanged;
+ Log.Information($"Saved image to '{basePath}'");
+ System.Diagnostics.Process.Start(
+ "explorer.exe",
+ Path.GetDirectoryName(basePath) ?? string.Empty
+ );
+ }
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
+ #endregion
- #endregion INotifyPropertyChanged
-}
+ #region Updating data
+
+ private void UpdateImage()
+ {
+ Task.Run(() =>
+ {
+ IsIdle = false;
+ var scanner = new ScreenshotScanner(MakeProcessor());
+
+ Clear();
+
+ if (Image != null)
+ {
+ scanner.Process(new[] { Image });
+ }
+
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ var confidence = 0f;
+ foreach (var word in scanner.Lookup.Keys)
+ {
+ confidence += word.Confidence;
+ Words.Add(word);
+ }
+
+ Confidence = confidence / scanner.Lookup.Keys.Count;
+ }
+ );
+
+ IsIdle = true;
+ });
+ }
+
+ #endregion
+
+ #region Properties
+
+ private float _confidence;
+ private MagickImage? _image;
+ private bool _isIdle;
+
+ private string _scannedText = string.Empty;
+
+ public string ScannedText
+ {
+ get => _scannedText;
+ set
+ {
+ if (value == _scannedText)
+ {
+ return;
+ }
+
+ _scannedText = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool IsIdle
+ {
+ get => _isIdle;
+ set
+ {
+ if (value == _isIdle)
+ {
+ return;
+ }
+
+ _isIdle = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public float Confidence
+ {
+ get => _confidence;
+ set
+ {
+ _confidence = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ObservableCollection Edited { get; } = new();
+
+ public MagickImage? Image
+ {
+ get => _image;
+ set
+ {
+ _image = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ObservableCollection Words { get; } = new();
+
+ #endregion Properties
+
+ #region Commands
+
+ public ICommand OpenFileCommand { get; private set; }
+ public ICommand SaveEditedImageCommand { get; private set; }
+
+ #endregion Commands
+
+ #region INotifyPropertyChanged
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ #endregion INotifyPropertyChanged
+}
\ No newline at end of file