using Inspectron.Fastbuffer; using Inspectron.Fastbuffer.Filesystems; using Lindt.Colorballs.Duo.Utils; using OpenCvSharp; using Serilog; using VisionBuilder.UI.Common; using VisionBuilder.UI.Common.Commands; using VisionBuilder.UI.Common.Processing; namespace VisionBuilder.UI.Ringbuffer; public class VisionBuilderRingbuffer:IVisionBuilderModule { private readonly VisionBuilderRingbufferSettings _settings; private readonly IRecognitionControl _recognitionControl; private readonly ILoadingService _loadingService; public VisionBuilderRingbuffer(VisionBuilderRingbufferSettings settings, IRecognitionControl recognitionControl, ILoadingService loadingService) { _settings = settings; _recognitionControl = recognitionControl; _loadingService = loadingService; } public void InitializeModule() { _recognitionControl.SessionStarted += _recognitionControl_SessionStarted; _recognitionControl.SessionEnded += _recognitionControl_SessionEnded; _recognitionControl.ImageProcessed += _recognitionControl_ImageProcessed; } private void _recognitionControl_SessionEnded(SessionEndedEvent obj) { _loadingService.StartLoading("Processing ringbuffer"); Log.Information("Processing ringbuffer"); try { CleanUp(); } catch (Exception e) { } finally { Log.Information("Finished processing ringbuffer"); _loadingService.StopLoading("Processing ringbuffer"); } } private void _recognitionControl_ImageProcessed(VisionBuilder.UI.Common.Commands.ImageProcessedEvent obj) { var sw = System.Diagnostics.Stopwatch.StartNew(); try { if (obj.HasError) { WriteBadResult(obj); return; } WriteGoodResult(obj); } finally { sw.Stop(); Console.WriteLine($"Ringbuffer: wrote image in {sw.ElapsedMilliseconds}ms"); } } private void _recognitionControl_SessionStarted(VisionBuilder.UI.Common.Commands.SessionStartedEvent obj) { NewProduct(obj.RecipeName); } private IsolatedRingbuffer _goodRingbufferIsolated; private string _path; private DateTime _startTime; private string _product; private void CleanUp() { _goodRingbufferIsolated?.Dispose(); foreach (var ringbuffer in _badRingbuffers) { ringbuffer.Value.Dispose(); } _badRingbuffers.Clear(); } public void Dispose() { CleanUp(); } public void WriteGoodResult(ImageProcessedEvent result) { if (result.ImageOriginal == null) return; var filename = PathSettingsUtils.ConvertVariables(_settings.FilenameTemplate, DateTime.Now, _startTime, _product,cameraName: _settings.CameraName) + ".png"; try { var image = result.ImageOriginal; _goodRingbufferIsolated.Write(image, filename); } catch (Exception e) { Console.WriteLine($"Error writing good result at {filename}: " + e.Message); } } Dictionary _badRingbuffers = new Dictionary(); private IsolatedRingbuffer GetBadRingbuffer(string defectName) { if (_badRingbuffers.ContainsKey(defectName)) { return _badRingbuffers[defectName]; } var path = PathSettingsUtils.ConvertVariables(Path.Combine(_settings.Root, _settings.BadImagesPathTemplate), _startTime, _startTime, _product, cameraName: _settings.CameraName); var ringbuffer = new IsolatedRingbuffer(path, _settings.MaxBad, new AsyncFilesystem()); _badRingbuffers[defectName] = ringbuffer; return ringbuffer; } private void SaveResultImage(Mat image, string defectName, DateTime time, bool isAnalysis) { var filename = PathSettingsUtils.ConvertVariables(_settings.FilenameTemplate,time,_startTime,_product,defectName,_settings.CameraName) + (isAnalysis ? "_analysis" : "") + ".png"; var ringbuffer = GetBadRingbuffer(defectName); try { ringbuffer.Write(image, filename); } catch (Exception e) { Console.WriteLine($"Error writing bad result for {filename}: " + e.Message); } } public void WriteBadResult(ImageProcessedEvent result) { var defectName = "unknown"; if (result.ErrorNames.Any()) { defectName = result.ErrorNames.First(); } var time = DateTime.Now; SaveResultImage(result.ImageOriginal, defectName, time, false); SaveResultImage(result.ImageAnalysis, defectName, time, true); } public void NewProduct(string product) { _startTime = DateTime.Now; _product = product; _path = PathSettingsUtils.ConvertVariables(Path.Combine(_settings.Root,_settings.GoodImagesPathTemplate), _startTime, _startTime, _product,cameraName:_settings.CameraName); _goodRingbufferIsolated = new IsolatedRingbuffer(_path, _settings.MaxGood, new AsyncFilesystem()); } }