hawkeye camera support(not tested)
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.HawkEye\Inspectron.HawkEye.csproj" />
|
||||
<ProjectReference Include="..\VisionBuilder.UI.Common\VisionBuilder.UI.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,133 @@
|
||||
using Inspectron.HawkEye.Protocol;
|
||||
using OpenCvSharp;
|
||||
using Serilog;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using VisionBuilder.UI.Common;
|
||||
using VisionBuilder.UI.Common.RecipeProcessing;
|
||||
using CameraSettings = Inspectron.HawkEye.Protocol.CameraSettings;
|
||||
|
||||
namespace Hawkeye.VisionBuilder.UI.Sources.Hawkeye
|
||||
{
|
||||
public class HawkeyeCameraImageSource : IImageSource, IVisionBuilderModule
|
||||
{
|
||||
private readonly HawkeyeSettings _settings;
|
||||
private ImageClientTCP _client;
|
||||
private CameraSettings _cameraSettings;
|
||||
|
||||
|
||||
public HawkeyeCameraImageSource(HawkeyeSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
|
||||
_client = new ImageClientTCP(new IPEndPoint(IPAddress.Parse("192.168.3.15"), 27001),
|
||||
IPAddress.Parse(_settings.Adapter));
|
||||
_client.ImageReceived += _client_ImageReceived;
|
||||
_client.SettingsReceived += _client_SettingsReceived;
|
||||
_client.Connect();
|
||||
Log.Information("Connected to Hawkeye camera at {Adapter}", _settings.Adapter, 27001);
|
||||
|
||||
}
|
||||
private void _client_SettingsReceived(CameraSettings obj)
|
||||
{
|
||||
ApplySettings(obj);
|
||||
}
|
||||
public void ApplySettings(CameraSettings obj)
|
||||
{
|
||||
_cameraSettings = UICameraSettings.LoadSettingsLocal(_settings.SettingsFile).ToCameraSettings();
|
||||
_client.ApplySettings(_cameraSettings);
|
||||
}
|
||||
|
||||
public Task<Mat> GetImage(CancellationToken token)
|
||||
{
|
||||
|
||||
_lastImage = null;
|
||||
if (_imageAquisitionTaskSource != null && !_imageAquisitionTaskSource.Task.IsCanceled)
|
||||
{
|
||||
_imageAquisitionTaskSource.SetCanceled(CancellationToken.None);
|
||||
_imageAquisitionTaskSource = null;
|
||||
|
||||
}
|
||||
_imageAquisitionTaskSource= new TaskCompletionSource<Mat>();
|
||||
_client.Trigger();
|
||||
return _imageAquisitionTaskSource.Task;
|
||||
|
||||
}
|
||||
|
||||
private TaskCompletionSource<Mat>? _imageAquisitionTaskSource;
|
||||
private Mat _lastImage;
|
||||
byte[] _flipBuffer = new byte[2000 * 2000];
|
||||
private void _client_ImageReceived(byte[] obj)
|
||||
{
|
||||
Log.Debug("Got image on {adapter}", _settings.Adapter);
|
||||
FlipLines(obj, _flipBuffer);
|
||||
obj = _flipBuffer;
|
||||
var pinnedArray = GCHandle.Alloc(obj, GCHandleType.Pinned);
|
||||
var pointer = pinnedArray.AddrOfPinnedObject();
|
||||
|
||||
Mat image = new Mat(_cameraSettings.ImageSettings.Lines, _cameraSettings.ImageSettings.SensorWidth,
|
||||
MatType.CV_8UC1, pointer);
|
||||
|
||||
var xCrop = _cameraSettings.ImageSettings.SensorWidth - _cameraSettings.ImageWidth - _cameraSettings.OffsetX;
|
||||
|
||||
// crop the image with opencv
|
||||
_lastImage = image[0, _cameraSettings.ImageSettings.Lines, xCrop,
|
||||
xCrop + _cameraSettings.ImageWidth].Clone();
|
||||
|
||||
if (_cameraSettings.BayerFilter)
|
||||
{
|
||||
_lastImage = BayerFilter(_lastImage);
|
||||
}
|
||||
|
||||
_imageAquisitionTaskSource!.SetResult(_lastImage);
|
||||
|
||||
pinnedArray.Free();
|
||||
}
|
||||
|
||||
Mat BayerFilter(Mat image)
|
||||
{
|
||||
// Assumes input is a single-channel Bayer pattern image (CV_8UC1)
|
||||
// Output is a 3-channel BGR image (CV_8UC3)
|
||||
if (image == null || image.Empty())
|
||||
throw new ArgumentException("Input image is null or empty.", nameof(image));
|
||||
|
||||
Mat bgrImage = new Mat();
|
||||
// Use OpenCV's demosaicing function for Bayer BG pattern
|
||||
Cv2.CvtColor(image, bgrImage, ColorConversionCodes.BayerBG2BGR);
|
||||
|
||||
return bgrImage;
|
||||
}
|
||||
|
||||
protected void FlipLines(byte[] src, byte[] dst)
|
||||
{
|
||||
int srcStride = _cameraSettings.ImageSettings.SensorWidth;
|
||||
int dstStride = _cameraSettings.ImageSettings.SensorWidth;
|
||||
int pixelSize = 1;
|
||||
int copySize = srcStride * pixelSize;
|
||||
var lines = _cameraSettings.ImageSettings.Lines;
|
||||
for (int line = 0; line < lines; line += 4)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int srcPos = (line + i) * srcStride;
|
||||
int dstPos = (line + (4 - i)) * dstStride;
|
||||
for (int j = 0; j < copySize; j++)
|
||||
{
|
||||
dst[dstPos + j] = src[srcPos + j];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeModule()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/HawkeyeSettings.cs
Normal file
25
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/HawkeyeSettings.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Inspectron.Settings;
|
||||
using Inspectron.Settings.Attributes;
|
||||
using VisionBuilder.UI.Common;
|
||||
|
||||
namespace Hawkeye.VisionBuilder.UI.Sources.Hawkeye;
|
||||
|
||||
public class HawkeyeSettings(string CameraName): ISettings
|
||||
{
|
||||
|
||||
|
||||
|
||||
public string Adapter { get; set; }="192.168.1.100";
|
||||
|
||||
[File("*.jcnf")]
|
||||
public string SettingsFile { get; set; }
|
||||
|
||||
|
||||
public void RegisterSettings(InspectronSettings settings)
|
||||
{
|
||||
settings.RegisterSimple(this, () => Adapter, $"{CameraName}/Sources/Hawkeye", nameof(Adapter));
|
||||
settings.RegisterSimple(this, () => SettingsFile, $"{CameraName}/Sources/Hawkeye", nameof(SettingsFile));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
119
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/UICameraSettings.cs
Normal file
119
Hawkeye.VisionBuilder.UI.Sources.Hawkeye/UICameraSettings.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Inspectron.HawkEye.Protocol;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Hawkeye.VisionBuilder.UI.Sources.Hawkeye;
|
||||
|
||||
public class UICameraSettings
|
||||
{
|
||||
public UICameraSettings()
|
||||
{
|
||||
}
|
||||
|
||||
public UICameraSettings(CameraSettings cameraSettings)
|
||||
{
|
||||
Shutter = cameraSettings.ImageSettings.Shutter;
|
||||
Gain = cameraSettings.ImageSettings.Gain;
|
||||
OffsetX = cameraSettings.OffsetX;
|
||||
SensorWidth = cameraSettings.ImageSettings.SensorWidth;
|
||||
Width = cameraSettings.ImageWidth;
|
||||
Lines = cameraSettings.ImageSettings.Lines;
|
||||
Divider = cameraSettings.ImageSettings.Divider;
|
||||
Light1 = cameraSettings.LightPwm1;
|
||||
Light2 = cameraSettings.LightPwm2;
|
||||
TriggerEnabled = cameraSettings.ImageSettings.UseExternalTrigger == 1;
|
||||
Name = cameraSettings.Name;
|
||||
CaptureBuffer = cameraSettings.ImageSettings.CaptureBuffer;
|
||||
RescaleWidth = cameraSettings.RescaleWidth;
|
||||
MinorCutoff = cameraSettings.MinorCutoff;
|
||||
BayerFilter = cameraSettings.BayerFilter;
|
||||
LaserTrigger = cameraSettings.LaserTrigger;
|
||||
LaserTriggerDelay = cameraSettings.LaserTriggerDelay;
|
||||
FlipLines = cameraSettings.FlipLines;
|
||||
TriggerLights = cameraSettings.TriggerLights;
|
||||
MirrorX = cameraSettings.MirrorX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public CameraSettings ToCameraSettings()
|
||||
{
|
||||
return new CameraSettings()
|
||||
{
|
||||
ImageSettings = new ImageSettings()
|
||||
{
|
||||
Lines = Lines,
|
||||
CaptureBuffer = CaptureBuffer,
|
||||
Divider = Divider,
|
||||
UseExternalTrigger = TriggerEnabled ? 1 : 0,
|
||||
Gain = Gain,
|
||||
Shutter = Shutter,
|
||||
SensorWidth = SensorWidth
|
||||
|
||||
|
||||
},
|
||||
LightPwm1 = Light1,
|
||||
LightPwm2 = Light2,
|
||||
OffsetX = OffsetX,
|
||||
ImageWidth = Width,
|
||||
RescaleWidth = RescaleWidth,
|
||||
MinorCutoff = MinorCutoff,
|
||||
BayerFilter = BayerFilter,
|
||||
LaserTrigger = LaserTrigger,
|
||||
LaserTriggerDelay = LaserTriggerDelay,
|
||||
FlipLines = FlipLines,
|
||||
TriggerLights = TriggerLights,
|
||||
MirrorX = MirrorX
|
||||
};
|
||||
}
|
||||
|
||||
public static UICameraSettings LoadSettingsLocal(string path)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<UICameraSettings>(File.ReadAllText(path));
|
||||
}
|
||||
|
||||
|
||||
public int LaserTriggerDelay { get; set; }
|
||||
|
||||
public bool LaserTrigger { get; set; }
|
||||
|
||||
public bool TriggerEnabled { get; set; }
|
||||
|
||||
|
||||
public int CaptureBuffer { get; set; }
|
||||
|
||||
public bool FlipLines { get; set; }
|
||||
|
||||
public int Shutter { get; set; }
|
||||
|
||||
public int Gain { get; set; }
|
||||
|
||||
public int OffsetX { get; set; }
|
||||
|
||||
public int SensorWidth { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int RescaleWidth { get; set; }
|
||||
|
||||
public int Lines { get; set; }
|
||||
|
||||
public int Divider { get; set; }
|
||||
|
||||
public int Light1 { get; set; }
|
||||
|
||||
public int Light2 { get; set; }
|
||||
|
||||
public bool TriggerLights { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
public int MinorCutoff { get; set; }
|
||||
|
||||
|
||||
|
||||
public bool BayerFilter { get; set; }
|
||||
|
||||
|
||||
public bool MirrorX { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user