162 lines
4.4 KiB
C#
162 lines
4.4 KiB
C#
using System.Diagnostics;
|
|
using Hawkeye.VisionBuilder.Workflow.Datatypes;
|
|
using Hawkeye.VisionBuilder.Workflow.Operations.Attributes;
|
|
using static IronPython.Runtime.Profiler;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using Compunet.YoloV8;
|
|
using Compunet.YoloV8.Data;
|
|
using OpenCvSharp;
|
|
using SixLabors.ImageSharp.PixelFormats;
|
|
using SixLabors.ImageSharp;
|
|
using SixLabors.ImageSharp.Processing;
|
|
|
|
namespace Hawkeye.VisionBuilder.Workflow.Operations.AI;
|
|
[Category("AI")]
|
|
public class YoloDetectionOperation:BaseOperation
|
|
{
|
|
|
|
private bool _initialized = false;
|
|
private FilePath _modelFilePath = new FilePath(){ Format = "Onnx format(*.onnx)|*.onnx" };
|
|
|
|
|
|
public int IgnoreType { get; set; } = -1;
|
|
|
|
public FilePath ModelFilePath
|
|
{
|
|
get => _modelFilePath;
|
|
set
|
|
{
|
|
_modelFilePath = value;
|
|
_initialized = false;
|
|
}
|
|
}
|
|
|
|
bool EnsureInitialized()
|
|
{
|
|
if (!_initialized)
|
|
{
|
|
if (!File.Exists(ModelFilePath?.Path))
|
|
{
|
|
this.SetError("Model file not found");
|
|
return false;
|
|
}
|
|
_predictor = YoloV8Predictor.Create(ModelFilePath?.Path);
|
|
|
|
_predictor.Configuration.SuppressParallelInference=true;
|
|
_initialized = true;
|
|
}
|
|
return true;
|
|
}
|
|
byte[] _buffer=new byte[0];
|
|
private YoloV8Predictor _predictor;
|
|
|
|
|
|
void EnsureBuffer(int size)
|
|
{
|
|
if (_buffer.Length != size)
|
|
{
|
|
_buffer = new byte[size];
|
|
}
|
|
}
|
|
protected override void InterpretInternal(Context context)
|
|
{
|
|
CheckImageExists(context);
|
|
CheckColorful(context);
|
|
try
|
|
{
|
|
if (!EnsureInitialized()) return;
|
|
var swImagePreparation = Stopwatch.StartNew();
|
|
|
|
var image = context.ActiveImage.ImageData.CvtColor(ColorConversionCodes.BGR2RGB);
|
|
EnsureBuffer(image.Cols * image.Rows * image.Channels());
|
|
Marshal.Copy(image.Data, _buffer, 0, _buffer.Length);
|
|
Image<Rgb24> img = SixLabors.ImageSharp.Image.LoadPixelData<Rgb24>(_buffer, image.Width, image.Height);
|
|
// convert to rgb24
|
|
|
|
|
|
swImagePreparation.Stop();
|
|
|
|
var swPrediction = Stopwatch.StartNew();
|
|
|
|
|
|
|
|
var result = _predictor.Detect(img);
|
|
|
|
|
|
|
|
swPrediction.Stop();
|
|
|
|
|
|
var swPostProcessing = Stopwatch.StartNew();
|
|
Mat res = new Mat(image.Size(), MatType.CV_8UC1, new Scalar(0));
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
Dictionary<int, string> classes = new Dictionary<int, string>();
|
|
|
|
|
|
|
|
foreach (BoundingBox box in result.Boxes.OrderBy(x=>x.Class.Id).ToList())
|
|
{
|
|
if (box.Confidence<0.7)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (box.Class.Id + 1 == IgnoreType)
|
|
{
|
|
continue;
|
|
}
|
|
classes[box.Class.Id + 1] = box.Class.Name;
|
|
var rect = box.Bounds;
|
|
res.Rectangle(new OpenCvSharp.Rect(rect.Left, rect.Top, rect.Width, rect.Height),
|
|
new Scalar(box.Class.Id + 1), -1);
|
|
}
|
|
swPostProcessing.Stop();
|
|
|
|
|
|
foreach (var c in classes)
|
|
{
|
|
sb.AppendLine($"{c.Key}={c.Value};");
|
|
}
|
|
|
|
Status = sb.ToString();
|
|
|
|
context.ActiveImage = new HawkeyeImage() {ImageData = res};
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public override void Save(BinaryWriter bw)
|
|
{
|
|
base.Save(bw);
|
|
bw.Write(ModelFilePath.Path);
|
|
}
|
|
|
|
public override void Load(BinaryReader br)
|
|
{
|
|
base.Load(br);
|
|
ModelFilePath.Path = br.ReadString();
|
|
}
|
|
|
|
public override void Save(Dictionary<string, object> dict)
|
|
{
|
|
base.Save(dict);
|
|
dict[nameof(ModelFilePath)] = ModelFilePath.Path;
|
|
dict[nameof(IgnoreType)] = IgnoreType;
|
|
}
|
|
|
|
public override void Load(Dictionary<string, object> dict)
|
|
{
|
|
base.Load(dict);
|
|
if (dict.ContainsKey(nameof(ModelFilePath)))
|
|
ModelFilePath.Path = dict[nameof(ModelFilePath)].ToString();
|
|
|
|
if (dict.ContainsKey(nameof(IgnoreType)))
|
|
IgnoreType = Convert.ToInt32(dict[nameof(IgnoreType)]);
|
|
}
|
|
} |