using System.Collections.Concurrent; using System.Diagnostics; using System.Reflection.Metadata; using System.Xml.Linq; using DH.Commons.Base; using DH.Commons.Enums; using DH.Commons.Helper; using DVPCameraType; using OpenCvSharp; using OpenCvSharp.Extensions; using static System.Net.Mime.MediaTypeNames; using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel; namespace DH.Devices.Camera { public class Do3ThinkCamera : CameraBase, ILogger { private dvpCameraInfo stDevInfo = new dvpCameraInfo(); private dvpStatus nRet = dvpStatus.DVP_STATUS_OK; private DVPCamera.dvpEventCallback pCallBackFunc; private uint m_handle; public int m_n_dev_count = 0; private DVPCamera.dvpStreamCallback ImageCallback; public dvpStreamFormat dvpStreamFormat = dvpStreamFormat.S_RGB24; public int m_CamCount = 0; public Double m_dfDisplayCount = 0; public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper(); public event Action OnLog; public ConcurrentDictionary _imageSetList = new ConcurrentDictionary(); public Do3ThinkCamera() { LoggerHelper.LogPath = "D://"; LoggerHelper.LogPrefix = CameraName; } public bool IsValidHandle(uint handle) { bool bValidHandle = false; dvpStatus status = DVPCamera.dvpIsValid(handle, ref bValidHandle); if (status == dvpStatus.DVP_STATUS_OK) { return bValidHandle; } return false; } public override bool CameraConnect() { try { nRet = DVPCamera.dvpOpenByUserId(CameraName, dvpOpenMode.OPEN_NORMAL, ref m_handle); // ch:打开设备 | en:Open device if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception($"Create device failed:{nRet:x8}"); } nRet = DVPCamera.dvpSetTargetFormat(m_handle, (dvpStreamFormat)dvpStreamFormat); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception($"Set image format failed:{nRet:x8}"); } dvpCameraInfo camerainfo = new dvpCameraInfo(); nRet = DVPCamera.dvpGetCameraInfo(m_handle, ref camerainfo); SerialNumber = camerainfo.SerialNumber; // ch:注册异常回调函数 | en:Register Exception Callback //nRet = DVPCamera.dvpRegisterEventCallback(m_handle, pCallBackFunc, dvpEvent.EVENT_DISCONNECTED, IntPtr.Zero); //if (nRet != dvpStatus.DVP_STATUS_OK) //{ // throw new Exception($"Register expection callback failed:{nRet}"); //} //GC.KeepAlive(pCallBackFunc); //// ch:设置采集连续模式 | en:Set Continues Aquisition Mode if (IsContinueMode) { // ch:设置触发模式为off || en:set trigger mode as off nRet = DVPCamera.dvpSetTriggerState(m_handle, false); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception("Set TriggerMode failed!"); } } else { // ch:设置触发模式为on || en:set trigger mode as on nRet = DVPCamera.dvpSetTriggerState(m_handle, true); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception("Set TriggerMode failed!"); } // 硬触发 if (IsHardwareTrigger) { // ch:触发源选择:1 - Line1; | en:Trigger source select:1 - Line1; nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_LINE1); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception("Set Line1 Trigger failed!"); } // ch:注册回调函数 | en:Register image callback ImageCallback = new DVPCamera.dvpStreamCallback(ImageCallbackFunc); nRet = DVPCamera.dvpRegisterStreamCallback(m_handle, ImageCallback, dvpStreamEvent.STREAM_EVENT_PROCESSED, IntPtr.Zero); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception("Register image callback failed!"); } } else // 软触发 { nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_SOFTWARE); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception("Set Software Trigger failed!"); } } // ch:开启抓图 || en: start grab image nRet = DVPCamera.dvpStart(m_handle); if (dvpStatus.DVP_STATUS_OK != nRet) { throw new Exception($"Start grabbing failed:{nRet:x8}"); } //// 曝光 if (Exposure != 0) { SetExposure(Exposure); } //// 增益 if (Gain >= 0) { SetGain(Gain); } //全画幅 if(!IsAllPicEnabled) SetPictureRoi((int)ROIX, (int)ROIY, (int)ROIW, (int)ROIH); //// 设置 触发延迟 if (TriggerDelay > 0) { nRet = DVPCamera.dvpSetTriggerDelay(m_handle, TriggerDelay); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception("Set TriggerDelay failed!"); } } //// 信号消抖 if (LineDebouncerTime > 0) { nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, LineDebouncerTime); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"LineDebouncerTime set failed:{nRet}"); } } //IIConfig.PropertyChanged -= IIConfig_PropertyChanged; //IIConfig.PropertyChanged += IIConfig_PropertyChanged; } return true; } catch { return false; } } private void IIConfig_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { //if (e.PropertyName == "IsHardwareTrigger" && !IIConfig.IsContinueMode) //{ // // ch:停止抓图 | en:Stop grab image // nRet = DVPCamera.dvpStop(m_handle); // if (nRet != dvpStatus.DVP_STATUS_OK) // { // throw new Exception($"Stop grabbing failed{nRet:x8}"); // } // // 硬触发 // if (IIConfig.IsHardwareTrigger) // { // // ch:触发源选择:1 - Line1; | en:Trigger source select:1 - Line1; // nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_LINE1); // if (dvpStatus.DVP_STATUS_OK != nRet) // { // throw new Exception("Set Line1 Trigger failed!"); // } // // ch:注册回调函数 | en:Register image callback // ImageCallback = new DVPCamera.dvpStreamCallback(ImageCallbackFunc); // nRet = DVPCamera.dvpRegisterStreamCallback(m_handle, ImageCallback, dvpStreamEvent.STREAM_EVENT_PROCESSED, IntPtr.Zero); // if (dvpStatus.DVP_STATUS_OK != nRet) // { // throw new Exception("Register image callback failed!"); // } // } // else // 软触发 // { // nRet = DVPCamera.dvpSetTriggerSource(m_handle, dvpTriggerSource.TRIGGER_SOURCE_SOFTWARE); // if (dvpStatus.DVP_STATUS_OK != nRet) // { // throw new Exception("Set Software Trigger failed!"); // } // } // // ch:开启抓图 || en: start grab image // nRet = DVPCamera.dvpStart(m_handle); // if (dvpStatus.DVP_STATUS_OK != nRet) // { // throw new Exception($"Start grabbing failed:{nRet:x8}"); // } // // 曝光 // if (IIConfig.DefaultExposure != 0) // { // SetExposure(IIConfig.DefaultExposure); // } // // 增益 // if (IIConfig.Gain >= 0) // { // SetGain(IIConfig.Gain); // } // // 设置 触发延迟 // if (IIConfig.TriggerDelay > 0) // { // nRet = DVPCamera.dvpSetTriggerDelay(m_handle, IIConfig.TriggerDelay); // if (nRet != dvpStatus.DVP_STATUS_OK) // { // throw new Exception("Set TriggerDelay failed!"); // } // } // // 信号消抖 // if (IIConfig.LineDebouncerTime > 0) // { // nRet = DVPCamera.dvpSetTriggerJitterFilter(m_handle, IIConfig.LineDebouncerTime); // if (nRet != dvpStatus.DVP_STATUS_OK) // { // throw new Exception($"LineDebouncerTime set failed:{nRet}"); // } // } //} } /// /// 设置曝光值 /// /// 曝光值 /// private void SetExposure(double exposure) { // 关闭自动曝光 nRet = DVPCamera.dvpSetAeOperation(m_handle, dvpAeOperation.AE_OP_OFF); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Exposure set failed:{nRet}"); } // 设置曝光值 nRet = DVPCamera.dvpSetExposure(m_handle, exposure); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Exposure set failed:{nRet}"); } } /// /// 设置增益 /// /// /// private void SetGain(float gain) { // 设置增益 nRet = DVPCamera.dvpSetAnalogGain(m_handle, gain); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Gain set failed:{nRet}"); } } private void SetPictureRoi(int x, int y, int W, int H) { dvpRegion dvpR = new dvpRegion(); dvpR.X = x; dvpR.Y = y; dvpR.W = W; dvpR.H = H; // 设置增益 nRet = DVPCamera.dvpSetRoi(m_handle, dvpR); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"SetRoi set failed:{nRet}"); } } public int ImageCallbackFunc(uint handle, dvpStreamEvent _event, IntPtr pContext, ref dvpFrame refFrame, IntPtr pBuffer) { Mat cvImage = new Mat(); if (this.CameraName.Equals("Cam1")) { Console.WriteLine( ); } if (this.CameraName.Equals("Cam2")) { Console.WriteLine(); } try { Interlocked.Increment(ref SnapshotCount); int nWidth = refFrame.iWidth; int nHeight = refFrame.iHeight; // 根据图像格式创建Mat switch (refFrame.format) { case dvpImageFormat.FORMAT_RGB24: cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC3, pBuffer); Cv2.CvtColor(cvImage, cvImage, ColorConversionCodes.RGB2BGR); break; case dvpImageFormat.FORMAT_BGR24: cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC3, pBuffer); break; case dvpImageFormat.FORMAT_MONO: cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC1, pBuffer); break; default: cvImage = Mat.FromPixelData(nHeight, nWidth, MatType.CV_8UC1, pBuffer); break; } Mat smat = cvImage.Clone(); var imageSet = new MatSet { _mat = smat, }; InitialImageSet(imageSet); OnHImageOutput?.Invoke(DateTime.Now, this, smat); //存图 DisplayAndSaveOriginImage(imageSet.Id,SnapshotCount); } catch (Exception ex) { } finally { cvImage?.Dispose(); } return 0; } public void InitialImageSet(MatSet set) { //if (saveOption != null) //{ // set.ImageSaveOption = saveOption.Copy(); //} //set.IsOriginSaved = !set.ImageSaveOption.IsSaveOriginImage; //set.IsFitSaved = !set.ImageSaveOption.IsSaveFitImage; //set.IsAddtionalSaved = string.IsNullOrWhiteSpace(set.ImageSaveOption.AddtionalSaveType); set.CameraId = this.CameraName; set.ImageTime = DateTime.Now; _imageSetList[set.Id] = set; } public virtual async void DisplayAndSaveOriginImage(string imgSetId, int _counter) { MatSet set = _imageSetList.Values.FirstOrDefault(u => u.Id == imgSetId); if (set != null && set._mat != null) { await Task.Run(() => { Bitmap showImage = set._mat.ToBitmap(); // showImage.Save("D:/test333.bmp"); // Marshal.Copy(pbyteImageBuffer, 0, (IntPtr)lAddrImage, (int)dwBufferSize); // Bitmap saveImage = showImage?.CopyBitmap(); // saveImage.Save("d://TEST444.BMP"); // OnShowImageUpdated?.Invoke(this, showImage, imgSetId); if (IsSavePicEnabled) { string fullname = Path.Combine(ImageSaveDirectory, $"{CameraName}_{_counter:D7}_{set.Id}.{set._imageFormat.ToString().ToLower()}"); ImageSaveAsync(fullname, showImage); } //释放 himage ClearImageSet(set); }); } } static object _imageSetLock = new object(); public void ClearImageSet(MatSet set) { try { bool flag = false; lock (_imageSetLock) { flag = _imageSetList.TryRemove(set.Id, out set); if (flag) { set.Dispose(); } //LogAsync(DateTime.Now, $"{Name}移除图片信息{(flag ? "成功" : "失败")},当前缓存数量:{_imageSetList.Count}", ""); } } catch (Exception ex) { LogAsync(DateTime.Now, LogLevel.Exception, $"清理图片缓存异常,当前缓存数量{_imageSetList.Count},{ex.GetExceptionMessage()}"); } } public ImageSaveHelper ImageSaveHelper { get; set; } = new ImageSaveHelper(); public virtual void ImageSaveAsync(string fullName, Bitmap map) { if (!IsSavePicEnabled) { map?.Dispose(); return; } ImageSaveSet imageSaveSet = new ImageSaveSet() { FullName = fullName, SaveImage = map, }; ImageSaveHelper.ImageSaveAsync(imageSaveSet); } public override bool CameraDisConnect() { try { dvpStreamState StreamState = new dvpStreamState(); nRet = DVPCamera.dvpGetStreamState(m_handle, ref StreamState); //Debug.Assert(nRet == dvpStatus.DVP_STATUS_OK); if (StreamState == dvpStreamState.STATE_STARTED) { // stop camera nRet = DVPCamera.dvpStop(m_handle); Debug.Assert(nRet == dvpStatus.DVP_STATUS_OK); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Stop grabbing failed{nRet:x8}"); } } nRet = DVPCamera.dvpUnregisterEventCallback(m_handle, pCallBackFunc, dvpEvent.EVENT_DISCONNECTED, IntPtr.Zero); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Unregister expection callback failed:{nRet}"); } // ch:关闭设备 | en:Close device nRet = DVPCamera.dvpClose(m_handle); if (nRet != dvpStatus.DVP_STATUS_OK) { throw new Exception($"Close device failed{nRet:x8}"); } m_handle = 0; return true; } catch { return false; } } public void LogAsync(LogMsg msg) { msg.MsgSource = CameraName; msg.ThreadId = Thread.CurrentThread.ManagedThreadId; //OnLog?.BeginInvoke(msg, null, null); OnLog?.Invoke(msg); //if (InitialConfig.IsEnableLog) { LoggerHelper.LogAsync(msg); } } public void LogAsync(DateTime dt, LogLevel logLevel, string msg) { LogAsync(new LogMsg(dt, logLevel, msg)); } } }