check point
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\framework\Inspectron.Fastbuffer\Inspectron.Fastbuffer.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Common\VisionBuilder.UI.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
127
VisionBuilder.UI.Ringbuffer/VisionBuilderRingbuffer.cs
Normal file
127
VisionBuilder.UI.Ringbuffer/VisionBuilderRingbuffer.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using Inspectron.Fastbuffer;
|
||||
using Inspectron.Fastbuffer.Filesystems;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenCvSharp;
|
||||
using VisionBuilder.UI.Common.Commands;
|
||||
using VisionBuilder.UI.Common.RecipeProcessing;
|
||||
|
||||
namespace Lindt.Colorballs.Duo.Utils;
|
||||
|
||||
public class VisionBuilderRingbuffer
|
||||
{
|
||||
private readonly VisionBuilderRingbufferSettings _settings;
|
||||
private readonly IRecognitionControl _recognitionControl;
|
||||
|
||||
public VisionBuilderRingbuffer(VisionBuilderRingbufferSettings settings, IRecognitionControl recognitionControl)
|
||||
{
|
||||
_settings = settings;
|
||||
_recognitionControl = recognitionControl;
|
||||
_recognitionControl.SessionStarted += _recognitionControl_SessionStarted;
|
||||
_recognitionControl.ImageProcessed += _recognitionControl_ImageProcessed;
|
||||
}
|
||||
|
||||
private void _recognitionControl_ImageProcessed(VisionBuilder.UI.Common.Commands.ImageProcessedEvent obj)
|
||||
{
|
||||
if (obj.HasError)
|
||||
{
|
||||
WriteBadResult(obj);
|
||||
return;
|
||||
}
|
||||
WriteGoodResult(obj);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
// save to memory stream
|
||||
_goodRingbufferIsolated.Write(image.ToBytes(), filename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Error writing good result at {filename}: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, IsolatedRingbuffer> _badRingbuffers = new Dictionary<string, IsolatedRingbuffer>();
|
||||
|
||||
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.ToBytes(), 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?.Dispose();
|
||||
_goodRingbufferIsolated = new IsolatedRingbuffer(_path, _settings.MaxGood, new AsyncFilesystem());
|
||||
|
||||
foreach (var ringbuffer in _badRingbuffers)
|
||||
{
|
||||
ringbuffer.Value.Dispose();
|
||||
}
|
||||
|
||||
_badRingbuffers.Clear();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using Inspectron.Settings;
|
||||
using Inspectron.Settings.Attributes;
|
||||
using System.ComponentModel;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using VisionBuilder.UI.Common;
|
||||
|
||||
namespace Lindt.Colorballs.Duo.Utils;
|
||||
|
||||
public class VisionBuilderRingbufferSettings : ISettings
|
||||
{
|
||||
|
||||
public VisionBuilderRingbufferSettings(string cameraName)
|
||||
{
|
||||
CameraName = cameraName;
|
||||
}
|
||||
|
||||
public string CameraName { get; }
|
||||
|
||||
public int MaxBad { get; set; } = 10000;
|
||||
public int MaxGood { get; set; } = 100;
|
||||
|
||||
|
||||
[SettingDescription(
|
||||
@"
|
||||
Specifies directory, in which MaxBad and MaxGood are applied.
|
||||
You can use the following system variables:
|
||||
|
||||
$RECIPE_NAME - name of the current recipe
|
||||
$DEFECT_NAME - name of the current defect(for bad images)
|
||||
$CAMERA_NAME - name of the camera
|
||||
|
||||
$HOUR - hour of the image
|
||||
$MINUTE - minute of the image
|
||||
$SECOND - second of the image
|
||||
$MS - milliseconds of the image
|
||||
|
||||
$DAY - day of the image
|
||||
$MONTH - month of the image
|
||||
$YEAR - year of the image
|
||||
|
||||
$SS_HOUR - hour of the session start
|
||||
$SS_MINUTE - minute of the session start
|
||||
$SS_SECOND - second of the session start
|
||||
|
||||
$SS_DAY - day of the session start
|
||||
$SS_MONTH - month of the session start
|
||||
$SS_YEAR - year of the session start
|
||||
|
||||
"
|
||||
)]
|
||||
[SettingPreview(typeof(VisionBuilderRingbufferSettings), nameof(ImagesPathTemplatePreview))]
|
||||
public string Root { get; set; } = @"..\Data\Ringbuffer\$SS_MONTH $SS_YEAR";
|
||||
|
||||
|
||||
|
||||
[SettingDescriptionAttribute("Specifies directory, relative to the Root")]
|
||||
[SettingPreview(typeof(VisionBuilderRingbufferSettings), nameof(ImagesPathTemplatePreview))]
|
||||
public string GoodImagesPathTemplate { get; set; } = @"\$RECIPE_NAME";
|
||||
|
||||
[SettingDescriptionAttribute("Specifies directory, relative to the Root")]
|
||||
[SettingPreview(typeof(VisionBuilderRingbufferSettings),nameof(ImagesPathTemplatePreview))]
|
||||
public string BadImagesPathTemplate { get; set; } =
|
||||
@"\$RECIPE_NAME\$DEFECT_NAME";
|
||||
|
||||
|
||||
[SettingPreview(typeof(VisionBuilderRingbufferSettings), nameof(ImagesPathTemplatePreview))]
|
||||
public string FilenameTemplate { get; set; } = "$YEAR-$MONTH-$DAY $HOUR-$MINUTE-$SECOND $MS";
|
||||
|
||||
|
||||
public void RegisterSettings(InspectronSettings settings)
|
||||
{
|
||||
settings.RegisterSimple(this, () => this.MaxGood, CameraName+"/Ringbuffer", nameof(MaxGood));
|
||||
settings.RegisterSimple(this, () => this.MaxBad, CameraName + "/Ringbuffer", nameof(MaxBad));
|
||||
settings.RegisterSimple(this, () => this.Root, CameraName + "/Ringbuffer", nameof(Root));
|
||||
settings.RegisterSimple(this, () => this.GoodImagesPathTemplate, CameraName + "/Ringbuffer", nameof(GoodImagesPathTemplate));
|
||||
settings.RegisterSimple(this, () => this.BadImagesPathTemplate, CameraName + "/Ringbuffer", nameof(BadImagesPathTemplate));
|
||||
settings.RegisterSimple(this, () => this.FilenameTemplate, CameraName + "/Ringbuffer", nameof(FilenameTemplate));
|
||||
}
|
||||
|
||||
public static string ImagesPathTemplatePreview(object template)
|
||||
{
|
||||
return PathSettingsUtils.ConvertVariables((string) template, DateTime.Now, DateTime.Now, "my recipe",
|
||||
"my defect", "my camera");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user