using Cognex.VisionPro;
using LampInspectionMachine.Interfaces;
using LampInspectionMachine.Log4xml;
using LampInspectionMachine.Model;
using Microsoft.Win32;
using MvCamCtrl.NET;
using MvCameraControl;
using SqlSugar.DistributedSystem.Snowflake;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
namespace LampInspectionMachine.Cameralibs.HKCamera
{
public class MvCamera : ICamera, INotifyPropertyChanged
{
#region 字段
private IDevice m_MyCamera = null;
private Thread m_hReceiveThread;
#endregion
#region 属性
public CameraBrand CameraBrand { get => CameraBrand.HikRobot_MVS; }
public string Name { get; private set; }
public Guid ID { get; private set; }
public string ManufacturerName { get; private set; }
public string ModelName { get; private set; }
public string SerialNumber { get; private set; }
public CameraType CameraType { get; private set; }
public IDeviceInfo CameraInfo { get; private set; }
public UInt32 ImageWidth { get; private set; }
public UInt32 ImageHeight { get; private set; }
public MvGvspPixelType PixelType { get; private set; }
private bool _IsGrabbing;
///
/// 正在采集
///
public bool IsGrabbing
{
get { return _IsGrabbing; }
private set { SetProperty(ref _IsGrabbing, value); }
}
private ICogImage _Image;
public ICogImage Image
{
get { return _Image; }
private set { SetProperty(ref _Image, value); }
}
public bool IsConnected { get; private set; }
private bool IsHaveCamera = false;
///
/// 采集用时
///
public TimeSpan TotalTime { get; private set; }
///
/// 错误信息
///
public string ErrorMessage { get; private set; }
#endregion
#region 事件
///
/// 手动采集图像回调事件
///
public event Action ImageCallbackEvent;
///
/// 触发取图回调事件
///
public event Action GrabImageCallbackEvent;
public event Action CameraConnectChangedEvent;
#endregion
public MvCamera(Guid _ID, string _Name, string _SerialNumber)
{
ID = _ID;
Name = _Name;
SerialNumber = _SerialNumber;
// ch: 初始化 SDK | en: Initialize SDK
SDKSystem.Initialize();
List devInfoList = new List();
// ch:枚举设备 | en:Enum device
int nRet = DeviceEnumerator.EnumDevices(DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvVirGigEDevice | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvUsbDevice | DeviceTLayerType.MvVirUsbDevice, out devInfoList);
if (nRet != MvError.MV_OK)
{
throw new Exception($"Enumerate devices fail: {nRet:x8}");
}
foreach (var devInfo in devInfoList)
{
if (devInfo.TLayerType == DeviceTLayerType.MvGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvVirGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvGenTLGigEDevice)
{
IGigEDeviceInfo gigeDevInfo = devInfo as IGigEDeviceInfo;
uint nIp1 = ((gigeDevInfo.CurrentIp & 0xff000000) >> 24);
uint nIp2 = ((gigeDevInfo.CurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((gigeDevInfo.CurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (gigeDevInfo.CurrentIp & 0x000000ff);
Console.WriteLine("DevIP: {0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
if (string.Equals(devInfo.SerialNumber, _SerialNumber))
{
ManufacturerName = devInfo.ManufacturerName;
ModelName = devInfo.ModelName;
SerialNumber = devInfo.SerialNumber;
CameraType = CameraType.GIGE;
CameraInfo = devInfo;
IsHaveCamera = true;
break;
}
}
else if (devInfo.TLayerType == DeviceTLayerType.MvUsbDevice || devInfo.TLayerType == DeviceTLayerType.MvVirUsbDevice)
{
if (string.Equals(devInfo.SerialNumber, _SerialNumber))
{
ManufacturerName = devInfo.ManufacturerName;
ModelName = devInfo.ModelName;
SerialNumber = devInfo.SerialNumber;
CameraType = CameraType.USB;
CameraInfo = devInfo;
IsHaveCamera = true;
break;
}
}
}
IsConnected = false;
}
#region 方法
///
/// 获取设备
///
///
public static CameraInfo[] GetDevices()
{
List cameras = new List();
try
{
if (!CheckSoftwareInstalled().isInstalled)
{
//LogHelper.WriteLogInfo("未安装MVS");
return cameras.ToArray();
}
// ch: 初始化 SDK | en: Initialize SDK
SDKSystem.Initialize();
List devInfoList = new List();
// ch:枚举设备 | en:Enum device
int nRet = DeviceEnumerator.EnumDevices(DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvVirGigEDevice | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvUsbDevice | DeviceTLayerType.MvVirUsbDevice, out devInfoList);
if (nRet != MvError.MV_OK)
{
throw new Exception($"Enumerate devices fail: {nRet:x8}");
}
foreach (var devInfo in devInfoList)
{
if (devInfo.TLayerType == DeviceTLayerType.MvGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvVirGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvGenTLGigEDevice)
{
IGigEDeviceInfo gigeDevInfo = devInfo as IGigEDeviceInfo;
uint nIp1 = ((gigeDevInfo.CurrentIp & 0xff000000) >> 24);
uint nIp2 = ((gigeDevInfo.CurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((gigeDevInfo.CurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (gigeDevInfo.CurrentIp & 0x000000ff);
Console.WriteLine("DevIP: {0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
cameras.Add(new CameraInfo()
{
CameraName = "",
CameraBrand = CameraBrand.HikRobot_MVS,
CameraType = CameraType.GIGE,
Id = Guid.NewGuid(),
ManufacturerName = devInfo.ManufacturerName,
Model = devInfo.ModelName,
SerialNumber = devInfo.SerialNumber,
CameraIp = $"{nIp1}.{nIp2}.{nIp3}.{nIp4}",
});
}
else if (devInfo.TLayerType == DeviceTLayerType.MvUsbDevice || devInfo.TLayerType == DeviceTLayerType.MvVirUsbDevice)
{
cameras.Add(new CameraInfo()
{
CameraName = "",
CameraBrand = CameraBrand.HikRobot_MVS,
CameraType = CameraType.USB,
Id = Guid.NewGuid(),
ManufacturerName = devInfo.ManufacturerName,
Model = devInfo.ModelName,
SerialNumber = devInfo.SerialNumber,
CameraIp = "",
});
}
}
}
catch (Exception ex)
{
// LogHelper.WriteLogError("搜索海康相机列表时出错!", ex);
}
return cameras.ToArray();
}
///
/// 检查相机软件是否安装
///
///
public static (bool isInstalled, string version) CheckSoftwareInstalled()
{
string softwareName = "MVS";
string softwareVersion = "4.5.0";
string[] registryPaths = new[]
{
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
};
foreach (var path in registryPaths)
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))
{
if (key == null) continue;
foreach (string subKeyName in key.GetSubKeyNames())
{
using (RegistryKey subKey = key.OpenSubKey(subKeyName))
{
string displayName = subKey.GetValue("DisplayName")?.ToString();
if (displayName != null && displayName.Contains(softwareName))
{
string version = subKey.GetValue("DisplayVersion")?.ToString();
Version v1 = new Version(version);
Version v2 = new Version(softwareVersion);
if (v1 >= v2)
{
return (true, version);
}
else
{
return (false, version);
}
}
}
}
}
}
return (false, "");
}
///
/// 打开相机
///
///
///
public bool OpenDevice()
{
if (!IsHaveCamera)
{
List devInfoList = new List();
// ch:枚举设备 | en:Enum device
int nRet = DeviceEnumerator.EnumDevices(DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvVirGigEDevice | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvUsbDevice | DeviceTLayerType.MvVirUsbDevice, out devInfoList);
if (nRet != MvError.MV_OK)
{
throw new Exception($"Enumerate devices fail: {nRet:x8}");
}
foreach (var devInfo in devInfoList)
{
if (devInfo.TLayerType == DeviceTLayerType.MvGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvVirGigEDevice || devInfo.TLayerType == DeviceTLayerType.MvGenTLGigEDevice)
{
IGigEDeviceInfo gigeDevInfo = devInfo as IGigEDeviceInfo;
uint nIp1 = ((gigeDevInfo.CurrentIp & 0xff000000) >> 24);
uint nIp2 = ((gigeDevInfo.CurrentIp & 0x00ff0000) >> 16);
uint nIp3 = ((gigeDevInfo.CurrentIp & 0x0000ff00) >> 8);
uint nIp4 = (gigeDevInfo.CurrentIp & 0x000000ff);
Console.WriteLine("DevIP: {0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
if (string.Equals(devInfo.SerialNumber, SerialNumber))
{
ManufacturerName = devInfo.ManufacturerName;
ModelName = devInfo.ModelName;
SerialNumber = devInfo.SerialNumber;
CameraType = CameraType.GIGE;
CameraInfo = devInfo;
IsHaveCamera = true;
break;
}
}
else if (devInfo.TLayerType == DeviceTLayerType.MvUsbDevice || devInfo.TLayerType == DeviceTLayerType.MvVirUsbDevice)
{
if (string.Equals(devInfo.SerialNumber, SerialNumber))
{
ManufacturerName = devInfo.ManufacturerName;
ModelName = devInfo.ModelName;
SerialNumber = devInfo.SerialNumber;
CameraType = CameraType.USB;
CameraInfo = devInfo;
IsHaveCamera = true;
break;
}
}
}
if (!IsHaveCamera)
{
throw new Exception("没有发现相机");
}
}
if (m_MyCamera == null)
{
// ch:创建设备 | en:Create device
try
{
m_MyCamera = DeviceFactory.CreateDevice(CameraInfo);
}
catch (Exception)
{
return false;
}
//m_MyCamera.RegisterExceptionCallBack(pCallBackFunc, IntPtr.Zero);
}
int nRet1 = m_MyCamera.Open(DeviceAccessMode.AccessControl, 0);
if (nRet1 != MvError.MV_OK)
{
m_MyCamera.Dispose();
return false;
}
CameraConnectChangedEvent?.Invoke(ID, true);
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (CameraType == CameraType.GIGE)
{
int packetSize;
int ret = (m_MyCamera as IGigEDevice).GetOptimalPacketSize(out packetSize);
if (packetSize > 0)
{
ret = m_MyCamera.Parameters.SetIntValue("GevSCPSPacketSize", packetSize);
if (ret != MvError.MV_OK)
{
Console.WriteLine("Warning: Set Packet Size failed {0:x8}", ret);
}
else
{
Console.WriteLine("Set PacketSize to {0}", packetSize);
}
}
else
{
Console.WriteLine("Warning: Get Packet Size failed {0:x8}", ret);
}
}
//连续采集
m_MyCamera.Parameters.SetEnumValueByString("TriggerMode", "Off");
// ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
// 1 - Line1;
// 2 - Line2;
// 3 - Line3;
// 4 - Counter;
// 7 - Software;
// m_MyCamera.Parameters.SetEnumValueByString("TriggerSource", "Software");
m_MyCamera.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
//m_MyCamera.Parameters.SetCommandValue("TriggerSoftware");
// ch:注册回调函数 | en:Register image callback
// m_MyCamera.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler;
IsConnected = m_MyCamera.IsConnected;
return IsConnected;
}
///
/// 关闭相机
///
public void CloseDevice()
{
m_MyCamera.StreamGrabber.FrameGrabedEvent -= FrameGrabedEventHandler;
// ch:关闭设备 | en:Close Device
m_MyCamera.Close();
m_MyCamera.Dispose();
m_MyCamera = null;
if (IsConnected)
{
IsConnected = false;
CameraConnectChangedEvent?.Invoke(ID, IsConnected);
}
}
///
/// 取图前的必要操作步骤
///
///
private Int32 NecessaryOperBeforeGrab()
{
// ch:取图像宽 | en:Get Iamge Width
IIntValue pcWidth = null;
int nRet = m_MyCamera.Parameters.GetIntValue("Width", out pcWidth);
if (nRet != MvError.MV_OK)
{
return nRet;
}
ImageWidth = (UInt32)pcWidth.CurValue;
// ch:取图像高 | en:Get Iamge Height
IIntValue pcHeight = null;
nRet = m_MyCamera.Parameters.GetIntValue("Height", out pcHeight);
if (nRet != MvError.MV_OK)
{
return nRet;
}
ImageHeight = (UInt32)pcHeight.CurValue;
// ch:取像素格式 | en:Get Pixel Format
IEnumValue pcPixelFormat = null;
nRet = m_MyCamera.Parameters.GetEnumValue("PixelFormat", out pcPixelFormat);
if (nRet != MvError.MV_OK)
{
return nRet;
}
PixelType = (MvCameraControl.MvGvspPixelType)pcPixelFormat.CurEnumEntry.Value;
return MvError.MV_OK;
}
///
/// 采集图像
///
///
public ICogImage Grab()
{
m_MyCamera.StreamGrabber.StartGrabbing();
m_MyCamera.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
m_MyCamera.Parameters.SetEnumValueByString("TriggerMode", "Off");
m_MyCamera.Parameters.SetFloatValue("ExposureTime", 5000); // 单位μs
m_MyCamera.Parameters.SetIntValue("GevSCPSPacketSize", 8164);
m_MyCamera.Parameters.SetIntValue("GevSCPD", 12000); // 缓冲区大小
m_MyCamera.Parameters.SetEnumValueByString("PixelFormat", "RGB8");
IFrameOut frameOut = null;
bool Succeed = false;
int nRet = -1;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 5; i++)
{
try
{
if (m_MyCamera == null || !m_MyCamera.IsConnected)
{
OpenDevice();
}
ErrorMessage = "";
// ch:前置配置 | en:pre-operation
nRet = NecessaryOperBeforeGrab();
if (nRet != MvError.MV_OK)
{
CloseDevice();
OpenDevice();
ErrorMessage = $"{nRet: x8}";
continue;
}
// ch:开始采集 | en:Start Grabbing
nRet = m_MyCamera.StreamGrabber.StartGrabbing();
if (nRet != MvError.MV_OK)
{
CloseDevice();
OpenDevice();
ErrorMessage = $"{nRet: x8}";
continue;
}
nRet = m_MyCamera.StreamGrabber.GetImageBuffer(20000, out frameOut);
m_MyCamera.StreamGrabber.StopGrabbing();
if (nRet != MvError.MV_OK)
{
CloseDevice();
OpenDevice();
ErrorMessage = $"{nRet: x8}";
continue;
}
m_MyCamera.StreamGrabber.FreeImageBuffer(frameOut);
Succeed = true;
break;
}
catch (Exception ex)
{
CloseDevice();
OpenDevice();
ErrorMessage = ex.Message;
}
}
if (!Succeed)
{
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
return null;
}
if( frameOut !=null)
Image = AnalyticImage(frameOut);
TotalTime = sw.Elapsed;
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
return Image;
}
///
/// 开始采集图像
///
public void StartGrabbing()
{
if (IsGrabbing)
return;
IsGrabbing = true;
m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
m_hReceiveThread.Start();
}
///
/// 停止采集图像
///
public void StopGrabbing()
{
try
{
if ( IsGrabbing )
{
IsGrabbing = false;
Thread.Sleep(1000);
}
if (m_hReceiveThread != null)
{
m_hReceiveThread.Abort();
m_hReceiveThread = null;
}
}
catch (Exception)
{
}
}
private void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
{
GrabImageCallbackEvent?.Invoke(AnalyticImage(e.FrameOut));
//Console.WriteLine("Get one frame: Width[{0}] , Height[{1}] , ImageSize[{2}], FrameNum[{3}]", e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.Image.ImageSize, e.FrameOut.FrameNum);
}
///
/// Converts the image data from the specified object into an
/// format.
///
/// This method processes both color and monochrome images, converting them to a
/// compatible format for further analysis. Unsupported pixel formats are not processed, and the method will
/// return in such cases. The caller is responsible for ensuring that the parameter is valid and properly initialized.
/// The frame output containing the image data to be analyzed and converted.
/// An object representing the converted image. Returns if the
/// image format is unsupported or if an error occurs during conversion.
private ICogImage AnalyticImage(IFrameOut frameOut)
{
ICogImage image = null;
int nRet = -1;
//IntPtr pTemp = IntPtr.Zero;
IImage pImage = frameOut.Image;
MvCameraControl.MvGvspPixelType pixelType = frameOut.Image.PixelType;
if (IsColorPixelFormat(frameOut.Image.PixelType)) // 彩色图像处理
{
if (frameOut.Image.PixelType == MvCameraControl.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
{
//pTemp = frameOut.Image.PixelDataPtr;
}
else
{
nRet = m_MyCamera.PixelTypeConverter.ConvertPixelType(frameOut.Image, out pImage, MvCameraControl.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed);
if (nRet != MvError.MV_OK)
{
frameOut.Dispose();
return null;
}
pixelType = MvCameraControl.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
}
}
else if (IsMonoPixelFormat(frameOut.Image.PixelType)) // Mono图像处理
{
if (frameOut.Image.PixelType == MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono8)
{
//pTemp = frameOut.Image.PixelDataPtr;
}
else
{
// 其他格式Mono转为Mono8
nRet = m_MyCamera.PixelTypeConverter.ConvertPixelType(frameOut.Image, out pImage, MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono8);
if (nRet != MvError.MV_OK)
{
frameOut.Dispose();
return null;
}
}
pixelType = MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono8;
}
else
{
return null; // 不支持的图像格式
}
// 直接转换为CogImage,避免不必要的内存拷贝
image = ConvertToICogImage(pImage.Width, pImage.Height,
pImage.PixelDataPtr, pixelType);
////2.申请 byte[]
//byte[] m_BufForDriver1 = new byte[pImage.ImageSize];
////3.海康相机取流 指针转 byte[]
//Marshal.Copy(pImage.PixelDataPtr, m_BufForDriver1, 0, ((int)pImage.ImageSize));
////4.转换成 CogImage
//image = ConvertToICogImage(pImage.Width, pImage.Height, pImage.PixelDataPtr, pixelType);
pImage.Dispose();
frameOut.Dispose();
return image;
}
///
/// 设置曝光时间
///
///
///
public bool SetExposureTime(float ExposureTime)
{
int nRet = m_MyCamera.Parameters.SetFloatValue("ExposureTime", ExposureTime);
if (nRet != MvError.MV_OK)
{
return false;
}
else
{
return true;
}
}
///
/// 获取曝光时间
///
///
public float GetExposureTime()
{
IFloatValue pcFloatValue = null;
int nRet = m_MyCamera.Parameters.GetFloatValue("ExposureTime", out pcFloatValue);
if (nRet == MvError.MV_OK)
{
return pcFloatValue.CurValue;
}
else
{
return 0;
}
}
///
/// 设置增益
///
///
///
public bool SetGain(float Gain)
{
int nRet = m_MyCamera.Parameters.SetFloatValue("Gain", Gain);
if (nRet != MvError.MV_OK)
{
return false;
}
else
{
return true;
}
}
///
/// 获取增益
///
///
public float GetGain()
{
IFloatValue pcFloatValue = null;
int nRet = m_MyCamera.Parameters.GetFloatValue("Gain", out pcFloatValue);
if (nRet == MvError.MV_OK)
{
return pcFloatValue.CurValue;
}
else
{
return 0;
}
}
///
/// ch:获取触发模式 | en:Get Trigger Mode
///
/// On/Off
public bool GetTriggerMode()
{
IEnumValue enumValue;
int result = m_MyCamera.Parameters.GetEnumValue("TriggerMode", out enumValue);
if (result == MvError.MV_OK)
{
if (enumValue.CurEnumEntry.Symbolic == "On")
{
return true;
}
return false;
}
return false;
}
///
/// 设置触发模式
///
/// 触发模式
/// 触发源0 - Line0;1 - Line1;2 - Line2;3 - Line3;4 - Counter;7 - Software;
///
public bool SetTriggerMode(bool mode, int triggerSource)
{
string strmode = mode ? "On" : "Off";
int nRet = m_MyCamera.Parameters.SetEnumValueByString("TriggerMode", strmode);
if (nRet != MvError.MV_OK)
{
return false;
}
if (mode)
{
return SetTriggerSource(triggerSource);
}
else
{
nRet = m_MyCamera.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
if (nRet != MvError.MV_OK)
{
return false;
}
}
return true;
}
///
/// Sets the trigger source for the camera.
///
/// 0 - Line0;1 - Line1;2 - Line2;3 - Line3;4 - Counter;7 - Software;
///
///
public bool SetTriggerSource(int source)
{
// ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
// 1 - Line1;
// 2 - Line2;
// 3 - Line3;
// 4 - Counter;
// 7 - Software;
string sourceStr;
switch (source)
{
case 0: sourceStr = "Line0"; break;
case 1: sourceStr = "Line1"; break;
case 2: sourceStr = "Line2"; break;
case 3: sourceStr = "Line3"; break;
case 4: sourceStr = "Counter"; break;
case 7: sourceStr = "Software"; break;
default: throw new ArgumentOutOfRangeException(nameof(source), "Invalid trigger source value");
}
int nRet = m_MyCamera.Parameters.SetEnumValueByString("TriggerSource", sourceStr);
if (nRet != MvError.MV_OK)
{
return false;
}
return true;
}
///
/// Retrieves the current trigger source setting of the camera.
///
/// This method queries the camera's parameters to determine the current trigger source.
/// If the retrieval is unsuccessful or the trigger source is not recognized, the method returns -1.
/// An integer representing the trigger source: - 0 for
/// "Line0".
- 1 for "Line1".
- 2
/// for "Line2".
- 3 for "Line3".
/// - 4 for "Counter".
- 7 for
/// "Software".
- -1 if the trigger source is unknown or if the retrieval
/// fails.
public int GetTriggerSource()
{
IEnumValue enumValue;
int result = m_MyCamera.Parameters.GetEnumValue("TriggerSource", out enumValue);
if (result == MvError.MV_OK)
{
switch (enumValue.CurEnumEntry.Symbolic)
{
case "Line0": return 0;
case "Line1": return 1;
case "Line2": return 2;
case "Line3": return 3;
case "Counter": return 4;
case "Software": return 7;
default: return -1; // 未知触发源
}
}
return -1; // 获取失败
}
///
/// Sends a software trigger command to the camera.
///
/// This method triggers the camera to capture an image or perform an action based on
/// its current configuration. Ensure the camera is properly initialized and configured to respond to software
/// triggers before calling this method.
public void TriggerSoftware()
{
// ch:触发软件 | en:Trigger Software
m_MyCamera.Parameters.SetCommandValue("TriggerSoftware");
}
private void GetStreamThreadProc()
{
m_MyCamera.StreamGrabber.StartGrabbing();
m_MyCamera.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
m_MyCamera.Parameters.SetEnumValueByString("TriggerMode", "Off");
m_MyCamera.Parameters.SetFloatValue("ExposureTime", 5000); // 单位μs
m_MyCamera.Parameters.SetIntValue("GevSCPSPacketSize", 8164);
m_MyCamera.Parameters.SetIntValue("GevSCPD", 12000); // 缓冲区大小
m_MyCamera.Parameters.SetEnumValueByString("PixelFormat", "RGB8");
while (IsGrabbing)
{
Stopwatch sw = Stopwatch.StartNew();
try
{
IFrameOut frameOut = null;
int nRet = m_MyCamera.StreamGrabber.GetImageBuffer(5000, out frameOut);
double time1 = sw.Elapsed.TotalMilliseconds;
Console.WriteLine($"获取图像:{time1}ms");
if ( nRet == MvError.MV_OK )
{
Image = AnalyticImage(frameOut);
TotalTime = sw.Elapsed;
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
m_MyCamera.StreamGrabber.FreeImageBuffer(frameOut);
}
else
{
TotalTime = sw.Elapsed;
Thread.Sleep(5);
}
}
catch (Exception ex)
{
TotalTime = sw.Elapsed;
ErrorMessage = ex.Message;
ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
continue;
}
}
IsGrabbing = false;
}
///
/// Converts raw image data into an object, supporting both monochrome and color pixel
/// formats.
///
/// This method supports both monochrome (PixelType_Gvsp_Mono8) and color pixel formats.
/// For color images, the method processes the image data as a planar color format.
/// The height of the image in pixels.
/// The width of the image in pixels.
/// A pointer to the buffer containing the raw image data.
/// The pixel format of the image, specified as a value.
/// An object representing the converted image. Returns if the
/// conversion fails.
private ICogImage ConvertToICogImage(UInt32 nHeight, UInt32 nWidth, IntPtr pImageBuf, MvCameraControl.MvGvspPixelType enPixelType)
{
ICogImage cogImage = null;
// ch:获取步长 || en: Get nRowStep
uint m_nRowStep = nWidth * nHeight;
// ch: 显示 || display
try
{
if (enPixelType == MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono8)
{
CogImage8Root cogImage8Root = new CogImage8Root();
cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null);
CogImage8Grey cogImage8Grey = new CogImage8Grey();
cogImage8Grey.SetRoot(cogImage8Root);
cogImage = cogImage8Grey.ScaleImage((int)nWidth, (int)nHeight);
System.GC.Collect();
}
else
{
CogImage8Root image0 = new CogImage8Root();
IntPtr ptr0 = new IntPtr(pImageBuf.ToInt64());
image0.Initialize((int)nWidth, (int)nHeight, ptr0, (int)nWidth, null);
CogImage8Root image1 = new CogImage8Root();
IntPtr ptr1 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep);
image1.Initialize((int)nWidth, (int)nHeight, ptr1, (int)nWidth, null);
CogImage8Root image2 = new CogImage8Root();
IntPtr ptr2 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep * 2);
image2.Initialize((int)nWidth, (int)nHeight, ptr2, (int)nWidth, null);
CogImage24PlanarColor colorImage = new CogImage24PlanarColor();
colorImage.SetRoots(image0, image1, image2);
cogImage = colorImage.ScaleImage((int)nWidth, (int)nHeight);
System.GC.Collect();
}
}
catch (System.Exception ex)
{
ErrorMessage = $"转换ICogImage出错: {ex.Message}";
return null;
}
return cogImage;
}
///
/// 图像是否为Mono格式
///
///
///
private bool IsMonoPixelFormat(MvCameraControl.MvGvspPixelType enType)
{
switch (enType)
{
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono10:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono12:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_Mono16:
return true;
default:
return false;
}
}
///
/// 图像是否为彩色
///
///
///
private bool IsColorPixelFormat(MvCameraControl.MvGvspPixelType enType)
{
switch (enType)
{
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BGRA8_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRBGG8:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGR16:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerRG16:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerGB16:
case MvCameraControl.MvGvspPixelType.PixelType_Gvsp_BayerBG16:
return true;
default:
return false;
}
}
#endregion
#region 属性通知
///
/// Occurs when a property value changes.
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
///
/// Type of the property.
/// Reference to a property with both getter and setter.
/// Desired value for the property.
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.
/// True if the value was changed, false if the existing value matched the
/// desired value.
protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(storage, value)) return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
///
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
///
/// Type of the property.
/// Reference to a property with both getter and setter.
/// Desired value for the property.
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.
/// Action that is called after the property value has been changed.
/// True if the value was changed, false if the existing value matched the
/// desired value.
protected virtual bool SetProperty(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer.Default.Equals(storage, value)) return false;
storage = value;
onChanged?.Invoke();
RaisePropertyChanged(propertyName);
return true;
}
///
/// Raises this object's PropertyChanged event.
///
/// Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
///
/// Raises this object's PropertyChanged event.
///
/// The PropertyChangedEventArgs
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
#endregion
}
}