using ImageMagick; using Ocr.Tesseract; using Ocr.Tesseract.Configuration; using Ocr.Tesseract.Extensions; using Ocr.Tesseract.Models; using Ocr.Tesseract.Screenshots; using Ocr.Tesseract.Screenshots.Configuration; using Process.Abstract.Configuration; using Process.Interface; using System.Text.Json; using System.Text.RegularExpressions; namespace CLI.Processor; internal class EvaluationProcessor { #region Configuration /// /// expression for extracting whole words from scan results /// private static readonly Regex wordRegex = new( @"[\w'\-]{2,}", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase ); private static readonly ITesseractConfiguration tesseractConfig = new TesseractScreenshotConfiguration { DataPath = "tessdata", Languages = new[] { "eng", "deu" } }; #endregion #region Processors private static readonly IProcessorChain postProcessor = new ProcessorChainConfiguration() .Use(new ConfidenceFilter(50)) .Use(new ToLowerProcessor()) .Use(new DuplicateFilter()) .Complete(new RegexFilter(wordRegex)); private static readonly TesseractProcessor tesseractProcessor = new(tesseractConfig); private readonly StopwatchProcessor _thresholdProcessor; #endregion public string OutputFolder { get; init; } = "results"; public EvaluationProcessor( IProcessor thresholdProcessor ) => _thresholdProcessor = new StopwatchProcessor(thresholdProcessor); /// public Task Process(MagickImage image) => Task.Run(async () => { var words = MakeProcessor() .Process(new[] { image }) .Select(r => r.Word) .ToArray(); var result = new { Words = words.ToArray(), Elapsed = _thresholdProcessor.Elapsed?.TotalMilliseconds, }; var name = Path.GetFileNameWithoutExtension(image.FileName); var path = Path.Combine(OutputFolder, $"{name}.{_thresholdProcessor}.json"); await using var file = File.OpenWrite(path); await JsonSerializer.SerializeAsync(file, result); }); private IProcessorChain MakeProcessor() { var preprocessing = new ProcessorChainConfiguration() .Use(new CloneImageProcessor()) .Use(new ResizeProcessor(FilterType.Lanczos2Sharp, PixelInterpolateMethod.Mesh)) .Use(new NormalizeProcessor()) .Use(_thresholdProcessor) .Use(new AddBorderProcessor(10)) .Use(new BinarizeProcessor()) .Use(new NegateCloneProcessor()) .Complete(OnPreprocessed); return new ProcessorChainConfiguration() .Use(preprocessing) .Use(tesseractProcessor) .Complete(postProcessor); } private IEnumerable OnPreprocessed(IEnumerable images) { var tImages = images.ToArray(); for (var i = 0; i < tImages.Length; i++) { var image = tImages[i].CloneImage(); var name = Path.GetFileName(image.FileName); var path = Path.Combine(OutputFolder, $"{_thresholdProcessor}.{i:D2}.{name}"); image.Write(path); } return tImages; } }