using MvCamCtrl.NET; using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace YSDetection { public class HikCamera { [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST(); int nRet = MyCamera.MV_OK; MyCamera.cbExceptiondelegate pCallBackFunc; private MyCamera device = new MyCamera(); bool m_bGrabbing = false; Thread m_hReceiveThread = null; MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX(); MyCamera.MV_CC_DEVICE_INFO stDevInfo = new MyCamera.MV_CC_DEVICE_INFO(); // ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver UInt32 m_nBufSizeForDriver = 0; IntPtr m_BufForDriver = IntPtr.Zero; private static Object BufForDriverLock = new Object(); bool _snapFlag = false; public MyCamera.cbOutputExdelegate ImageCallback; MyCamera.MV_FRAME_OUT _frame = new MyCamera.MV_FRAME_OUT(); readonly ManualResetEvent _snapHandle = new ManualResetEvent(false); //ImageSet _bufferImgSet = null; ManualResetEvent _bufferHandle = new ManualResetEvent(false); public Action OnHImageOutput { get; set; } /// /// 相机拍照计数 /// public volatile int SnapshotCount = 0; public bool Ifsucess = false; public HikCamera() { } private void DeviceListAcq() { // ch:创建设备列表 | en:Create Device List System.GC.Collect(); // cbDeviceList.Items.Clear(); // m_stDeviceList.nDeviceNum = 0; int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList); if (0 != nRet) { // ShowErrorMsg("Enumerate devices fail!", 0); return; } // ch:在窗体列表中显示设备名 | en:Display device name in the form list for (int i = 0; i < m_stDeviceList.nDeviceNum; i++) { MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO)); if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) { MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); if (gigeInfo.chUserDefinedName != "") { //cbDeviceList.Items.Add("GEV: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")"); } else { // cbDeviceList.Items.Add("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")"); } } else if (device.nTLayerType == MyCamera.MV_USB_DEVICE) { MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO)); if (usbInfo.chUserDefinedName != "") { //cbDeviceList.Items.Add("U3V: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")"); } else { //cbDeviceList.Items.Add("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")"); } } } // ch:选择第一项 | en:Select the first item if (m_stDeviceList.nDeviceNum != 0) { //cbDeviceList.SelectedIndex = 0; } } public bool Start() { #region 枚举相机后根据IP地址匹配连接相机 //将IP地址转换为字节数组 uint intAddress = 0; if (/*(IIConfig.HikCameraType == EnumHelper.HikCameraType.Gige) &&*/ (!string.IsNullOrWhiteSpace("169.254.127.84"))) { byte[] IPArr = IPAddress.Parse("169.254.127.84").GetAddressBytes(); for (int i = 0; i < IPArr.Length; i++) { intAddress += (uint)(IPArr[i] << (IPArr.Length - 1 - i) * 8); } } MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST(); int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList); if (0 != nRet) { throw new Exception($"Enumerate devices fail!"); } else { //LogAsync(DateTime.Now, $"搜索获取{m_pDeviceList.nDeviceNum.ToInt()}台相机在线", ""); } bool isCameraFound = false; for (int i = 0; i < m_pDeviceList.nDeviceNum; i++) { MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO)); IntPtr buffer = IntPtr.Zero; if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) { buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0); MyCamera.MV_GIGE_DEVICE_INFO stGigEDev = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); if (stGigEDev.nCurrentIp == intAddress) { stDevInfo = device; isCameraFound = true; } } else if (device.nTLayerType == MyCamera.MV_USB_DEVICE) { //buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stUsb3VInfo, 0); //MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_USB3_DEVICE_INFO)); //if (usbInfo.chSerialNumber == IConfig.SerialNum) //{ // stDevInfo = device; // isCameraFound = true; //} } //释放内存空间 //Marshal.FreeHGlobal(buffer); if (isCameraFound) break; } if (!isCameraFound) { throw new Exception($"相机未能找到"); } #endregion // ch:创建设备 | en: Create device nRet = device.MV_CC_CreateDevice_NET(ref stDevInfo); if (MyCamera.MV_OK != nRet) { throw new Exception($"Create device failed:{nRet:x8}"); } // ch:打开设备 | en:Open device nRet = device.MV_CC_OpenDevice_NET(); if (MyCamera.MV_OK != nRet) { throw new Exception($"Open device failed:{nRet:x8}"); } // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera) if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE) { int nPacketSize = device.MV_CC_GetOptimalPacketSize_NET(); if (nPacketSize > 0) { nRet = device.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize); if (nRet != MyCamera.MV_OK) { Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet); } } else { Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize); } } // ch:注册异常回调函数 | en:Register Exception Callback nRet = device.MV_CC_RegisterExceptionCallBack_NET(pCallBackFunc, IntPtr.Zero); if (MyCamera.MV_OK != nRet) { throw new Exception($"Register expection callback failed:{nRet}"); } GC.KeepAlive(pCallBackFunc); // ch:设置采集连续模式 | en:Set Continues Aquisition Mode device.MV_CC_SetEnumValue_NET("AcquisitionMode", 2);// ch:工作在连续模式 | en:Acquisition On Continuous Mode if (false) { device.MV_CC_SetEnumValue_NET("TriggerMode", 0); // ch:连续模式 | en:Continuous // ch:注册回调函数 | en:Register image callback ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc); nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero); if (MyCamera.MV_OK != nRet) { throw new Exception("Register image callback failed!"); } } else { // ch:设置触发模式为off || en:set trigger mode as off nRet = device.MV_CC_SetEnumValue_NET("TriggerMode", 1); if (MyCamera.MV_OK != nRet) { throw new Exception("Set TriggerMode failed!"); } if (false) { // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0; // 1 - Line1; // 2 - Line2; // 3 - Line3; // 4 - Counter; // 7 - Software; nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", 0); if (MyCamera.MV_OK != nRet) { throw new Exception("Set Line0 Trigger failed!"); } // ch:注册回调函数 | en:Register image callback ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc); nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero); if (MyCamera.MV_OK != nRet) { throw new Exception("Register image callback failed!"); } } else { nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", 7); if (MyCamera.MV_OK != nRet) { throw new Exception("Set Software Trigger failed!"); } } } // ch:开启抓图 || en: start grab image nRet = device.MV_CC_StartGrabbing_NET(); if (MyCamera.MV_OK != nRet) { throw new Exception($"Start grabbing failed:{nRet:x8}"); } else { Ifsucess = true; } return true; } public void Stop() { if(Ifsucess) { // IIConfig.PropertyChanged -= IIConfig_PropertyChanged; // ch:停止抓图 | en:Stop grab image nRet = device.MV_CC_StopGrabbing_NET(); if (MyCamera.MV_OK != nRet) { throw new Exception($"Stop grabbing failed{nRet:x8}"); } // ch:关闭设备 | en:Close device nRet = device.MV_CC_CloseDevice_NET(); if (MyCamera.MV_OK != nRet) { throw new Exception($"Close device failed{nRet:x8}"); } // ch:销毁设备 | en:Destroy device nRet = device.MV_CC_DestroyDevice_NET(); if (MyCamera.MV_OK != nRet) { throw new Exception($"Destroy device failed:{nRet:x8}"); } } Ifsucess = false; } void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser) { try { // if (false) // { // // SnapshotCount++; // Interlocked.Increment(ref SnapshotCount); // // Console.WriteLine($">>>> {IIConfig.Name} 相机硬触发..."); // //LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机硬触发"); // //Stopwatch sw = new Stopwatch(); // //sw.Start(); // int nWidth = pFrameInfo.nWidth; // int nHeight = pFrameInfo.nHeight; // //HImage hImage = new HImage(); // //HObject Hobj = new HObject(); // //IntPtr pTemp = IntPtr.Zero; // //hImage.GenImage1((HTuple)"byte", nWidth, nHeight, pData); // //var imgSet = new ImageSet // //{ // // HImage = hImage, // // ImageSaveOption = IConfig.ImageSaveOption.Copy() // //}; // //测试图片颜色 // //if (IsColor(pFrameInfo.enPixelType)) // //{ // // //pFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed; // // // 彩色图 // // switch (pFrameInfo.enPixelType) // // { // // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8: // // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_gr", "bilinear"); // // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage(); // // break; // // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8: // // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_rg", "bilinear"); // // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage(); // // break; // // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8: // // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_gb", "bilinear"); // // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage(); // // break; // // case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8: // // imgSet.HImage = imgSet.HImage.CfaToRgb("bayer_bg", "bilinear"); // // imgSet.HImage = imgSet.HImage.ConvertHObjectToHImage(); // // break; // // } // //} // if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) // { // // Console.WriteLine("image pixel format is rgb8..."); // //pTemp = pData; // //HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0); // //HobjectToRGBHimage(Hobj, ref hImage); // } // // Console.WriteLine($">>>> {IIConfig.Name} 相机数据转换完成 ..."); // //if (!IsMonoData(pFrameInfo.enPixelType)) // //{ // // pImageBuf = Marshal.AllocHGlobal((int)stFrameInfo.nWidth * stFrameInfo.nHeight * 3); // // HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0); // //} //#if false // if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8) // { // //加入内部队列 // InitialImageSet(imgSet); // //业务图片处理加入外部队列 // var outImgSet = CopyImageSet(imgSet); // if (IIConfig.IsDirectHardwareTrigger) // { // //传感器直接触发 收到图片后 传出 // OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet); // } // else // { // _bufferImgSet = outImgSet; // //_bufferImgSetQueue.Enqueue(outImgSet); // _bufferHandle.Set(); // } // ClearImageSet(imgSet); // } // else // { // Console.WriteLine($">>>> 像素类型:{pFrameInfo.enPixelType}"); // } //#else // //加入内部队列 // InitialImageSet(imgSet); // //业务图片处理加入外部队列 // var outImgSet = CopyImageSet(imgSet); // // LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机取像, 次数:{SnapshotCount}"); // // Console.WriteLine($">>>> {IIConfig.Name} 相机回调 OnHImageOutput ..."); // if (IIConfig.IsDirectHardwareTrigger) // { // // 传感器直接触发 收到图片后 传出 // OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet); // } // else // { // _bufferImgSet = outImgSet; // // _bufferImgSetQueue.Enqueue(outImgSet); // _bufferHandle.Set(); // } // //处理完图片 会清理内部队列的图像 // DisplayAndSaveOriginImage(imgSet.Id); // //ClearImageSet(imgSet); //#endif // } //else //{ if (_snapFlag) { _snapFlag = false; _frame = new MyCamera.MV_FRAME_OUT { stFrameInfo = pFrameInfo, pBufAddr = pData }; _snapHandle.Set(); } // } } catch (Exception ex) { //LogAsync(DateTime.Now, LogLevel.Exception, $"{Name}相机取像异常,{ex.GetExceptionMessage()}"); } } public void Snapshot() { Stopwatch sw = new Stopwatch(); sw.Start(); // ImageSet set = new ImageSet(); // set.SnapshotCount = SnapshotCount; // set.SnapshotFileName = SnapshotFileNames; //InitialImageSet(set); MyCamera.MV_FRAME_OUT frameInfo = new MyCamera.MV_FRAME_OUT(); nRet = MyCamera.MV_OK; if (true) { // ch: 触发命令 || en: Trigger command nRet = device.MV_CC_SetCommandValue_NET("TriggerSoftware"); if (MyCamera.MV_OK != nRet) { throw new Exception($"相机拍照触发失败:{nRet}"); } nRet = device.MV_CC_GetImageBuffer_NET(ref frameInfo, 1000); nRet = device.MV_CC_FreeImageBuffer_NET(ref frameInfo); } else { _snapHandle.Reset(); _snapFlag = true; _snapHandle.WaitOne(); //lock (_imgCallBackLock) { frameInfo.stFrameInfo = _frame.stFrameInfo; frameInfo.pBufAddr = _frame.pBufAddr; } } // ch:获取一帧图像 | en:Get one image if (MyCamera.MV_OK == nRet) { if (frameInfo.pBufAddr != IntPtr.Zero) { if (nRet == MyCamera.MV_OK) { var pFrameInfo = frameInfo.stFrameInfo; Mat mat=new Mat(pFrameInfo.nHeight, pFrameInfo.nWidth, MatType.CV_8UC3, frameInfo.pBufAddr); OnHImageOutput?.Invoke(DateTime.Now, mat, SnapshotCount); mat.ImWrite("D://123.jpg"); //HImage hImage = new HImage(); //HObject Hobj = new HObject(); //IntPtr pTemp = IntPtr.Zero; //hImage.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, frameInfo.pBufAddr); ////hImage.ConvertHImageTo16GrayBitmap(); //var imgSet = new ImageSet //{ // HImage = hImage, // ImageSaveOption = IConfig.ImageSaveOption.Copy() //}; //if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) //{ // // Console.WriteLine("image pixel format is rgb8..."); // pTemp = frameInfo.pBufAddr; // HOperatorSet.GenImageInterleaved(out Hobj, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0); // HobjectToRGBHimage(Hobj, ref hImage); //} //加入内部队列 //InitialImageSet(imgSet); ////业务图片处理加入外部队列 //var outImgSet = CopyImageSet(imgSet); //OnHImageOutput?.Invoke(DateTime.Now, this, outImgSet); //LogAsync(DateTime.Now, LogLevel.Information, $"{Name}相机取像, 次数:{SnapshotCount}"); //DisplayAndSaveOriginImage(imgSet.Id); //HikToBitmap(pFrameInfo, frameInfo.pBufAddr); //Generate8GrayImageByPointer((int)nWidth, (int)nHeight, frameInfo.pBufAddr, ""); } } } else { throw new Exception($"Grap Image Failed:{nRet:x8}"); } sw.Stop(); //LogAsync(DateTime.Now, LogLevel.Information, $"取像耗时:{sw.ElapsedMilliseconds} ms"); } } }