using Cognex.VisionPro; using CSScripting; using Microsoft.Win32; using MVSDK_Net; using NPOI.Util; using NPOI.XSSF.Model; using OpenCvSharp.Dnn; using Org.BouncyCastle.Asn1.Tsp; using OxyPlot; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data.SqlTypes; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Media.Media3D; using TeamAAS_VP.Enums; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; using TeamAAS_VP; using static MVSDK_Net.IMVDefine; namespace TeamAAS_VP.Core.Cameras { public class AHuaCamera : CameraBase, ICamera, INotifyPropertyChanged { #region 字段 private Thread m_hReceiveThread; #endregion #region 属性 /// /// 是否是3D相机 /// public bool Is3D { get; } = false; public CameraBrand CameraBrand { get => CameraBrand.IRayple; } public string Name { get; private set; } public Guid ID { get; private set; } public int Index { get; set; } public string ManufacturerName { get; private set; } public bool IsFindByIp { get; private set; } public string ModelName { get; private set; } public string SerialNumber { get; private set; } public string CameraIp { get; private set; } public CameraType CameraType { get; private set; } MVSDK_Net.MyCamera mvCameraAcq; public UInt32 ImageWidth { get; private set; } public UInt32 ImageHeight { 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; } /// /// 采集用时 /// public TimeSpan TotalTime { get; private set; } /// /// 错误信息 /// public string ErrorMessage { get; private set; } private bool IsHaveCamera = false; #endregion #region 事件 public event Action ImageCallbackEvent; public event Action CameraConnectChangedEvent; #endregion public AHuaCamera(Guid id, int index, string name, string serialNumber, string cameraip, bool isFindByIp) { ID = id; Name = serialNumber; Index = index; CameraIp = cameraip; SerialNumber = serialNumber; IsFindByIp = isFindByIp; mvCameraAcq = new MVSDK_Net.MyCamera(); var list = GetDevices(); foreach (var device in list) { if (device.CameraType == CameraType.GIGE) { if (IsFindByIp) { if (device.CameraIp == CameraIp) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, serialNumber); if (res == IMVDefine.IMV_OK) { } break; } } else { if (device.SerialNumber == serialNumber) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; CameraIp = device.CameraIp; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, serialNumber); if (res == IMVDefine.IMV_OK) { } break; } } } else { if (device.SerialNumber == serialNumber) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, serialNumber); if (res == IMVDefine.IMV_OK) { } break; } } } IsConnected = false; } #region 方法 /// /// 获取设备 /// /// public static CameraInfo[] GetDevices() { List cameras = new List(); if (!CheckSoftwareInstalled().isInstalled) { LogHelper.WriteLogInfo("未安装MV Viewer"); return cameras.ToArray(); } // 设备搜索 // device search IMVDefine.IMV_DeviceList deviceList = new IMVDefine.IMV_DeviceList(); IMVDefine.IMV_EInterfaceType interfaceTp = IMVDefine.IMV_EInterfaceType.interfaceTypeAll; int res = MyCamera.IMV_EnumDevices(ref deviceList, (uint)interfaceTp); // 添加设备信息 // Add device info if (res == IMVDefine.IMV_OK && deviceList.nDevNum > 0) { for (int i = 0; i < deviceList.nDevNum; i++) { IMVDefine.IMV_DeviceInfo deviceInfo = (IMVDefine.IMV_DeviceInfo) Marshal.PtrToStructure( deviceList.pDevInfo + Marshal.SizeOf(typeof(IMVDefine.IMV_DeviceInfo)) * i, typeof(IMVDefine.IMV_DeviceInfo)); if (deviceInfo.nCameraType == IMV_ECameraType.typeGigeCamera) { IMVDefine.IMV_GigEDeviceInfo gigEDeviceInfo = (IMVDefine.IMV_GigEDeviceInfo) ByteToStruct(deviceInfo.deviceSpecificInfo.gigeDeviceInfo, typeof(IMVDefine.IMV_GigEDeviceInfo)); cameras.Add(new Models.CameraInfo() { CameraNo = i + 1, CameraName = deviceInfo.cameraName, CameraBrand = CameraBrand.IRayple, CameraType = CameraType.GIGE, ManufacturerName = deviceInfo.manufactureInfo, Model = deviceInfo.modelName, SerialNumber = deviceInfo.serialNumber, CameraIp = gigEDeviceInfo.ipAddress, IsFindByIp = true, }); } else if (deviceInfo.nCameraType == IMV_ECameraType.typeU3vCamera) { cameras.Add(new Models.CameraInfo() { CameraNo = i + 1, CameraName = deviceInfo.cameraName, CameraBrand = CameraBrand.IRayple, CameraType = CameraType.USB, ManufacturerName = deviceInfo.cameraName, Model = deviceInfo.modelName, SerialNumber = deviceInfo.serialNumber, CameraIp = "", }); } else if (deviceInfo.nCameraType == IMV_ECameraType.typeCLCamera) { cameras.Add(new Models.CameraInfo() { CameraNo = i + 1, CameraName = deviceInfo.cameraName, CameraBrand = CameraBrand.IRayple, CameraType = CameraType.Link, ManufacturerName = deviceInfo.cameraName, Model = deviceInfo.modelName, SerialNumber = deviceInfo.serialNumber, CameraIp = "", }); } else { cameras.Add(new Models.CameraInfo() { CameraNo = i + 1, CameraName = deviceInfo.cameraName, CameraBrand = CameraBrand.IRayple, CameraType = CameraType.Unknown, ManufacturerName = deviceInfo.cameraName, Model = deviceInfo.modelName, SerialNumber = deviceInfo.serialNumber, CameraIp = "", }); } } } return cameras.ToArray(); } /// /// 检查相机软件是否安装 /// /// public static (bool isInstalled, string version) CheckSoftwareInstalled() { string softwareName = "MV Viewer"; string softwareVersion = "2.5.1.1"; 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(); var match = Regex.Match(version, @"^(\d+\.\d+\.\d+\.\d+)"); if (match.Success) { version = match.Groups[1].Value; } else { continue; } 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() { EnterOperation(); try { IsConnected = false; //if (!IsHaveCamera) //{ var list = GetDevices(); foreach (var device in list) { if (device.CameraType == CameraType.GIGE) { if (IsFindByIp) { if (device.CameraIp == CameraIp) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, SerialNumber); if (res == IMVDefine.IMV_OK) { } break; } } else { if (device.SerialNumber == SerialNumber) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; CameraIp = device.CameraIp; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, SerialNumber); if (res == IMVDefine.IMV_OK) { } break; } } } else { if (device.SerialNumber == SerialNumber) { IsHaveCamera = true; ManufacturerName = device.ManufacturerName; ModelName = device.Model; SerialNumber = device.SerialNumber; CameraType = device.CameraType; int res = mvCameraAcq.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByCameraKey, 0, SerialNumber); if (res == IMVDefine.IMV_OK) { } break; } } } if (!IsHaveCamera) { //throw new Exception("没有发现相机"); return false; } //} // 打开设备 // open device int res1 = mvCameraAcq.IMV_Open(); if (res1 != IMVDefine.IMV_OK) { return IsConnected; } if (!IsConnected) { CameraConnectChangedEvent?.Invoke(ID, true); } long width = 0; long height = 0; // 获取宽 // Get Width res1 = mvCameraAcq.IMV_GetIntFeatureValue("Width", ref width); if (res1 != IMVDefine.IMV_OK) { //MessageBox.Show("Get Width failed"); } // 获取高 // Get Height res1 = mvCameraAcq.IMV_GetIntFeatureValue("Height", ref height); if (res1 != IMVDefine.IMV_OK) { //MessageBox.Show("Get Height failed"); } ImageWidth = (uint)width; ImageHeight = (uint)height; m_picSize = width * height; res1 = mvCameraAcq.IMV_SetEnumFeatureSymbol("AcquisitionMode", "Continuous"); if (res1 != IMVDefine.IMV_OK) { //MessageBox.Show("Set AcquisitionMode failed"); } // 关闭触发模式 // set trigger mode as off res1 = mvCameraAcq.IMV_SetEnumFeatureSymbol("TriggerMode", "Off"); if (res1 != IMVDefine.IMV_OK) { //MessageBox.Show("Set TriggerMode failed"); } // 开启码流 // start grabbing res1 = mvCameraAcq.IMV_StartGrabbing(); if (res1 != IMVDefine.IMV_OK) { //MessageBox.Show("Start grabbing failed!"); } IsConnected = mvCameraAcq.IMV_IsOpen(); return IsConnected; } finally { ExitOperation(); } } /// /// 打开相机异步 /// /// public Task OpenDeviceAsync() { return Task.Run(() => { return OpenDevice(); }); } /// /// 关闭相机 /// public void CloseDevice() { EnterOperation(); try { if (mvCameraAcq.IMV_IsOpen()) { // ch:关闭设备 | en:Close Device mvCameraAcq.IMV_Close(); mvCameraAcq.IMV_DestroyHandle(); } } finally { ExitOperation(); } } private long m_picSize = 0; IMVDefine.IMV_Frame frame = new IMVDefine.IMV_Frame(); IntPtr pTemp = IntPtr.Zero; IntPtr pConvertDstBuffer = IntPtr.Zero; int nConvertBufSize = 0; private IMVDefine.IMV_PixelConvertParam stPixelConvertParam = new IMVDefine.IMV_PixelConvertParam(); private IMVDefine.IMV_EPixelType type = IMVDefine.IMV_EPixelType.gvspPixelMono8; /// /// 采集图像 /// /// public ICogImage Grab(bool isRealtime = true) { EnterOperation(); try { Byte[] byteArrImageData = new Byte[m_picSize * 3]; Stopwatch sw = Stopwatch.StartNew(); int res = IMVDefine.IMV_OK; for (int i = 0; i < 5; i++) { try { if (!mvCameraAcq.IMV_IsOpen()) { OpenDevice(); } mvCameraAcq.IMV_ClearFrameBuffer(); res = mvCameraAcq.IMV_GetFrame(ref frame, 1000); if (res == IMVDefine.IMV_OK) { try { // Mono图像处理 if (IsMonoPixelFormat(frame.frameInfo.pixelFormat)) { type = IMVDefine.IMV_EPixelType.gvspPixelMono8; if (frame.frameInfo.pixelFormat == IMVDefine.IMV_EPixelType.gvspPixelMono8) { pTemp = frame.pData; } else { if (pConvertDstBuffer == IntPtr.Zero || nConvertBufSize < (frame.frameInfo.width * frame.frameInfo.height)) { if (pConvertDstBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertDstBuffer); pConvertDstBuffer = IntPtr.Zero; } pConvertDstBuffer = Marshal.AllocHGlobal((int)(frame.frameInfo.width * frame.frameInfo.height)); if (pConvertDstBuffer == IntPtr.Zero) { break; } nConvertBufSize = (int)(frame.frameInfo.width * frame.frameInfo.height); } // 其他格式Mono转为Mono8 stPixelConvertParam.nWidth = frame.frameInfo.width; stPixelConvertParam.nHeight = frame.frameInfo.height; stPixelConvertParam.ePixelFormat = frame.frameInfo.pixelFormat; stPixelConvertParam.pSrcData = frame.pData; stPixelConvertParam.nSrcDataLen = frame.frameInfo.size; stPixelConvertParam.nPaddingX = frame.frameInfo.paddingX; stPixelConvertParam.nPaddingY = frame.frameInfo.paddingY; stPixelConvertParam.eBayerDemosaic = IMVDefine.IMV_EBayerDemosaic.demosaicNearestNeighbor; stPixelConvertParam.eDstPixelFormat = IMVDefine.IMV_EPixelType.gvspPixelMono8; stPixelConvertParam.pDstBuf = pConvertDstBuffer; stPixelConvertParam.nDstBufSize = frame.frameInfo.width * frame.frameInfo.height; res = mvCameraAcq.IMV_PixelConvert(ref stPixelConvertParam); if (res != IMVDefine.IMV_OK) { break; } pTemp = pConvertDstBuffer; } } // 彩色图像处理 else if (IsColorPixelFormat(frame.frameInfo.pixelFormat)) { type = IMVDefine.IMV_EPixelType.gvspPixelRGB8; if (frame.frameInfo.pixelFormat == IMVDefine.IMV_EPixelType.gvspPixelRGB8) { pTemp = frame.pData; } else { if (pConvertDstBuffer == IntPtr.Zero || nConvertBufSize < (frame.frameInfo.width * frame.frameInfo.height * 3)) { if (pConvertDstBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertDstBuffer); pConvertDstBuffer = IntPtr.Zero; } pConvertDstBuffer = Marshal.AllocHGlobal((int)(frame.frameInfo.width * frame.frameInfo.height * 3)); if (pConvertDstBuffer == IntPtr.Zero) { break; } nConvertBufSize = (int)(frame.frameInfo.width * frame.frameInfo.height * 3); } // 其他格式彩色图像转为RGB stPixelConvertParam.nWidth = frame.frameInfo.width; stPixelConvertParam.nHeight = frame.frameInfo.height; stPixelConvertParam.ePixelFormat = frame.frameInfo.pixelFormat; stPixelConvertParam.pSrcData = frame.pData; stPixelConvertParam.nSrcDataLen = frame.frameInfo.size; stPixelConvertParam.nPaddingX = frame.frameInfo.paddingX; stPixelConvertParam.nPaddingY = frame.frameInfo.paddingY; stPixelConvertParam.eBayerDemosaic = IMVDefine.IMV_EBayerDemosaic.demosaicNearestNeighbor; stPixelConvertParam.eDstPixelFormat = IMVDefine.IMV_EPixelType.gvspPixelRGB8; stPixelConvertParam.pDstBuf = pConvertDstBuffer; stPixelConvertParam.nDstBufSize = frame.frameInfo.width * frame.frameInfo.height * 3; res = mvCameraAcq.IMV_PixelConvert(ref stPixelConvertParam); if (res != IMVDefine.IMV_OK) { break; } pTemp = pConvertDstBuffer; } unsafe { byte* pBufForSaveImage = (byte*)pTemp; UInt32 nSupWidth = (uint)((frame.frameInfo.width + (UInt32)3) & 0xfffffffc); for (int nRow = 0; nRow < frame.frameInfo.height; nRow++) { for (int col = 0; col < frame.frameInfo.width; col++) { byteArrImageData[nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col)]; byteArrImageData[frame.frameInfo.width * frame.frameInfo.height + nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col + 1)]; byteArrImageData[frame.frameInfo.width * frame.frameInfo.height * 2 + nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col + 2)]; } } pTemp = Marshal.UnsafeAddrOfPinnedArrayElement(byteArrImageData, 0); } } else { continue; } Image = ConvertImage(frame.frameInfo.width, frame.frameInfo.height, pTemp, type); if (Image != null) { ErrorMessage = ""; TotalTime = sw.Elapsed; return Image; } } catch (Exception) { } finally { // 释放帧数据 // release frame mvCameraAcq.IMV_ReleaseFrame(ref frame); } } else { ErrorMessage = res.ToString(); CloseDevice(); OpenDevice(); } } catch (Exception ex) { CloseDevice(); OpenDevice(); ErrorMessage = ex.Message; } } if (IsConnected) { IsConnected = false; CameraConnectChangedEvent?.Invoke(ID, false); } return null; } finally { ExitOperation(); } } /// /// 采集图像 /// /// public ICogImage Grab2(bool isRealtime = true) { EnterOperation(); try { Byte[] byteArrImageData = new Byte[m_picSize * 3]; Stopwatch sw = Stopwatch.StartNew(); int res = IMVDefine.IMV_OK; for (int i = 0; i < 5; i++) { try { if (!mvCameraAcq.IMV_IsOpen()) { OpenDevice(); } mvCameraAcq.IMV_ClearFrameBuffer(); res = mvCameraAcq.IMV_GetFrame(ref frame, 1000); if (res == IMVDefine.IMV_OK) { try { // Mono图像处理 if (IsMonoPixelFormat(frame.frameInfo.pixelFormat)) { type = IMVDefine.IMV_EPixelType.gvspPixelMono8; if (frame.frameInfo.pixelFormat == IMVDefine.IMV_EPixelType.gvspPixelMono8) { pTemp = frame.pData; } else { if (pConvertDstBuffer == IntPtr.Zero || nConvertBufSize < (frame.frameInfo.width * frame.frameInfo.height)) { if (pConvertDstBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertDstBuffer); pConvertDstBuffer = IntPtr.Zero; } pConvertDstBuffer = Marshal.AllocHGlobal((int)(frame.frameInfo.width * frame.frameInfo.height)); if (pConvertDstBuffer == IntPtr.Zero) { break; } nConvertBufSize = (int)(frame.frameInfo.width * frame.frameInfo.height); } // 其他格式Mono转为Mono8 stPixelConvertParam.nWidth = frame.frameInfo.width; stPixelConvertParam.nHeight = frame.frameInfo.height; stPixelConvertParam.ePixelFormat = frame.frameInfo.pixelFormat; stPixelConvertParam.pSrcData = frame.pData; stPixelConvertParam.nSrcDataLen = frame.frameInfo.size; stPixelConvertParam.nPaddingX = frame.frameInfo.paddingX; stPixelConvertParam.nPaddingY = frame.frameInfo.paddingY; stPixelConvertParam.eBayerDemosaic = IMVDefine.IMV_EBayerDemosaic.demosaicNearestNeighbor; stPixelConvertParam.eDstPixelFormat = IMVDefine.IMV_EPixelType.gvspPixelMono8; stPixelConvertParam.pDstBuf = pConvertDstBuffer; stPixelConvertParam.nDstBufSize = frame.frameInfo.width * frame.frameInfo.height; res = mvCameraAcq.IMV_PixelConvert(ref stPixelConvertParam); if (res != IMVDefine.IMV_OK) { break; } pTemp = pConvertDstBuffer; } } // 彩色图像处理 else if (IsColorPixelFormat(frame.frameInfo.pixelFormat)) { type = IMVDefine.IMV_EPixelType.gvspPixelRGB8; if (frame.frameInfo.pixelFormat == IMVDefine.IMV_EPixelType.gvspPixelRGB8) { pTemp = frame.pData; } else { if (pConvertDstBuffer == IntPtr.Zero || nConvertBufSize < (frame.frameInfo.width * frame.frameInfo.height * 3)) { if (pConvertDstBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pConvertDstBuffer); pConvertDstBuffer = IntPtr.Zero; } pConvertDstBuffer = Marshal.AllocHGlobal((int)(frame.frameInfo.width * frame.frameInfo.height * 3)); if (pConvertDstBuffer == IntPtr.Zero) { break; } nConvertBufSize = (int)(frame.frameInfo.width * frame.frameInfo.height * 3); } // 其他格式彩色图像转为RGB stPixelConvertParam.nWidth = frame.frameInfo.width; stPixelConvertParam.nHeight = frame.frameInfo.height; stPixelConvertParam.ePixelFormat = frame.frameInfo.pixelFormat; stPixelConvertParam.pSrcData = frame.pData; stPixelConvertParam.nSrcDataLen = frame.frameInfo.size; stPixelConvertParam.nPaddingX = frame.frameInfo.paddingX; stPixelConvertParam.nPaddingY = frame.frameInfo.paddingY; stPixelConvertParam.eBayerDemosaic = IMVDefine.IMV_EBayerDemosaic.demosaicNearestNeighbor; stPixelConvertParam.eDstPixelFormat = IMVDefine.IMV_EPixelType.gvspPixelRGB8; stPixelConvertParam.pDstBuf = pConvertDstBuffer; stPixelConvertParam.nDstBufSize = frame.frameInfo.width * frame.frameInfo.height * 3; res = mvCameraAcq.IMV_PixelConvert(ref stPixelConvertParam); if (res != IMVDefine.IMV_OK) { break; } pTemp = pConvertDstBuffer; } unsafe { byte* pBufForSaveImage = (byte*)pTemp; UInt32 nSupWidth = (uint)((frame.frameInfo.width + (UInt32)3) & 0xfffffffc); for (int nRow = 0; nRow < frame.frameInfo.height; nRow++) { for (int col = 0; col < frame.frameInfo.width; col++) { byteArrImageData[nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col)]; byteArrImageData[frame.frameInfo.width * frame.frameInfo.height + nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col + 1)]; byteArrImageData[frame.frameInfo.width * frame.frameInfo.height * 2 + nRow * nSupWidth + col] = pBufForSaveImage[nRow * frame.frameInfo.width * 3 + (3 * col + 2)]; } } pTemp = Marshal.UnsafeAddrOfPinnedArrayElement(byteArrImageData, 0); } } else { continue; } Image = ConvertImage(frame.frameInfo.width, frame.frameInfo.height, pTemp, type); if (Image != null) { ErrorMessage = ""; TotalTime = sw.Elapsed; return Image; } } catch (Exception) { } finally { // 释放帧数据 // release frame mvCameraAcq.IMV_ReleaseFrame(ref frame); } } else { ErrorMessage = res.ToString(); CloseDevice(); OpenDevice(); } } catch (Exception ex) { CloseDevice(); OpenDevice(); ErrorMessage = ex.Message; } } if (IsConnected) { IsConnected = false; CameraConnectChangedEvent?.Invoke(ID, false); } return null; } finally { ExitOperation(); } } /// /// 开始采集图像 /// public void StartGrabbing() { lock (_stateLock) { if (IsGrabbing) return; IsGrabbing = true; } m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true }; m_hReceiveThread.Start(); } /// /// 停止采集图像 /// public void StopGrabbing() { try { lock (_stateLock) { IsGrabbing = false; } Thread.Sleep(1000); if (m_hReceiveThread != null) { m_hReceiveThread.Abort(); m_hReceiveThread = null; } } catch (Exception) { } } /// /// 设置曝光时间 /// /// /// public bool SetExposureTime(float ExposureTime) { if (!mvCameraAcq.IMV_IsOpen()) return false; if (GetExposureTime() != ExposureTime) { bool success = false; for (int i = 0; i < 5; i++) { int res = mvCameraAcq.IMV_SetDoubleFeatureValue("ExposureTime", (double)ExposureTime); if (IMVDefine.IMV_OK == res) { success = true; Thread.Sleep(100); break; } } return success; } return true; } /// /// 获取曝光时间 /// /// public float GetExposureTime() { if (!mvCameraAcq.IMV_IsOpen()) return 0; // 获取曝光值 // set ExposureTime double exposureTime = 0; int res = mvCameraAcq.IMV_GetDoubleFeatureValue("ExposureTime", ref exposureTime); if (IMVDefine.IMV_OK != res) { return 0; } return (float)exposureTime; } /// /// 设置增益 /// /// /// public bool SetGain(float Gain) { if (!mvCameraAcq.IMV_IsOpen()) return false; if (GetGain() != Gain) { // 设置增益 // set Gain bool success = false; for (int i = 0; i < 5; i++) { int res = mvCameraAcq.IMV_SetDoubleFeatureValue("GainRaw", (double)Gain); if (IMVDefine.IMV_OK == res) { success = true; break; } } return success; } return true; } /// /// 获取增益 /// /// public float GetGain() { if (!mvCameraAcq.IMV_IsOpen()) return 0; // 获取增益 double gain = 0; int res = mvCameraAcq.IMV_GetDoubleFeatureValue("GainRaw", ref gain); if (IMVDefine.IMV_OK != res) { return 0; } return (float)gain; } private void GetStreamThreadProc() { while (IsGrabbing) { try { Grab(); ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage, ID); } catch (Exception) { } Thread.Sleep(10); } IsGrabbing = false; } /// /// 图像是否为Mono格式 /// /// /// private bool IsMonoPixelFormat(IMVDefine.IMV_EPixelType enType) { switch (enType) { case IMVDefine.IMV_EPixelType.gvspPixelMono8: case IMVDefine.IMV_EPixelType.gvspPixelMono10: case IMVDefine.IMV_EPixelType.gvspPixelMono10Packed: case IMVDefine.IMV_EPixelType.gvspPixelMono12: case IMVDefine.IMV_EPixelType.gvspPixelMono12Packed: return true; default: return false; } } /// /// 图像是否为彩色 /// /// /// private bool IsColorPixelFormat(IMVDefine.IMV_EPixelType enType) { switch (enType) { case IMVDefine.IMV_EPixelType.gvspPixelRGB8: case IMVDefine.IMV_EPixelType.gvspPixelBGR8: case IMVDefine.IMV_EPixelType.gvspPixelRGBA8: case IMVDefine.IMV_EPixelType.gvspPixelBGRA8: case IMVDefine.IMV_EPixelType.gvspPixelYUV422_8: case IMVDefine.IMV_EPixelType.gvspPixelYUV422_8_UYVY: case IMVDefine.IMV_EPixelType.gvspPixelBayGR8: case IMVDefine.IMV_EPixelType.gvspPixelBayRG8: case IMVDefine.IMV_EPixelType.gvspPixelBayGB8: case IMVDefine.IMV_EPixelType.gvspPixelBayBG8: case IMVDefine.IMV_EPixelType.gvspPixelBayGB10: case IMVDefine.IMV_EPixelType.gvspPixelBayGB10Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayBG10: case IMVDefine.IMV_EPixelType.gvspPixelBayBG10Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayRG10: case IMVDefine.IMV_EPixelType.gvspPixelBayRG10Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayGR10: case IMVDefine.IMV_EPixelType.gvspPixelBayGR10Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayGB12: case IMVDefine.IMV_EPixelType.gvspPixelBayGB12Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayBG12: case IMVDefine.IMV_EPixelType.gvspPixelBayBG12Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayRG12: case IMVDefine.IMV_EPixelType.gvspPixelBayRG12Packed: case IMVDefine.IMV_EPixelType.gvspPixelBayGR12: case IMVDefine.IMV_EPixelType.gvspPixelBayGR12Packed: return true; default: return false; } } /// /// 转换图片 /// /// 高 /// 宽 /// 图片数据 /// 像素格式 public ICogImage ConvertImage(UInt32 nWidth, UInt32 nHeight, IntPtr pImageBuf, IMVDefine.IMV_EPixelType enPixelType) { try { if (enPixelType == IMVDefine.IMV_EPixelType.gvspPixelMono8) { CogImage8Root cogImage8Root = new CogImage8Root(); cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null); CogImage8Grey cogImage8Grey = new CogImage8Grey(); cogImage8Grey.SetRoot(cogImage8Root); var image = cogImage8Grey.ScaleImage((int)nWidth, (int)nHeight); System.GC.Collect(); return image; } 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_picSize); image1.Initialize((int)nWidth, (int)nHeight, ptr1, (int)nWidth, null); CogImage8Root image2 = new CogImage8Root(); IntPtr ptr2 = new IntPtr(pImageBuf.ToInt64() + m_picSize * 2); image2.Initialize((int)nWidth, (int)nHeight, ptr2, (int)nWidth, null); CogImage24PlanarColor colorImage = new CogImage24PlanarColor(); colorImage.SetRoots(image0, image1, image2); var image = colorImage.ScaleImage((int)nWidth, (int)nHeight); System.GC.Collect(); return image; } } catch (System.Exception) { return null; } } public static object ByteToStruct(Byte[] bytes, Type type) { int size = Marshal.SizeOf(type); if (size > bytes.Length) { return null; } // 分配结构体内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); // 将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); // 将内存空间转换为目标结构体 object obj = Marshal.PtrToStructure(structPtr, type); // 释放内存空间 Marshal.FreeHGlobal(structPtr); return obj; } #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 } }