using OpenCvSharp; using System; using System.Collections.Generic; 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.Forms; using MvCamCtrl.NET; using OpenCvSharp.Dnn; using System.Diagnostics; using HalconDotNet; using System.Xml.Linq; namespace GuideGraspSys { public class HikCamDriver: CameraBase { [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_pDeviceList; MyCamera.MV_CC_DEVICE_INFO device; MyCamera hkCamera = new MyCamera(); /// /// 抓图回调 /// MyCamera.cbOutputExdelegate ImageCallback; Thread m_hReceiveThread = null; /// /// 异常回调 /// MyCamera.cbExceptiondelegate pCallBackFunc; HObject hPylonImage = new HObject(); List CameraName = new List(); MyCamera.MV_FRAME_OUT _frame = new MyCamera.MV_FRAME_OUT(); readonly ManualResetEvent _snapHandle = new ManualResetEvent(false); bool _snapFlag = false; // ch:Bitmap及其像素格式 | en:Bitmap and Pixel Format Bitmap m_bitmap = null; PixelFormat m_bitmapPixelFormat = PixelFormat.DontCare; IntPtr m_ConvertDstBuf = IntPtr.Zero; UInt32 m_nConvertDstBufLen = 0; int nRet = MyCamera.MV_OK; /// /// 曝光时间 /// public int ExposureTime { get; set; } /// /// 增益 /// public int Gain { get; set; } /// /// 帧率 /// public int FrameRate { get; set; } public bool m_bGrabbing = false; private static Object BufForDriverLock = new Object(); IntPtr m_BufForDriver = IntPtr.Zero; UInt32 m_nBufSizeForDriver = 0; MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX(); public delegate void MatImgTransferDelegate(Mat img); public event MatImgTransferDelegate OnImgTransfer; public delegate void BitmapTransferDelegate(Bitmap img); public event BitmapTransferDelegate OnBitmapTransfer; public Action OnHImageOutput { get; set; } public static Dictionary allCamera=new Dictionary(); private CameraInfor currentCam; public override bool CloserCamera() { m_bGrabbing = false; hkCamera.MV_CC_StopGrabbing_NET();//停止采集 hkCamera.MV_CC_CloseDevice_NET();//关闭设备 hkCamera.MV_CC_DestroyDevice_NET(); return true; } /// /// 开启硬触发 /// /// public override bool EncoderGrap() { try { if (m_bGrabbing) { Console.WriteLine("Camera is now Continue Grabing Images!"); return false; } else { // ch:标志位置位true | en:Set position bit true m_bGrabbing = true; hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); //设置使用硬触发模式 int nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); if (MyCamera.MV_OK != nRet) { m_bGrabbing = false; return false; } return true; } } catch (Exception) { return false; } } //public override List FindCamera() //{ // int nRet; // System.GC.Collect(); // CameraName.Clear(); // nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList); // if (0 != nRet) // { // Console.WriteLine("Not Find Camera!{0:x8}", nRet); // return null; // } // 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)); // //网口相机 // if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) // { // IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0); // MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); // if (gigeInfo.chUserDefinedName != "") // { // Console.WriteLine("GigE:" + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")"); // CameraName.Add("GigE:" + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")"); // } // else // { // Console.WriteLine("GigE: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")"); // CameraName.Add("GigE: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")"); // } // } // else if (device.nTLayerType == MyCamera.MV_USB_DEVICE) // { // IntPtr 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.chUserDefinedName != "") // { // Console.WriteLine("USB: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")"); // CameraName.Add("USB: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")"); // } // else // { // Console.WriteLine("USB: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")"); // CameraName.Add("USB: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")"); // } // } // } // if (m_pDeviceList.nDeviceNum == 0) // { // Console.WriteLine("未能找到USB或者网线接口的相机", 0); // return null; // } // return CameraName; //} public Dictionary EnumDevice() { System.GC.Collect();//强制对所有代进行及时垃圾回收 m_pDeviceList.nDeviceNum = 0; //初始化信息列表 int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList); if (0 != nRet) { return null; } allCamera.Clear(); //清空设备列表 CameraInfor cameraInfor; 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));//获取第i个相机句柄的相机信息 cameraInfor = new CameraInfor(); cameraInfor.pDeviceInfo = m_pDeviceList.pDeviceInfo[i];//获取相机句柄 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));//将通用相机信息结构体转化为Gige相机结构体 UInt32 nNetIp1 = (gigeInfo.nNetExport & 0xFF000000) >> 24; UInt32 nNetIp2 = (gigeInfo.nNetExport & 0x00FF0000) >> 16; UInt32 nNetIp3 = (gigeInfo.nNetExport & 0x0000FF00) >> 8; UInt32 nNetIp4 = (gigeInfo.nNetExport & 0x000000FF); // ch:显示IP | en:Display IP UInt32 nIp1 = (gigeInfo.nCurrentIp & 0xFF000000) >> 24; UInt32 nIp2 = (gigeInfo.nCurrentIp & 0x00FF0000) >> 16; UInt32 nIp3 = (gigeInfo.nCurrentIp & 0x0000FF00) >> 8; UInt32 nIp4 = (gigeInfo.nCurrentIp & 0x000000FF); cameraInfor.serialNumber = gigeInfo.chSerialNumber; cameraInfor.userDefinedName = gigeInfo.chUserDefinedName; cameraInfor.manufacturerName = gigeInfo.chManufacturerName; cameraInfor.modelName = gigeInfo.chModelName; cameraInfor.deviceType = "GEV"; //千兆网工业相机技术之GigE Vision(GEV) cameraInfor.deviceIPAdd = nIp1.ToString() + "." + nIp2.ToString() + "." + nIp3.ToString() + "." + nIp4.ToString(); allCamera.Add(cameraInfor.userDefinedName, cameraInfor); } 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)); cameraInfor.serialNumber = usbInfo.chSerialNumber; cameraInfor.userDefinedName = usbInfo.chUserDefinedName; cameraInfor.manufacturerName = usbInfo.chManufacturerName; cameraInfor.modelName = usbInfo.chModelName; cameraInfor.deviceType = "U3V"; allCamera.Add(cameraInfor.deviceIPAdd, cameraInfor); } } return allCamera; } /// /// 根据相机序列号开启相机 /// /// /// int cameraIndex /// public override bool OpenCamera(string userDefinedName, IntPtr hWnd) { int nRet = 0; currentCam = allCamera[userDefinedName]; //m_pDeviceList.pDeviceInfo[cameraIndex] device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(allCamera[userDefinedName].pDeviceInfo, typeof(MyCamera.MV_CC_DEVICE_INFO)); IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0); MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); if (null == hkCamera) { hkCamera = new MyCamera(); if (null == hkCamera) { return false; } } for (int i = 0; i < 10; i++) { nRet = hkCamera.MV_CC_CreateDevice_NET(ref device); if (MyCamera.MV_OK != nRet) { Thread.Sleep(1); if (i == 9) Console.WriteLine("创建相机失败!{0:x8}", nRet); continue; } nRet = hkCamera.MV_CC_OpenDevice_NET(); if (MyCamera.MV_OK != nRet) { hkCamera.MV_CC_DestroyDevice_NET(); Thread.Sleep(10); if (i == 9) Console.WriteLine("打开相机失败!{0:x8}", nRet); } else { break; } } //探测网络最佳包大小(只对gige相机有效) if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) { int nPacketSize = hkCamera.MV_CC_GetOptimalPacketSize_NET(); if (nPacketSize > 0) { nRet = hkCamera.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); } } SetTriggerMode(true); SetSoftTrigger(true); //注册断线重连回调函数 nRet = hkCamera.MV_CC_RegisterExceptionCallBack_NET(pCallBackFunc, IntPtr.Zero); if (MyCamera.MV_OK != nRet) { return false; } GC.KeepAlive(pCallBackFunc); //注册图像回调函数 //ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc); //nRet = hkCamera.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero); if (MyCamera.MV_OK != nRet) { Console.WriteLine("Register image callback failed!"); return false; } // ch:设置采集连续模式 | en:Set Continues Aquisition Mode hkCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS); //设置开启触发模式 nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF); //设置开启软触发模式 //hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); //使用软触发命令 //nRet = hkCamera.MV_CC_SetCommandValue_NET("TriggerSoftware"); if (MyCamera.MV_OK != nRet) { m_bGrabbing = false; return false; } //开始采集 // nRet = hkCamera.MV_CC_StartGrabbing_NET(); if (MyCamera.MV_OK != nRet) { Console.WriteLine("开启相机采集失败! {0:x8}", nRet); return false; } return true; } /// /// 设置触发模式 /// /// 触发模式:true;连续采集模式:false public void SetTriggerMode(bool isTrigger) { if (isTrigger) { hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); } else { hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF); } } /// /// 设置软触发 /// /// public void SetSoftTrigger(bool trigBySoft) { if (trigBySoft) { hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); } else { //外部触发源:Line0~Line3,默认用Line0 hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); } } /// /// //public override bool OneGrap() //{ // try // { // if (m_bGrabbing) // { // Console.WriteLine("Camera is now Continue Grabing Images!"); // return false; // } // else // { // // ch:标志位置位true | en:Set position bit true // //m_bGrabbing = true; // int nRet; // MyCamera.MV_FRAME_OUT frameInfo = new MyCamera.MV_FRAME_OUT(); // //设置开启触发模式 // nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); // //设置开启软触发模式 // nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); // //使用软触发命令 // nRet = hkCamera.MV_CC_SetCommandValue_NET("TriggerSoftware"); // if (MyCamera.MV_OK != nRet) // { // throw new Exception($"相机拍照触发失败:{nRet}"); // } // //nRet = hkCamera.MV_CC_GetImageBuffer_NET(ref frameInfo, 1000); // //nRet = hkCamera.MV_CC_FreeImageBuffer_NET(ref frameInfo); // if (MyCamera.MV_OK != nRet) // { // m_bGrabbing = false; // return false; // } // else // { // //if (frameInfo.pBufAddr != IntPtr.Zero) // //{ // if (nRet == MyCamera.MV_OK) // { // var pFrameInfo = frameInfo.stFrameInfo; // //himg.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, frameInfo.pBufAddr); // Mat mat = Mat.FromPixelData(pFrameInfo.nWidth, pFrameInfo.nHeight, MatType.CV_8UC3, frameInfo.pBufAddr); // //Bitmap a = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat); // //OnDeliverImg?.Invoke(_mat); // Cv2.ImWrite("test.jpg", mat); // OnImgTransfer?.Invoke(mat); // } // //} // } // // HeventSlim.Wait(); // return true; // } // } // catch (Exception) // { // return false; // } //} bool IsGrabImg; public void GrabImg() { IsGrabImg = true; int nRet = hkCamera.MV_CC_SetCommandValue_NET("TriggerSoftware"); MyCamera.MV_FRAME_OUT frameInfo = new MyCamera.MV_FRAME_OUT(); //nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref frameInfo,10); //nRet = m_MyCamera.MV_CC_FreeImageBuffer_NET(ref frameInfo); if (MyCamera.MV_OK != nRet) { //ShowErrorMsg("Trigger Software Fail!", nRet); } } public void StartGarb(IntPtr handle) { int nRet; nRet = NecessaryOperBeforeGrab(); m_bGrabbing = true; IsGrabImg = false; m_hReceiveThread = new Thread(new ParameterizedThreadStart(ReceiveThreadProcess)); m_hReceiveThread.Start(handle); m_stFrameInfo.nFrameLen = 0; m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined; // nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); //设置开启软触发模式 //nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); // ch:开始采集 | en:Start Grabbing nRet = hkCamera.MV_CC_StartGrabbing_NET(); if (MyCamera.MV_OK != nRet) { m_bGrabbing = false; m_hReceiveThread.Join(); //ShowErrorMsg("Start Grabbing Fail!", nRet); return; } } //public void StopGrabbing() //{ // int nRet = hkCamera.MV_CC_StopGrabbing_NET(); // if (nRet != MyCamera.MV_OK) // { // //ShowAlarm(string.Format("相机{0}结束采集失败,错误代码:{1}", m_Name, nRet)); // } //} public void ReceiveThreadProcess(object handle) { MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT(); MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO(); MyCamera.MV_PIXEL_CONVERT_PARAM stConvertInfo = new MyCamera.MV_PIXEL_CONVERT_PARAM(); int nRet = MyCamera.MV_OK; while (m_bGrabbing) { nRet = hkCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000); if (nRet == MyCamera.MV_OK) { lock (BufForDriverLock) { if (m_BufForDriver == IntPtr.Zero || stFrameInfo.stFrameInfo.nFrameLen > m_nBufSizeForDriver) { if (m_BufForDriver != IntPtr.Zero) { Marshal.Release(m_BufForDriver); m_BufForDriver = IntPtr.Zero; } m_BufForDriver = Marshal.AllocHGlobal((Int32)stFrameInfo.stFrameInfo.nFrameLen); if (m_BufForDriver == IntPtr.Zero) { return; } m_nBufSizeForDriver = stFrameInfo.stFrameInfo.nFrameLen; } m_stFrameInfo = stFrameInfo.stFrameInfo; CopyMemory(m_BufForDriver, stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo.nFrameLen); stConvertInfo.nWidth = stFrameInfo.stFrameInfo.nWidth; stConvertInfo.nHeight = stFrameInfo.stFrameInfo.nHeight; stConvertInfo.enSrcPixelType = stFrameInfo.stFrameInfo.enPixelType; stConvertInfo.pSrcData = stFrameInfo.pBufAddr; stConvertInfo.nSrcDataLen = stFrameInfo.stFrameInfo.nFrameLen; stConvertInfo.pDstBuffer = m_ConvertDstBuf; stConvertInfo.nDstBufferSize = m_nConvertDstBufLen; if (PixelFormat.Format8bppIndexed == m_bitmap.PixelFormat) { stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8; hkCamera.MV_CC_ConvertPixelType_NET(ref stConvertInfo); } else { stConvertInfo.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed; hkCamera.MV_CC_ConvertPixelType_NET(ref stConvertInfo); } // ch:保存Bitmap数据 | en:Save Bitmap Data BitmapData bitmapData = m_bitmap.LockBits(new Rectangle(0, 0, stConvertInfo.nWidth, stConvertInfo.nHeight), ImageLockMode.ReadWrite, m_bitmap.PixelFormat); CopyMemory(bitmapData.Scan0, stConvertInfo.pDstBuffer, (UInt32)(bitmapData.Stride * m_bitmap.Height)); m_bitmap.UnlockBits(bitmapData); } if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType)) { hkCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo); continue; } nRet = hkCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo); if (IsGrabImg) { if (MyCamera.MV_OK == nRet) { if (stFrameInfo.pBufAddr != IntPtr.Zero) { stDisplayInfo.hWnd = (IntPtr)handle; stDisplayInfo.pData = stFrameInfo.pBufAddr; stDisplayInfo.nDataLen = stFrameInfo.stFrameInfo.nFrameLen; stDisplayInfo.nWidth = stFrameInfo.stFrameInfo.nWidth; stDisplayInfo.nHeight = stFrameInfo.stFrameInfo.nHeight; stDisplayInfo.enPixelType = stFrameInfo.stFrameInfo.enPixelType; hkCamera.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo); //nRet = hkCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo); var pFrameInfo = stFrameInfo.stFrameInfo; Mat ab = new Mat(pFrameInfo.nHeight, pFrameInfo.nWidth, MatType.CV_8UC3, stFrameInfo.pBufAddr); //OnImgTransfer?.Invoke(ab); OnHImageOutput?.Invoke(DateTime.Now, ab); //Cv2.ImWrite("test.jpg", ab); } } } } else { } } } public void ConvertToImage(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser) { int nRet; //HObject img = new HObject(); Mat matImag = new Mat(); //Bitmap bitmap = new Bitmap(); IntPtr pImageBuf = IntPtr.Zero; int nImageBufSize = 0; //Bitmap cameraImg; IntPtr pTemp = IntPtr.Zero; if (IsColorPixelFormat(pFrameInfo.enPixelType)) { //cameraImg = new Bitmap(pFrameInfo.nWidth, pFrameInfo.nHeight, pFrameInfo.nWidth * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb,pData); //bmp.Save("1.bmp", System.Drawing.Imaging.ImageFormat.Bmp); if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) { pTemp = pData; } else { if (IntPtr.Zero == pImageBuf || nImageBufSize < (pFrameInfo.nWidth * pFrameInfo.nHeight * 3)) { if (pImageBuf != IntPtr.Zero) { Marshal.FreeHGlobal(pImageBuf); pImageBuf = IntPtr.Zero; } pImageBuf = Marshal.AllocHGlobal((int)pFrameInfo.nWidth * pFrameInfo.nHeight * 3); if (IntPtr.Zero == pImageBuf) { Console.WriteLine("图像采集为空"); return; } nImageBufSize = pFrameInfo.nWidth * pFrameInfo.nHeight * 3; } MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM(); stPixelConvertParam.pSrcData = pData;//源数据 stPixelConvertParam.nWidth = pFrameInfo.nWidth;//图像宽度 stPixelConvertParam.nHeight = pFrameInfo.nHeight;//图像高度 stPixelConvertParam.enSrcPixelType = pFrameInfo.enPixelType;//源数据的格式 stPixelConvertParam.nSrcDataLen = pFrameInfo.nFrameLen; stPixelConvertParam.nDstBufferSize = (uint)nImageBufSize; stPixelConvertParam.pDstBuffer = pImageBuf;//转换后的数据 stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed; nRet = hkCamera.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换 if (MyCamera.MV_OK != nRet) { Console.WriteLine("图像转换异常"); return; } pTemp = stPixelConvertParam.pDstBuffer; } try { HOperatorSet.GenImageInterleaved(out hPylonImage, (HTuple)pTemp, (HTuple)"rgb", (HTuple)pFrameInfo.nWidth, (HTuple)pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0); } catch (System.Exception ex) { Console.WriteLine(ex.ToString()); return; } } else if (IsMonoPixelFormat(pFrameInfo.enPixelType)) { if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8) { pTemp = pData; } else { if (IntPtr.Zero == pImageBuf || nImageBufSize < (pFrameInfo.nWidth * pFrameInfo.nHeight)) { if (pImageBuf != IntPtr.Zero) { Marshal.FreeHGlobal(pImageBuf); pImageBuf = IntPtr.Zero; } pImageBuf = Marshal.AllocHGlobal((int)pFrameInfo.nWidth * pFrameInfo.nHeight); if (IntPtr.Zero == pImageBuf) { Console.WriteLine("图像采集为空"); return; } nImageBufSize = pFrameInfo.nWidth * pFrameInfo.nHeight; } MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM(); stPixelConvertParam.pSrcData = pData;//源数据 stPixelConvertParam.nWidth = pFrameInfo.nWidth;//图像宽度 stPixelConvertParam.nHeight = pFrameInfo.nHeight;//图像高度 stPixelConvertParam.enSrcPixelType = pFrameInfo.enPixelType;//源数据的格式 stPixelConvertParam.nSrcDataLen = pFrameInfo.nFrameLen; stPixelConvertParam.nDstBufferSize = (uint)nImageBufSize; stPixelConvertParam.pDstBuffer = pImageBuf;//转换后的数据 stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8; nRet = hkCamera.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换 if (MyCamera.MV_OK != nRet) { Console.WriteLine("图像转换异常"); return; } pTemp = stPixelConvertParam.pDstBuffer; ; } try { //cameraImg = new Bitmap(); // HOperatorSet.GenImage1Extern(out hPylonImage, "byte", pFrameInfo.nWidth, pFrameInfo.nHeight, pTemp, IntPtr.Zero); } catch (System.Exception ex) { MessageBox.Show(ex.ToString()); return; } } else { Console.WriteLine("采集图像格式错误,不为彩色和黑白图像"); return; } try { //GetImage(hPylonImage);//调用相机基类的函数,用于传出变量 //hPylonImage.Dispose(); m_bGrabbing = false; } catch (Exception e) { Console.WriteLine(e.ToString()); return; } } private Boolean IsMono(UInt32 enPixelType) { switch (enPixelType) { case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono1p: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono2p: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono4p: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8_Signed: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono14: case (UInt32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono16: return true; default: return false; } } private Int32 NecessaryOperBeforeGrab() { // ch:取图像宽 | en:Get Iamge Width MyCamera.MVCC_INTVALUE_EX stWidth = new MyCamera.MVCC_INTVALUE_EX(); int nRet = hkCamera.MV_CC_GetIntValueEx_NET("Width", ref stWidth); if (MyCamera.MV_OK != nRet) { //ShowErrorMsg("Get Width Info Fail!", nRet); return nRet; } // ch:取图像高 | en:Get Iamge Height MyCamera.MVCC_INTVALUE_EX stHeight = new MyCamera.MVCC_INTVALUE_EX(); nRet = hkCamera.MV_CC_GetIntValueEx_NET("Height", ref stHeight); if (MyCamera.MV_OK != nRet) { //ShowErrorMsg("Get Height Info Fail!", nRet); return nRet; } // ch:取像素格式 | en:Get Pixel Format MyCamera.MVCC_ENUMVALUE stPixelFormat = new MyCamera.MVCC_ENUMVALUE(); nRet = hkCamera.MV_CC_GetEnumValue_NET("PixelFormat", ref stPixelFormat); if (MyCamera.MV_OK != nRet) { //ShowErrorMsg("Get Pixel Format Fail!", nRet); return nRet; } // ch:设置bitmap像素格式,申请相应大小内存 | en:Set Bitmap Pixel Format, alloc memory if ((Int32)MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined == stPixelFormat.nCurValue) { //ShowErrorMsg("Unknown Pixel Format!", MyCamera.MV_E_UNKNOW); return MyCamera.MV_E_UNKNOW; } else if (IsMono(stPixelFormat.nCurValue)) { m_bitmapPixelFormat = PixelFormat.Format8bppIndexed; if (IntPtr.Zero != m_ConvertDstBuf) { Marshal.Release(m_ConvertDstBuf); m_ConvertDstBuf = IntPtr.Zero; } // Mono8为单通道 m_nConvertDstBufLen = (UInt32)(stWidth.nCurValue * stHeight.nCurValue); m_ConvertDstBuf = Marshal.AllocHGlobal((Int32)m_nConvertDstBufLen); if (IntPtr.Zero == m_ConvertDstBuf) { //ShowErrorMsg("Malloc Memory Fail!", MyCamera.MV_E_RESOURCE); return MyCamera.MV_E_RESOURCE; } } else { m_bitmapPixelFormat = PixelFormat.Format24bppRgb; if (IntPtr.Zero != m_ConvertDstBuf) { Marshal.FreeHGlobal(m_ConvertDstBuf); m_ConvertDstBuf = IntPtr.Zero; } // RGB为三通道 m_nConvertDstBufLen = (UInt32)(3 * stWidth.nCurValue * stHeight.nCurValue); m_ConvertDstBuf = Marshal.AllocHGlobal((Int32)m_nConvertDstBufLen); if (IntPtr.Zero == m_ConvertDstBuf) { //ShowErrorMsg("Malloc Memory Fail!", MyCamera.MV_E_RESOURCE); return MyCamera.MV_E_RESOURCE; } } // 确保释放保存了旧图像数据的bitmap实例,用新图像宽高等信息new一个新的bitmap实例 if (null != m_bitmap) { m_bitmap.Dispose(); m_bitmap = null; } m_bitmap = new Bitmap((Int32)stWidth.nCurValue, (Int32)stHeight.nCurValue, m_bitmapPixelFormat); // ch:Mono8格式,设置为标准调色板 | en:Set Standard Palette in Mono8 Format if (PixelFormat.Format8bppIndexed == m_bitmapPixelFormat) { ColorPalette palette = m_bitmap.Palette; for (int i = 0; i < palette.Entries.Length; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } m_bitmap.Palette = palette; } return MyCamera.MV_OK; } /// /// 相机重连开启 /// /// /// public override bool ReconnectCamera(string CameraName) { CloserCamera(); for (int i = 0; i < m_pDeviceList.nDeviceNum; i++) { device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO)); IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0); MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO)); if (gigeInfo.chSerialNumber == CameraName) { break; } } int index = 0; while (true) { int nRet = hkCamera.MV_CC_CreateDevice_NET(ref device); index++; if (index > 1000) { Console.WriteLine("相机重连超时,请检查相机安装"); nRet = -1; break; } if (MyCamera.MV_OK != nRet) { Thread.Sleep(5); continue; } nRet = hkCamera.MV_CC_OpenDevice_NET(); if (MyCamera.MV_OK != nRet) { Thread.Sleep(5); hkCamera.MV_CC_DestroyDevice_NET(); continue; } else { if (MyCamera.MV_OK != nRet) { Thread.Sleep(5); hkCamera.MV_CC_DestroyDevice_NET(); continue; } break; } } return true; } void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser) { //Console.WriteLine("Get one frame: Width[" + Convert.ToString(pFrameInfo.nWidth) + "] , Height[" + Convert.ToString(pFrameInfo.nHeight) // + "] , FrameNum[" + Convert.ToString(pFrameInfo.nFrameNum) + "]"); ConvertToImage(pData, ref pFrameInfo, pUser); } public Action OnDeliverImg { get; set; } 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 = hkCamera.MV_CC_SetCommandValue_NET("TriggerSoftware"); if (MyCamera.MV_OK != nRet) { throw new Exception($"相机拍照触发失败:{nRet}"); } nRet = hkCamera.MV_CC_GetImageBuffer_NET(ref frameInfo, 1000); nRet = hkCamera.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; HImage hImage = new HImage(); hImage.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, frameInfo.pBufAddr); Mat mat = new Mat(); Bitmap a = hImage.ConvertHImageToBitmap(); OnBitmapTransfer?.Invoke(a); } } } else { throw new Exception($"Grap Image Failed:{nRet:x8}"); } sw.Stop(); //LogAsync(DateTime.Now, LogLevel.Information, $"取像耗时:{sw.ElapsedMilliseconds} ms"); } /// /// 转化像素为Bit图像 /// /// /// public Bitmap GetBitmap(int nWidth, int nHeight, int nBpp, byte[] DataBuf, int nCompress = 1) { int nNewH = nHeight / nCompress; int nNewW = nWidth / nCompress; Bitmap BitmapImage = new Bitmap(nNewW, nNewH, PixelFormat.Format24bppRgb); BitmapData srcBmpData = BitmapImage.LockBits( new Rectangle(0, 0, BitmapImage.Width, BitmapImage.Height), ImageLockMode.ReadWrite, BitmapImage.PixelFormat); switch (nBpp) { case 0: unsafe { byte* psrcBuffer = (byte*)srcBmpData.Scan0.ToPointer(); int nIndex = 0; for (int i = 0; i < nHeight; i += nCompress) { for (int j = 0; j < nWidth; j += nCompress) { psrcBuffer[nIndex++] = DataBuf[i * nWidth + j]; psrcBuffer[nIndex++] = DataBuf[i * nWidth + j]; psrcBuffer[nIndex++] = DataBuf[i * nWidth + j]; } } } break; case 1: unsafe { byte* psrcBuffer = (byte*)srcBmpData.Scan0.ToPointer(); int nCount = nWidth * nHeight; int nStep = nCount * 2; int nIndex = 0; for (int i = 0; i < nHeight; i += nCompress) { for (int j = 0; j < nWidth; j += nCompress) { psrcBuffer[nIndex++] = DataBuf[i * nWidth + j + nStep]; psrcBuffer[nIndex++] = DataBuf[i * nWidth + j + nCount]; psrcBuffer[nIndex++] = DataBuf[i * nWidth + j]; } } } break; } BitmapImage.UnlockBits(srcBmpData); return BitmapImage; } public void SetHeartBeatTime(uint value) { try { //判断是否是网口相机 if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) { hkCamera.MV_CC_SetHeartBeatTimeout_NET(value); } } catch (Exception) { } } public override bool SetExpoureTime(int ExposureTime) { try { hkCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0); int nRet = hkCamera.MV_CC_SetFloatValue_NET("ExposureTime", ExposureTime); if (nRet != MyCamera.MV_OK) { return false; } return true; } catch (Exception) { return false; } } /// /// 判断是否为彩色图像 /// /// /// private bool IsColorPixelFormat(MyCamera.MvGvspPixelType enType) { switch (enType) { case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGBA8_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGRA8_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12: case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed: return true; default: return false; } } private bool IsMonoPixelFormat(MyCamera.MvGvspPixelType enType) { switch (enType) { case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8: case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10: case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed: case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12: case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed: return true; default: return false; } } private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat) { Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000)); if (0x80000000 == nResult) { return true; } else { return false; } } public void SetTriggerMode() { hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF); } public void SetTriggerModeON() { hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); } public void SetTriggerSource() { hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); } public void SetTriggerSourceLine0() { hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); } public void SetTriggerMode1() { int nRet; nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); //设置开启软触发模式 nRet = hkCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); } } public static class HalconHelper { [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); public static Bitmap ConvertHImageToBitmap(this HObject hImage) { HOperatorSet.CountChannels(hImage, out HTuple chanels); if (chanels.I == 1) { return hImage.ConvertHImageTo8GrayBitmap(); } else { return hImage.ConvertHImageToRGBBitmap(); // return hImage.HObject2BitmapRGB(); } } public static Bitmap ConvertHImageTo8GrayBitmap(this HObject hImage) { try { HTuple type, width, height, pointer; HOperatorSet.GetImagePointer1(hImage, out pointer, out type, out width, out height); Bitmap bmp = new Bitmap(width.I, height.I, PixelFormat.Format8bppIndexed); ColorPalette pal = bmp.Palette; for (int i = 0; i <= 255; i++) { pal.Entries[i] = Color.FromArgb(255, i, i, i); } bmp.Palette = pal; BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); if (width % 4 == 0) { CopyMemory(bitmapData.Scan0, (IntPtr)pointer.D, (uint)(bitmapData.Stride * height.I)); } else { Parallel.For(0, height.I, h => { CopyMemory(bitmapData.Scan0 + h * bitmapData.Stride, (IntPtr)(pointer.D + h * width.I), (uint)width.I); }); } bmp.UnlockBits(bitmapData); return bmp; } catch (Exception ex) { return null; } } public static Bitmap ConvertHImageToRGBBitmap(this HObject hImage) { try { HOperatorSet.GetImagePointer3(hImage, out HTuple pointRed, out HTuple pointGreen, out HTuple pointBlue, out HTuple type, out HTuple width, out HTuple height); Bitmap image = new Bitmap(width.I, height.I, PixelFormat.Format24bppRgb); BitmapData imageData = image.LockBits(new Rectangle(0, 0, width.I, height.I), ImageLockMode.ReadWrite, image.PixelFormat); IntPtr pR = (IntPtr)pointRed.D; IntPtr pG = (IntPtr)pointGreen.D; IntPtr pB = (IntPtr)pointBlue.D; Parallel.For(0, imageData.Height, h => { Parallel.For(0, imageData.Width, w => { int dest = h * imageData.Stride + w * 3; int source = h * imageData.Width + w; Marshal.WriteByte(imageData.Scan0, dest, Marshal.ReadByte(pB, source)); Marshal.WriteByte(imageData.Scan0, dest + 1, Marshal.ReadByte(pG, source)); Marshal.WriteByte(imageData.Scan0, dest + 2, Marshal.ReadByte(pR, source)); }); }); image.UnlockBits(imageData); return image; } catch (Exception exc) { return null; } } } public class CameraInfor { public string userDefinedName { get; set; } //用户定义的名字 public string serialNumber { get; set; } //序列号 public string deviceIPAdd { get; set; } //设备IP地址 public string manufacturerName { get; set; }//制造厂商名 public string modelName { get; set; } //型号名称 public string deviceType { get; set; } //型号名称 public IntPtr pDeviceInfo; //相机句柄 public float ExposureTime { get; set; } //曝光时间 public float Gain { get; set; } //增益 public float ResultingFrameRate { get; set; } //帧率 public bool isOpenTriggerMode { get; set; } //是否打开触发方式 } public class ASCameraParamInfor { /// /// 曝光时间 /// public float ExposureTime { get; set; } /// /// 增益 /// public float Gain { get; set; } /// /// 获取帧率 /// public float FrameRate { get; set; } } }