check point

This commit is contained in:
meelstorm
2025-07-14 12:03:59 +02:00
commit d3cb790bd9
431 changed files with 44078 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
using Inspectron.Camera.Emulation;
using Ninject;
namespace Inspectron.Camera
{
public static class CameraExtensions
{
public static IKernel UseEmulationCamera(this IKernel self,string[] folders)
{
self.Rebind<ICameraProvider>().ToConstant(new EmulationCameraProvider(folders)).InSingletonScope();
return self;
}
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Inspectron.Camera
{
/// <summary>
/// Standard implementation of ICameraParameter interface
/// </summary>
public class CameraParameter : ICameraParameter, INotifyPropertyChanged
{
public CameraParameter(string name, Func<object> get, Action<object> set,
IEnumerable<object> values = null)
{
Name = name;
this.setter = set;
this.getter = get;
Values = new ReadOnlyCollection<object>(values != null ?
values.ToList() : new List<object>());
}
public string Name { get; private set; }
public object Value
{
get
{
return getter();
}
set
{
if (setter == null)
throw new NotSupportedException("This is a read-only parameter");
setter(value);
RaisePropertyChanged("Value");
}
}
public bool IsReadOnly { get { return setter == null; } }
public ReadOnlyCollection<object> Values { get; private set; }
Action<object> setter;
Func<object> getter;
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
}
}

View File

@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using Inspectron.Camera.Image;
namespace Inspectron.Camera.Emulation
{
public class EmulationCamera : ICamera
{
private string[] _selectedFiles = new string[0];
private int _index = 0;
private string _currentFolder;
public void Reset()
{
_index = 0;
}
public EmulationCamera(ICameraProvider provider)
{
Provider = provider;
}
public bool SingleRun { get; set; }=false;
public void SetFolder(string imagesFolder)
{
try
{
_currentFolder = imagesFolder;
var path = Path.Combine(@"..\Data\Emulation", imagesFolder);
_selectedFiles = Directory.GetFiles(path, "*.bmp")
.Concat(Directory.GetFiles(path, "*.png"))
.Concat(Directory.GetFiles(path, "*.jpg"))
.Where(x => !Path.GetFileNameWithoutExtension(x).Contains("_analysis"))
.ToArray();
}
catch
{
}
}
public void SetFolderAbsolute(string imagesFolder)
{
try
{
_currentFolder = imagesFolder;
var path = imagesFolder;
_selectedFiles = Directory.GetFiles(path, "*.bmp")
.Concat(Directory.GetFiles(path, "*.png"))
.Concat(Directory.GetFiles(path, "*.jpg"))
.Where(x => !Path.GetFileNameWithoutExtension(x).Contains("_analysis"))
.ToArray();
}
catch
{
}
}
public string Name { get; set; } = "Emulation";
public void Open()
{
IsOpen = true;
}
public bool IsOpen { get; private set; }
public void Close()
{
IsOpen = false;
}
public bool IsGrabbingContinuous { get; }
public void StartGrabContinuous()
{
throw new NotImplementedException();
}
public void StopGrabContinuous()
{
throw new NotImplementedException();
}
public void LoadParameters(string parametersFile)
{
}
public void SaveParameters(string parametersFile)
{
throw new NotImplementedException();
}
public void SaveParametersToDevice()
{
throw new NotImplementedException();
}
public int CycleDelay { get; set; } = 1;
public int PerImageDelay { get; set; } = 5000;
public event Action OnLoopOver=delegate{};
public IImage GrabSingle()
{
if (_selectedFiles.Length == 0) return null;
var id = (_index) % _selectedFiles.Length;
if (id == 0)
{
if(_index>0)
OnLoopOver();
if (SingleRun&&_index>0)
{
// infinite sleep
Thread.Sleep(Timeout.Infinite);
}
Console.WriteLine("starting new emulation cycle");
Thread.Sleep(CycleDelay);
}
else
{
Thread.Sleep(PerImageDelay);
}
var path = _selectedFiles[id];
_index++;
var bmp = new Bitmap(path);
Console.WriteLine($"Getting image {path}");
return new BitmapImage(bmp);
}
public event ImageGrabbedHandler ImageGrabbed;
public ICameraCapabilities Capabilities { get; } = new EmulationCameraCapabilities();
public IEnumerable<ICameraParameter> Parameters => new List<ICameraParameter>()
{
new CameraParameter("Folder", () => this.CurrentFolder, x => CurrentFolder = (string) x)
};
public ICameraProvider Provider { get; }
public string CurrentFolder
{
get => _currentFolder;
set => _currentFolder = value;
}
public int Index
{
get => _index;
set => _index = value;
}
public IEnumerable<(Bitmap bmp, string path)> GetImages()
{
foreach (string selectedFile in _selectedFiles)
{
yield return (new Bitmap(selectedFile), selectedFile);
}
}
}
}

View File

@@ -0,0 +1,10 @@
namespace Inspectron.Camera.Emulation
{
public class EmulationCameraCapabilities:ICameraCapabilities
{
public bool CanGrabSingle { get; } = true;
public bool CanGrabContinuous { get; } = false;
public bool CanSaveParametersToFile { get; } = false;
public bool CanSaveParametersToDevice { get; } = false;
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
namespace Inspectron.Camera.Emulation
{
public class EmulationCameraProvider:ICameraProvider
{
private EmulationCamera _emulationCamera;
public EmulationCameraProvider(params string[] emulationFolders)
{
List<ICamera> cameras = new List<ICamera>();
foreach (string s in emulationFolders)
{
_emulationCamera = new EmulationCamera(this);
_emulationCamera.Name = "Emulation "+Path.GetFileNameWithoutExtension(s);
_emulationCamera.SetFolder(s);
cameras.Add(_emulationCamera);
}
Cameras=new ReadOnlyCollection<ICamera>(cameras);
}
public string Name { get; } = "Emulation camera provider";
public ReadOnlyCollection<ICamera> Discover()
{
return Cameras;
}
public ReadOnlyCollection<ICamera> Cameras { get; }
}
}

View File

@@ -0,0 +1,10 @@
namespace Inspectron.Camera.Enums
{
public enum EStandardRotation
{
Rot0,
Rot90,
Rot180,
Rot270
}
}

View File

@@ -0,0 +1,91 @@
using System.Collections.Generic;
using Inspectron.Camera.Image;
namespace Inspectron.Camera
{
public interface ICamera
{
/// <summary>
/// Returns the name of the camera
/// </summary>
string Name { get; }
/// <summary>
/// Opens the camera
/// </summary>
void Open();
/// <summary>
/// Returns true if the camera is opened
/// </summary>
bool IsOpen { get; }
/// <summary>
/// Closes the camera
/// </summary>
void Close();
/// <summary>
/// Returns true if the camera is live
/// </summary>
bool IsGrabbingContinuous { get; }
/// <summary>
/// Stats live asynchronous acquisition. Images are transmitted the ImageGrabbed Event
/// </summary>
void StartGrabContinuous();
/// <summary>
/// Stops the asynchronous acquisition.
/// </summary>
void StopGrabContinuous();
/// <summary>
/// Loads the parameters from a filename
/// </summary>
/// <param name="parameters_file"></param>
void LoadParameters(string parametersFile);
/// <summary>
/// Saves the camera parameters to the given filename
/// </summary>
/// <param name="parameters_file"></param>
void SaveParameters(string parametersFile);
/// <summary>
/// Saves the parameters to the camera memory
/// </summary>
void SaveParametersToDevice();
/// <summary>
/// Synchronously grab an image
/// </summary>
/// <returns></returns>
IImage GrabSingle();
/// <summary>
/// Event occuring when a new frame is acquired
/// </summary>
event ImageGrabbedHandler ImageGrabbed;
/// <summary>
/// Returns the capabilities of the camera
/// </summary>
ICameraCapabilities Capabilities { get; }
/// <summary>
/// Returns a Ienumerable containing all of the camera
/// </summary>
IEnumerable<ICameraParameter> Parameters { get; }
/// <summary>
/// Reference to Parent Camera Provider
/// </summary>
ICameraProvider Provider { get; }
}
/// <summary>
/// Handler called when an image has been grabbed
/// </summary>
/// <param name="image">the grabbed image</param>
public delegate void ImageGrabbedHandler(ICamera sender, IImage image);
}

View File

@@ -0,0 +1,25 @@
namespace Inspectron.Camera
{
/// <summary>
/// Interface specifying the capabilities of the camera
/// </summary>
public interface ICameraCapabilities
{
/// <summary>
/// Indicates that handle synchronous acquisition. (see ICamera Grab method)
/// </summary>
bool CanGrabSingle { get; }
/// <summary>
/// Indicates that handle live asynchronous acquisition. Images are transmitted the ImageGrabbed Event. (see ICamera StartLive / StopLive methods)
/// </summary>
bool CanGrabContinuous { get; }
/// <summary>
/// Indicates that the camera can save and load the current parameter set to a file
/// </summary>
bool CanSaveParametersToFile { get; }
/// <summary>
/// Indicates that the camera can save the current parameter set to memory
/// </summary>
bool CanSaveParametersToDevice { get; }
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.ObjectModel;
namespace Inspectron.Camera
{
/// <summary>
/// ICameraParameter interface, standard interface to list and change camera parameters
/// </summary>
public interface ICameraParameter
{
/// <summary>
/// User friendly name
/// </summary>
string Name { get; }
/// <summary>
/// Getter and setter to values, null setter if readonly
/// </summary>
object Value { get; set; }
/// <summary>
/// Indicates that the parameter is readonly, Value setter is null
/// </summary>
bool IsReadOnly { get; }
/// <summary>
/// Values that can be chosen in case of fixed parameters set.
/// </summary>
ReadOnlyCollection<object> Values { get; }
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.ObjectModel;
namespace Inspectron.Camera
{
public interface ICameraProvider
{
/// <summary>
///
/// </summary>
string Name { get; }
/// <summary>
///
/// </summary>
/// <returns></returns>
ReadOnlyCollection<ICamera> Discover();
/// <summary>
///
/// </summary>
ReadOnlyCollection<ICamera> Cameras { get; }
}
}

View File

@@ -0,0 +1,35 @@
using System.Drawing;
using System.Drawing.Imaging;
namespace Inspectron.Camera.Image
{
public class BitmapImage : IImage
{
private readonly Bitmap _bitmap;
public BitmapImage(Bitmap bitmap)
{
_bitmap = bitmap;
}
public int Width => _bitmap.Width;
public int Height => _bitmap.Height;
public int Channels => throw new System.NotImplementedException();
public Bitmap Bitmap => (Bitmap)_bitmap.Clone();
public void Dispose()
{
}
public void Save(string path)
{
_bitmap.Save(path,ImageFormat.Bmp);
}
}
}

View File

@@ -0,0 +1,131 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace Inspectron.Camera.Image
{
public class ByteImage : IImage
{
Byte[] data;
int step;
/// <summary>
/// Initializes a newinstance with the given image dimensions and pixel-data
/// </summary>
/// <param name="width">the image width in pixel</param>
/// <param name="height">the image height in pixel</param>
/// <param name="channels">the number of color channels (1-4)</param>
/// <param name="channelDepth">the bit-depth per channel (8 or 16)</param>
/// <param name="data">pointer to the pixel data in unmanaged memory</param>
/// <param name="step">the number of bytes per image row</param>
public ByteImage(int width, int height, int channels,
Byte[] data, int step)
{
Width = width;
Height = height;
Channels = channels;
this.data = data;
this.step = step;
ProcessBitmapCache();
}
private void ProcessBitmapCache()
{
var image = new Bitmap(Width, Height,
Channels == 1 ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb);
var lockedDst = image.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly,
image.PixelFormat);
Marshal.Copy(data, 0, lockedDst.Scan0, data.Length);
image.UnlockBits(lockedDst);
if (Channels == 1)
{
image.Palette = _monoPalette;
}
_cachedBMP = image;
}
static ColorPalette GetGrayScalePalette()
{
Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
ColorPalette monoPalette = bmp.Palette;
Color[] entries = monoPalette.Entries;
for (int i = 0; i < 256; i++)
{
entries[i] = Color.FromArgb(i, i, i);
}
return monoPalette;
}
private static ColorPalette _monoPalette = GetGrayScalePalette();
public int Width { get; private set; }
public int Height { get; private set; }
public int Channels { get; private set; }
public IImageLock Lock { get { return new ImageLock(this); } }
private Bitmap _cachedBMP = null;
public Bitmap Bitmap
{
get
{
return (Bitmap)_cachedBMP.Clone();
}
}
public byte[] Data
{
get => data;
set => data = value;
}
public int Step
{
get => step;
set => step = value;
}
class ImageLock : IImageLock
{
ByteImage parent;
GCHandle pinnedArray;
internal ImageLock(ByteImage parent) { this.parent = parent; }
public int Step { get { return parent.step; } }
public IntPtr PixelData
{
get
{
pinnedArray = GCHandle.Alloc(parent.data, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
return pointer;
}
}
public void Dispose()
{
pinnedArray.Free();
}
}
public void Save(string path)
{
(new Bitmap(new MemoryStream(data))).Save(path,ImageFormat.Bmp);
}
public void Dispose()
{
data = null;
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace Inspectron.Camera.Image
{
public static class Extensions
{
public static ByteImage ToByteImage(this Bitmap self,int channels)
{
MemoryStream ms = new MemoryStream();
var bmp = self;
bmp.Save(ms, ImageFormat.Bmp);
ByteImage bi = new ByteImage(bmp.Width, bmp.Height, channels, ms.ToArray(), bmp.Width);
return bi;
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Drawing.Imaging;
namespace Inspectron.Camera.Image
{
public interface IImage:IDisposable
{
int Width { get; }
int Height { get; }
int Channels { get; }
void Save(string path);
System.Drawing.Bitmap Bitmap { get; }
}
}

View File

@@ -0,0 +1,10 @@
using System;
namespace Inspectron.Camera.Image
{
public interface IImageLock:IDisposable
{
int Step { get; }
IntPtr PixelData { get; }
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="NoImage\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Threading;
using Inspectron.Camera.Image;
namespace Inspectron.Camera.NoImage
{
public class NoImageCamera:ICamera
{
public NoImageCamera(ICameraProvider provider)
{
Provider = provider;
}
private int _acquisitionDelay = 0;
public string Name { get; }
public void Open()
{
}
public bool IsOpen { get; }
public void Close()
{
}
public bool IsGrabbingContinuous { get; private set; }
public void StartGrabContinuous()
{
IsGrabbingContinuous = true;
}
public void StopGrabContinuous()
{
IsGrabbingContinuous = false;
}
public void LoadParameters(string parametersFile)
{
throw new System.NotImplementedException();
}
public void SaveParameters(string parametersFile)
{
throw new System.NotImplementedException();
}
public void SaveParametersToDevice()
{
throw new System.NotImplementedException();
}
public int AcquisitionDelay
{
get => _acquisitionDelay;
set => _acquisitionDelay = value;
}
public IImage GrabSingle()
{
Thread.Sleep(AcquisitionDelay);
return null;
}
public event ImageGrabbedHandler ImageGrabbed=delegate{};
public ICameraCapabilities Capabilities =>new NoImageCameraCapabilities();
public IEnumerable<ICameraParameter> Parameters =>new List<ICameraParameter>()
{
new CameraParameter("AcquisitionDelay",() => this.AcquisitionDelay,x=>AcquisitionDelay=(int)x)
};
public ICameraProvider Provider { get; }
}
}

View File

@@ -0,0 +1,10 @@
namespace Inspectron.Camera.NoImage
{
public class NoImageCameraCapabilities:ICameraCapabilities
{
public bool CanGrabSingle { get; }=true;
public bool CanGrabContinuous { get; } = true;
public bool CanSaveParametersToFile { get; } = false;
public bool CanSaveParametersToDevice { get; } = false;
}
}

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Inspectron.Camera.NoImage
{
public class NoImageCameraProvider : ICameraProvider
{
public string Name { get; } = "No image camera provider";
public int CamerasToDiscover { get; set; } = 1;
public ReadOnlyCollection<ICamera> Discover()
{
return Enumerable.Range(0, CamerasToDiscover).Select(x => (ICamera)new NoImageCamera(this)).ToList().AsReadOnly();
}
public ReadOnlyCollection<ICamera> Cameras { get; }
}
}