| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- using IKapCDotNet;
- using IKapBoardDotNet;
- using System.Windows.Forms;
- using System.Threading;
- namespace TeamAAS_VP.Core.IKapMethod
- {
- public class IKDevice
- {
- [DllImport("kernel32.dll")]
- public static extern void OutputDebugString(string lpOutputString);
- [DllImport("kernel32.dll")]
- public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
- public static unsafe void CopyLargeMemory(IntPtr dest, IntPtr src, long size)
- {
- if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size));
- // .NET Core 2.1+ / .NET 5+ 支持
- Buffer.MemoryCopy(src.ToPointer(), dest.ToPointer(), size, size);
- }
- delegate void IKapCCallBackDelegate(uint eventType, IntPtr pContext);
- private IKapCCallBackDelegate IKapC_OnGrabStartDelegate;
- private IKapCCallBackDelegate IKapC_OnFrameLostDelegate;
- private IKapCCallBackDelegate IKapC_OnTimeoutDelegate;
- private IKapCCallBackDelegate IKapC_OnFrameReadyDelegate;
- private IKapCCallBackDelegate IKapC_OnGrabStopDelegate;
- delegate void IKapBoardCallBackDelegate(IntPtr pParam);
- private IKapBoardCallBackDelegate IKapB_OnGrabStartDelegate;
- private IKapBoardCallBackDelegate IKapB_OnFrameLostDelegate;
- private IKapBoardCallBackDelegate IKapB_OnTimeoutDelegate;
- private IKapBoardCallBackDelegate IKapB_OnFrameReadyDelegate;
- private IKapBoardCallBackDelegate IKapB_OnGrabStopDelegate;
- // 相机句柄
- public ITKDEVICE m_hDev = new ITKDEVICE();
- // 采集流句柄
- public ITKSTREAM m_hStream = new ITKSTREAM();
- // 缓冲区列表
- public List<ITKBUFFER> m_listBuffer = new List<ITKBUFFER>();
- // 采集卡句柄
- public IntPtr m_pBoard = new IntPtr(-1);
- // 相机缓冲区个数
- public uint m_nFrameCount = 5;
- // 用户缓冲区,用于图像数据转换
- public IntPtr m_pUserBuffer = new IntPtr(-1);
- // 是否正在采集
- public volatile bool m_bGrabingImage = false;
- // 是否已更新用户缓冲区
- public volatile bool m_bUpdateImage = false;
- // 相机类型,0为GV/XGV相机+网卡,1为CL相机,2为CXP相机,3为GV/XGV相机,4为U3V设备
- public int m_nCameraType = -1;
- //相机设置的像素格式
- public StringBuilder m_sPixelFormat = new StringBuilder(128);
- public uint m_nCameraPixelFormat = IKapC.ITKBUFFER_VAL_FORMAT_MONO8;
- //最终出图像素格式
- public uint m_nImagePixelFormat = IKapC.ITKBUFFER_VAL_FORMAT_MONO8;
- //采集卡ImageType数值
- public int m_nImageType = -1;
- // 图像宽度
- public long m_nWidth = 0;
- // 图像高度
- public long m_nHeight = 0;
- // 通道位深
- public int m_nChannelDepth = 8;
- // 图像通道数
- public uint m_nChannels = 1;
- // 像素深度
- public int m_nPixelDepth = 8;
- // BayerPattern: 0:非bayer格式; 1:BGGR; 2:RGGB; 3:GBRG; 4:GRBG
- public int m_nBayerPattern = 0;
- // 相机名
- public string m_devName;
- // 相机索引
- public int m_nDevIndex = -1;
- // 采集卡索引
- public int m_nBoardIndex = -1;
- // 当前帧索引
- public uint m_nCurFrameIndex = 0;
- //缓冲区中图像大小
- public long m_nImageSize = 0;
- // 用户缓冲区锁
- public readonly object m_mutexImage = new object();
- //设备是否打开
- public bool m_bIsOpened = false;
- ///<summary>设备类型:面阵、线阵</summary>
- ///<remarks>TODO:目前Demo只考虑面阵相机处理</remarks>
- public bool m_bIsAreaType = true;
- /*
- *@brief:根据索引开启设备
- *@param [in] nDevIndex:相机索引
- *@param [in] nBoardIndex:采集卡索引
- *@return:是否开启成功
- */
- public virtual bool openDevice(int nDevIndex, int nBoardIndex = -1)
- {
- if (isOpen())
- {
- DebugLog("Device already opened!");
- return true;
- }
- //获取设备信息
- ITKDEV_INFO pDevInfo = new ITKDEV_INFO();
- uint res = IKapC.ItkManGetDeviceInfo((uint)nDevIndex, pDevInfo);
- if (!CheckIKapC(res))
- {
- DebugLog("Get device info failed!");
- return false;
- }
- m_devName = pDevInfo.FullName;
- if (nBoardIndex != -1) //设备:采集卡+相机
- {
- //打开相机
- res = IKapC.ItkDevOpen((uint)nDevIndex, IKapC.ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, ref m_hDev);
- if (!CheckIKapC(res))
- {
- MessageBox.Show("Open camera failed!", "Tool Hint", MessageBoxButtons.OK, MessageBoxIcon.Error);
- DebugLog("Camera error:Open camera failed");
- return false;
- }
- //打开采集卡
- ITK_CXP_DEV_INFO cxp_cam_info = new ITK_CXP_DEV_INFO();
- ITK_GVB_DEV_INFO gvb_cam_info = new ITK_GVB_DEV_INFO();
- ITK_CL_DEV_INFO cl_cam_info = new ITK_CL_DEV_INFO();
- IntPtr info = IntPtr.Zero;
- if (String.Compare(pDevInfo.DeviceClass, "CoaXPress") == 0)
- {
- /// \~chinese 获取CoaXPress相机设备信息 \~english Get CoaXPress camera device information
- res = IKapC.ItkManGetCXPDeviceInfo((uint)nDevIndex, cxp_cam_info);
- CheckIKapC(res);
- info = IKapC.get_itk_cxp_dev_info_IntPtr(cxp_cam_info);
- m_nCameraType = 2;
- }
- else if (String.Compare(pDevInfo.DeviceClass, "GigEVisionBoard") == 0)
- {
- /// \~chinese 获取GigEVision相机设备信息 \~english Get GigEVision camera device information
- res = IKapC.ItkManGetGVBDeviceInfo((uint)nDevIndex, gvb_cam_info);
- CheckIKapC(res);
- info = IKapC.get_itk_gvb_dev_info_IntPtr(gvb_cam_info);
- m_nCameraType = 0;
- }
- else if (String.Compare(pDevInfo.DeviceClass, "CameraLink") == 0)
- {
- /// \~chinese 获取CameraLink相机设备信息 \~english Get CameraLink camera device information
- res = IKapC.ItkManGetCLDeviceInfo((uint)nDevIndex, cl_cam_info);
- CheckIKapC(res);
- info = IKapC.get_itk_cl_dev_info_IntPtr(cl_cam_info);
- m_nCameraType = 1;
- }
- else
- {
- return false;
- }
- m_pBoard = IKapBoard.IKapOpenWithSpecificInfo(info);
- if (m_pBoard == new IntPtr(-1))
- {
- return false;
- }
- if (pDevInfo.DeviceClass == "CameraLink")
- {
- //CL采集卡关闭后,无法保存设置参数,所以必须需要通过配置文件方式配置参数。其他设备可选
- // 导入配置文件
- string configFileName = GetOption();
- if (configFileName == null)
- {
- MessageBox.Show("Fail to get frameGrabber configuration file, using default setting!", "Tool Hint", MessageBoxButtons.OK, MessageBoxIcon.Warning);
- }
- else
- {
- int ret = IKapBoard.IKapLoadConfigurationFromFile(m_pBoard, configFileName);
- CheckIKapBoard(ret);
- }
- }
- m_nBoardIndex = nBoardIndex;
- }
- else
- { //设备:相机
- //打开相机
- res = IKapC.ItkDevOpen((uint)nDevIndex, IKapC.ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, ref m_hDev);
- if (!CheckIKapC(res))
- {
- MessageBox.Show("Open camera failed!", "Tool Hint", MessageBoxButtons.OK, MessageBoxIcon.Error);
- DebugLog("Camera error:Open camera failed");
- return false;
- }
- if (String.Compare(pDevInfo.DeviceClass, "GigEVision") == 0)
- {
- m_nCameraType = 3;
- }
- if (String.Compare(pDevInfo.DeviceClass, "USB3Vision") == 0)
- {
- m_nCameraType = 4;
- }
- }
- m_nDevIndex = nDevIndex;
- m_bIsOpened = true;
- return true;
- }
- /*
- *@brief:关闭相机
- *@param [in]:
- *@return:是否关闭成功
- */
- public virtual bool closeDevice()
- {
- if (isOpen())
- {
- if (m_pBoard != new IntPtr(-1))
- {
- IKapBoard.IKapClose(m_pBoard);
- }
- IKapC.ItkDevClose(m_hDev);
- }
- m_bIsOpened = false;
- return true;
- }
- /*
- *@brief:查询设备连接状态
- *@param [in]:
- *@return:是否连接
- */
- public virtual bool isOpen()
- {
- return m_bIsOpened;
- }
- /*
- *@brief:加载采集卡配置文件
- *@param [in] sFilePath:配置文件路径
- *@return:是否加载成功
- */
- public virtual bool loadConfiguration(string sFilePath)
- {
- int ret = IKapBoard.IKapLoadConfigurationFromFile(m_pBoard, sFilePath);
- return ret == IKapBoard.IK_RTN_OK;
- }
- /*
- * @brief:申请缓冲区资源
- * @return:是否申请成功
- */
- public virtual bool createStream()
- {
- if (m_pBoard != new IntPtr(-1))
- {
- // 设置帧超时时间
- int timeout = -1;
- int ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)IKapBoard.IKP_TIME_OUT, timeout);
- if (!CheckIKapBoard(ret))
- return false;
- // 设置抓取模式,IKP_GRAB_NON_BLOCK为非阻塞模式
- int grab_mode = IKapBoard.IKP_GRAB_NON_BLOCK;
- ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)IKapBoard.IKP_GRAB_MODE, grab_mode);
- if (!CheckIKapBoard(ret))
- return false;
- // 设置帧传输模式,IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT为同步保存模式
- int transfer_mode = IKapBoard.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT;
- ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)IKapBoard.IKP_FRAME_TRANSFER_MODE, transfer_mode);
- if (!CheckIKapBoard(ret))
- return false;
- // 设置缓冲区格式
- ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)IKapBoard.IKP_FRAME_COUNT, (int)m_nFrameCount);
- if (!CheckIKapBoard(ret))
- return false;
- /// \~chinese 注册回调函数时须使用static声明的静态函数,如果使用成员函数的情况下需注意成员函数的生命周期,在该成员函数被释放前需使用 IKapUnRegisterCallback() 取消注册回调函数,否则在成员函数已经被释放的情况下触发回调函数,会引发异常
- /// \~english Use a static function declared with 'static' to register a callback, if using a member function, be aware of the lifetime of the object that owns the member function and unregister the callback by IKapUnRegisterCallback() before the object is destroyed, or if the callback is triggered after the object has been released, it will cause an exception
- //注册采集开始回调
- IKapB_OnGrabStartDelegate = new IKapBoardCallBackDelegate(IKapB_OnGrabStartFunc);
- ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_GrabStart, Marshal.GetFunctionPointerForDelegate(IKapB_OnGrabStartDelegate), IntPtr.Zero);
- if (!CheckIKapBoard(ret))
- return false;
- //注册帧结束回调
- IKapB_OnFrameReadyDelegate = new IKapBoardCallBackDelegate(IKapB_OnFrameReadyFunc);
- /// \~chinese 帧完成回调函数中不应执行耗时操作,应控制在 1s/帧率 的时间内完成,否则可能引起帧丢失
- /// \~english in OnFrameReadyDelegate callback function, should not execute time-consuming operation, and finish in time of 1s/framerate, or could cause framelost
- ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_FrameReady, Marshal.GetFunctionPointerForDelegate(IKapB_OnFrameReadyDelegate), IntPtr.Zero);
- if (!CheckIKapBoard(ret))
- return false;
- //注册采集丢帧回调
- IKapB_OnFrameLostDelegate = new IKapBoardCallBackDelegate(IKapB_OnFrameLostFunc);
- ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_FrameLost, Marshal.GetFunctionPointerForDelegate(IKapB_OnFrameLostDelegate), IntPtr.Zero);
- if (!CheckIKapBoard(ret))
- return false;
- //注册采集超时回调
- IKapB_OnTimeoutDelegate = new IKapBoardCallBackDelegate(IKapB_OnTimeoutFunc);
- ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_TimeOut, Marshal.GetFunctionPointerForDelegate(IKapB_OnTimeoutDelegate), IntPtr.Zero);
- if (!CheckIKapBoard(ret))
- return false;
- //注册帧结束回调
- IKapB_OnGrabStopDelegate = new IKapBoardCallBackDelegate(IKapB_OnGrabStopFunc);
- ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_GrabStop, Marshal.GetFunctionPointerForDelegate(IKapB_OnGrabStopDelegate), IntPtr.Zero);
- if (!CheckIKapBoard(ret))
- return false;
- }
- else
- {
- /*创建流*/
- uint res = IKapC.ItkDevAllocStreamEx(m_hDev, 0, m_nFrameCount, ref m_hStream);
- if (!CheckIKapC(res)) return false;
- /// \~chinese 注册回调函数时须使用static声明的静态函数,如果使用成员函数的情况下需注意成员函数的生命周期,在该成员函数被释放前需使用 ItkStreamUnregisterCallback() 取消注册回调函数,否则在成员函数已经被释放的情况下触发回调函数,会引发异常
- /// \~english Use a static function declared with 'static' to register a callback, if using a member function, be aware of the lifetime of the object that owns the member function and unregister the callback by ItkStreamUnregisterCallback() before the object is destroyed, or if the callback is triggered after the object has been released, it will cause an exception
- //注册采集开始回调
- IKapC_OnGrabStartDelegate = new IKapCCallBackDelegate(IKapC_OnStreamStartFunc);
- res = IKapC.ItkStreamRegisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_START_OF_STREAM, Marshal.GetFunctionPointerForDelegate(IKapC_OnGrabStartDelegate), IntPtr.Zero);
- if (!CheckIKapC(res))
- {
- DebugLog("Configure stream error:Register callback failed");
- return false;
- }
- //注册采集超时回调
- IKapC_OnTimeoutDelegate = new IKapCCallBackDelegate(IKapC_OnTimeOutFunc);
- res = IKapC.ItkStreamRegisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT, Marshal.GetFunctionPointerForDelegate(IKapC_OnTimeoutDelegate), IntPtr.Zero);
- if (!CheckIKapC(res))
- {
- DebugLog("Configure stream error:Register callback failed");
- return false;
- }
- //注册采集丢帧回调
- IKapC_OnFrameLostDelegate = new IKapCCallBackDelegate(IKapC_OnFrameLostFunc);
- res = IKapC.ItkStreamRegisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST, Marshal.GetFunctionPointerForDelegate(IKapC_OnFrameLostDelegate), IntPtr.Zero);
- if (!CheckIKapC(res))
- {
- DebugLog("Configure stream error:Register callback failed");
- return false;
- }
- //注册采集结束回调
- IKapC_OnGrabStopDelegate = new IKapCCallBackDelegate(IKapC_OnStreamEndFunc);
- res = IKapC.ItkStreamRegisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM, Marshal.GetFunctionPointerForDelegate(IKapC_OnGrabStopDelegate), IntPtr.Zero);
- if (!CheckIKapC(res))
- {
- DebugLog("Configure stream error:Register callback failed");
- return false;
- }
- //注册帧结束回调
- IKapC_OnFrameReadyDelegate = new IKapCCallBackDelegate(IKapC_OnFrameReadyFunc);
- /// \~chinese 帧完成回调函数中不应执行耗时操作,应控制在 1s/帧率 的时间内完成,否则可能引起帧丢失
- /// \~english in OnFrameReadyDelegate callback function, should not execute time-consuming operation, and finish in time of 1s/framerate, or could cause framelost
- res = IKapC.ItkStreamRegisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME, Marshal.GetFunctionPointerForDelegate(IKapC_OnFrameReadyDelegate), IntPtr.Zero);
- if (!CheckIKapC(res))
- {
- DebugLog("Configure stream error:Register callback failed");
- return false;
- }
- }
- m_bUpdateImage = false;
- return true;
- }
- /*
- * @brief:清除已申请缓冲区资源
- * @return:
- */
- public virtual void releaseStream()
- {
- if (m_pBoard == new IntPtr(-1)) //设备:相机
- {
- //注销回调函数
- IKapC.ItkStreamUnregisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_START_OF_STREAM);
- IKapC.ItkStreamUnregisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM);
- IKapC.ItkStreamUnregisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST);
- IKapC.ItkStreamUnregisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT);
- IKapC.ItkStreamUnregisterCallback(m_hStream, IKapC.ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME);
- IKapC.ItkDevFreeStream(m_hStream); //释放流
- }
- else
- {
- //设备:相机+采集卡
- //注销回调函数
- IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_GrabStart);
- IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_FrameReady);
- IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_FrameLost);
- IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_TimeOut);
- IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)IKapBoard.IKEvent_GrabStop);
- }
- }
- /*
- *@brief:开始采集前准备工作:获取设备相关信息,申请图像缓冲区
- */
- public bool preStartGrab()
- {
- uint res = IKapC.ITKSTATUS_OK;
- int ret = IKapBoard.IK_RTN_OK;
- // 获取相机像素格式
- uint pixelFormatSize = 128;
- res = IKapC.ItkDevToString(m_hDev, "PixelFormat", m_sPixelFormat, ref pixelFormatSize);
- if (!CheckIKapC(res)) return false;
- res = IKapC.ItkDevGetPixelFormatVal(m_hDev, m_sPixelFormat.ToString(), ref m_nCameraPixelFormat);
- if (!CheckIKapC(res)) return false;
- if (m_sPixelFormat.ToString().Contains("Bayer"))
- {
- //BayerPattern: 0:非bayer格式; 1:BGGR; 2:RGGB; 3:GBRG; 4:GRBG
- if (m_sPixelFormat.ToString().Contains("BayerBG"))
- {
- m_nBayerPattern = 1;
- }
- else if (m_sPixelFormat.ToString().Contains("BayerRG"))
- {
- m_nBayerPattern = 2;
- }
- else if (m_sPixelFormat.ToString().Contains("BayerGB"))
- {
- m_nBayerPattern = 3;
- }
- else if (m_sPixelFormat.ToString().Contains("BayerGR"))
- {
- m_nBayerPattern = 4;
- }
- else
- {
- DebugLog("The Bayer format is not supported!");
- return false;
- }
- }
- if (m_pBoard != new IntPtr(-1)) //设备:采集卡+相机
- {
- ret = IKapBoard.IKapGetInfo64(m_pBoard, (uint)IKapBoard.IKP_IMAGE_WIDTH, ref m_nWidth);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo64(m_pBoard, (uint)IKapBoard.IKP_IMAGE_HEIGHT, ref m_nHeight);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)IKapBoard.IKP_IMAGE_TYPE, ref m_nImageType);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)IKapBoard.IKP_DATA_FORMAT, ref m_nChannelDepth);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)IKapBoard.IKP_BOARD_BIT, ref m_nPixelDepth);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)IKapBoard.IKP_BAYER_PATTERN, ref m_nBayerPattern);
- if (!CheckIKapBoard(ret))
- return false;
- ret = IKapBoard.IKapGetInfo64(m_pBoard, (uint)IKapBoard.IKP_FRAME_SIZE, ref m_nImageSize);
- if (!CheckIKapBoard(ret))
- return false;
- switch (m_nImageType)
- {
- case 0: //IKP_IMAGE_TYPE_VAL_MONOCHROME、Bayer format
- m_nChannels = 1;
- break;
- case 1: //IKP_IMAGE_TYPE_VAL_COLORFUL、IKP_IMAGE_TYPE_VAL_RGB
- case 3: //IKP_IMAGE_TYPE_VAL_BGR
- m_nChannels = 3;
- break;
- case 2: //IKP_IMAGE_TYPE_VAL_RGBC
- case 4: //IKP_IMAGE_TYPE_VAL_BGRC
- m_nChannels = 4;
- break;
- case 5: //IKP_IMAGE_TYPE_VAL_YUV422、IKP_IMAGE_TYPE_VAL_YUV422_YUYV
- DebugLog("YUV image type!");
- m_nChannels = 2;
- break;
- default:
- DebugLog("Not supported image type!");
- return false;
- }
- }
- else
- {
- // 获取图像宽度
- res = IKapC.ItkDevGetInt64(m_hDev, "Width", ref m_nWidth);
- if (!CheckIKapC(res)) return false;
- // 获取图像高度
- res = IKapC.ItkDevGetInt64(m_hDev, "Height", ref m_nHeight);
- if (!CheckIKapC(res)) return false;
- //根据像素格式获取通道深度、像素深度、通道数、bayer格式信息
- m_nChannelDepth = (int)IKapC.ITKBUFFER_FORMAT_CHANNEL_BITS(m_nCameraPixelFormat);
- m_nPixelDepth = (int)IKapC.ITKBUFFER_FORMAT_PIXEL_BITS(m_nCameraPixelFormat);
- m_nChannels = (uint)(m_nPixelDepth / m_nChannelDepth);
- // 获取图像大小
- m_nImageSize = m_nWidth * m_nHeight * m_nPixelDepth >> 3;
- }
- //获取最终出图像素格式
- m_nImagePixelFormat = getImagePixelFormat();
- //申请用户缓冲区缓存图像数据进行图像处理操作
- m_pUserBuffer = Marshal.AllocHGlobal((IntPtr)m_nImageSize);
- // 检查是否分配成功(可能因系统内存不足失败)
- if (m_pUserBuffer == new IntPtr(-1))
- {
- throw new OutOfMemoryException("无法分配指定大小的内存");
- }
- return true;
- }
- /*
- *@brief:开始采集
- *@param [in] nCount:采集帧数
- *@return:是否开始采集
- */
- public virtual bool startGrab(int nCount)
- {
- uint res = IKapC.ITKSTATUS_OK;
- int ret = IKapBoard.IK_RTN_OK;
- bool temp = preStartGrab();
- if (!temp) return false;
- //开始采集
- if (m_pBoard == new IntPtr(-1))
- { //设备类型:相机
- uint nGrabCount = (uint)nCount;
- if (nCount <= 0)
- nGrabCount = IKapC.ITKSTREAM_CONTINUOUS;
- res = IKapC.ItkStreamStart(m_hStream, nGrabCount);
- if (!CheckIKapC(res))
- {
- DebugLog("Start grab error:Start stream failed");
- return false;
- }
- }
- else
- { //设备类型:采集卡+相机
- IKapC.ItkDevExecuteCommand(m_hDev, "AcquisitionStart");
- ret = IKapBoard.IKapStartGrab(m_pBoard, nCount);
- if (!CheckIKapBoard(ret))
- return false;
- }
- m_bUpdateImage = false;
- m_nCurFrameIndex = 0;
- m_bGrabingImage = true;
- return true;
- }
- /*
- *@brief:等待序列采集结束
- *@param [in] nCount:采集帧数
- *@return:是否开始采集
- */
- public virtual bool waitGrab()
- {
- if (m_pBoard == new IntPtr(-1))
- { //设备类型:相机
- uint res = IKapC.ItkStreamWait(m_hStream);
- if (!CheckIKapC(res))
- {
- DebugLog($"Waiting stream operation failed, retured {res}.");
- return false;
- }
- }
- else
- { //设备类型:采集卡+相机
- int ret = IKapBoard.IKapWaitGrab(m_pBoard);
- if (!CheckIKapBoard(ret))
- {
- DebugLog($"Waiting stream operation failed!");
- return false;
- }
- }
- return true;
- }
- /*
- *@brief:停止采集
- *@return:是否停止采集
- */
- public virtual bool stopGrab()
- {
- if (m_pBoard == new IntPtr(-1))
- { //设备类型:相机
- uint res = IKapC.ItkStreamStop(m_hStream);
- if (!CheckIKapC(res))
- {
- DebugLog("Stop grab error:Stop stream failed");
- return false;
- }
- m_bGrabingImage = false;
- }
- else
- { //设备类型:采集卡+相机
- IKapBoard.IKapStopGrab(m_pBoard);
- m_bGrabingImage = false;
- }
- //释放用户缓冲区
- if (m_pUserBuffer != new IntPtr(-1))
- {
- Marshal.FreeHGlobal(m_pUserBuffer);
- m_pUserBuffer = new IntPtr(-1);
- }
- return true;
- }
- public static bool isRGBFormat(uint _pixelFormat)
- {
- if (_pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB888 || _pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB888PACKED || _pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB101010 || _pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB121212 || _pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB141414 || _pixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB161616)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- private uint getReversedColorPixel(uint nOriginalPixelFormat)
- {
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB888PACKED)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR888PACKED;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB888)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR888;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB101010)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR101010;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB121212)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR121212;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB141414)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR141414;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_RGB161616)
- return IKapC.ITKBUFFER_VAL_FORMAT_BGR161616;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR888PACKED)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB888PACKED;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR888)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB888;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR101010)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB101010;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR121212)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB121212;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR141414)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB141414;
- if (nOriginalPixelFormat == IKapC.ITKBUFFER_VAL_FORMAT_BGR161616)
- return IKapC.ITKBUFFER_VAL_FORMAT_RGB161616;
- return nOriginalPixelFormat;
- }
- //根据相机和采集卡设置确定最终输出图像像素格式
- public uint getImagePixelFormat()
- {
- //如果是一代GVB采集卡设备,且相机像素格式为Packed模式,采集卡会自动解Packed
- if (m_nCameraType == 0 && m_sPixelFormat.ToString().Contains("Packed"))
- {
- int originStrLength = m_sPixelFormat.Length;
- string sImagePixelFormat = m_sPixelFormat.ToString(0, originStrLength - 6); //得到采集卡端的像素格式字符串
- uint nPixelFormat = 0;
- uint res = IKapC.ItkDevGetPixelFormatVal(m_hDev, sImagePixelFormat, ref nPixelFormat);
- if (!CheckIKapC(res))
- {
- DebugLog("ItkDevGetPixelFormatVal: Excute failed!");
- }
- else
- {
- return nPixelFormat;
- }
- }
- //如果是CXP采集卡设备,彩色图像通道顺序会翻转
- if (m_nCameraType == 2 && m_nChannels == 3)
- {
- return getReversedColorPixel(m_nCameraPixelFormat);
- }
- return m_nCameraPixelFormat;
- }
- /*
- *@brief:Bayer image transform to RGB image
- *@param [in]:pDataSrc: the buffer of Bayer image
- *@param [in]:nDataSrcFormat: the pixelformat of Bayer image defiend in IKapC
- *@param [out]:pDataDst: the buffer of RGB image
- *@param [in]:nDataSrcFormat: the pixelformat of RGB image defiend in IKapC
- *@param [in]:nWidth: the width of image
- *@param [in]:nHeight: the height of image
- *@param [in]:nBayerEncodeType: the encoding type of Bayer image,optional valid params: 1[BGGR]; 2[RGGB]; 3[GBRG]; 4[GRBG]
- *@return:是否错误
- */
- public unsafe static bool Bayer2RGB(IntPtr pDataSrc, uint nDataSrcFormat, ref IntPtr pDataDst, uint nDataDstFormat, int nWidth, int nHeight, int nBayerEncodeType)
- {
- DebugLog("Bayer2RGB Begin...");
- uint res = IKapC.ITKSTATUS_OK;
- ITKBUFFER itkBufferBayer = new ITKBUFFER();
- ITKBUFFER itkBufferRGB = new ITKBUFFER();
- res = IKapC.ItkBufferNewWithPtr(nWidth, nHeight, nDataSrcFormat, pDataSrc, ref itkBufferBayer);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- res = IKapC.ItkBufferNewWithPtr(nWidth, nHeight, nDataDstFormat, pDataDst, ref itkBufferRGB);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- ///res = IKapC.ItkBufferSave(itkBufferBayer,"./bayer.tif",IKapC.NET.ItkBufferSaveType.ITKBUFFER_VAL_TIFF);
- DebugLog("ItkBufferBayerConvert Begin...");
- res = IKapC.ItkBufferBayerConvert(itkBufferBayer, itkBufferRGB, IKapC.ITKBUFFER_VAL_BAYER_METHOD_BILINEAR | IKapC.IKAPC_BAYER_PATTERN_VAL_FROM_IKAP(nBayerEncodeType)); //ITKBUFFER_VAL_BAYER_METHOD_BILINEAR为最快算法
- DebugLog("ItkBufferBayerConvert End!");
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- ///res = IKapC.ItkBufferSave(itkBufferRGB, "./rgb.tif", IKapC.NET.ItkBufferSaveType.ITKBUFFER_VAL_TIFF);
- //释放资源,否则会造成资源泄露
- res = IKapC.ItkBufferFree(itkBufferBayer);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- res = IKapC.ItkBufferFree(itkBufferRGB);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- DebugLog("Bayer2RGB end!");
- return true;
- }
- public unsafe static bool Convert2BGR(IntPtr pDataSrc, uint nDataSrcFormat, ref IntPtr pDataDst, uint nDataDstFormat, int nWidth, int nHeight, int nBayerEncodeType = 0)
- {
- uint res = IKapC.ITKSTATUS_OK;
- ITKBUFFER itkBufferSrc = new ITKBUFFER();
- ITKBUFFER itkBufferBGR = new ITKBUFFER();
- res = IKapC.ItkBufferNewWithPtr(nWidth, nHeight, nDataSrcFormat, pDataSrc, ref itkBufferSrc);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- res = IKapC.ItkBufferNewWithPtr(nWidth, nHeight, nDataDstFormat, pDataDst, ref itkBufferBGR);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- res = IKapC.ItkBufferConvert(itkBufferSrc, itkBufferBGR, nDataDstFormat, 0);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- //释放资源,否则会造成资源泄露
- res = IKapC.ItkBufferFree(itkBufferSrc);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- res = IKapC.ItkBufferFree(itkBufferBGR);
- if (!IKDevice.CheckIKapC(res))
- {
- return false;
- }
- return true;
- }
- public string GetOption()
- {
- string vlcfFileName = null;
- OpenFileDialog ofd = new OpenFileDialog();
- ofd.Filter = "vlcf文件(*.vlcf)|*.vlcf|所有文件(*.*)|*.*";
- ofd.FilterIndex = 1;
- ofd.Title = "选择打开文件";
- if (ofd.ShowDialog() == DialogResult.OK)
- vlcfFileName = ofd.FileName;
- return vlcfFileName;
- }
- internal static void DebugLog(string message)
- {
- #if DEBUG
- OutputDebugString($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {message}\n");
- #endif
- }
- /*
- *@brief:检查IKapCDotNet接口返回
- *@param [in] err:错误码
- *@return:是否错误
- */
- public static bool CheckIKapC(uint err)
- {
- if (err != IKapC.ITKSTATUS_OK)
- {
- DebugLog("Error code: " + err.ToString("x8"));
- return false;
- }
- return true;
- }
- /*
- *@brief:检查IKapBoardDotNet接口返回
- *@param [in] err:错误码
- *@return:是否错误
- */
- public static bool CheckIKapBoard(int ret)
- {
- if (ret != IKapBoard.IK_RTN_OK)
- {
- IKAPERRORINFO tIKei = new IKAPERRORINFO();
- string sErrMsg = "";
- // 获取错误码信息。
- //
- // Get error code message.
- IKapBoard.IKapGetLastError(tIKei, true);
- // 打印错误信息。
- //
- // Print error message.
- sErrMsg = string.Concat("Error",
- sErrMsg,
- "Board Type\t = 0x", tIKei.uBoardType.ToString("X4"), "\n",
- "Board Index\t = 0x", tIKei.uBoardIndex.ToString("X4"), "\n",
- "Error Code\t = 0x", tIKei.uErrorCode.ToString("X4"), "\n"
- );
- DebugLog(sErrMsg);
- return false;
- }
- return true;
- }
- #region Callback
- // 开始抓帧回调
- public void IKapB_OnGrabStartFunc(IntPtr pParam)
- {
- Console.WriteLine("Start grabbing image");
- }
- // 丢帧回调
- public void IKapB_OnFrameLostFunc(IntPtr pParam)
- {
- Console.WriteLine("Frame lost");
- }
- // 帧超时回调
- public void IKapB_OnTimeoutFunc(IntPtr pParam)
- {
- Console.WriteLine("Grab image timeout");
- }
- // 停止抓取图像回调
- public void IKapB_OnGrabStopFunc(IntPtr pParam)
- {
- Console.WriteLine("Stop grabbing image");
- }
- // 一帧图像完成回调
- public void IKapB_OnFrameReadyFunc(IntPtr pParam)
- {
- IntPtr hPtr = new IntPtr(-1);
- // 获取当前帧状态
- IKAPBUFFERSTATUS status = new IKAPBUFFERSTATUS();
- IKapBoard.IKapGetBufferStatus(m_pBoard, (int)m_nCurFrameIndex, status);
- if (status.uFull == 1)
- {
- IKapBoard.IKapGetBufferAddress(m_pBoard, (int)m_nCurFrameIndex, ref hPtr);
- if (!m_bUpdateImage)
- {
- if (Monitor.TryEnter(m_mutexImage))
- {
- DebugLog("m_mutexImage Monitor.TryEnter successed!");
- CopyLargeMemory(m_pUserBuffer, hPtr, m_nImageSize);
- DebugLog("CL OnFrameReadyFunc: finish buffer data copy!");
- m_bUpdateImage = true;
- Monitor.Exit(m_mutexImage);
- DebugLog("m_mutexImage Monitor.Exit!");
- }
- }
- }
- m_nCurFrameIndex++;
- m_nCurFrameIndex = m_nCurFrameIndex % m_nFrameCount;
- }
- public void IKapC_OnStreamStartFunc(uint eventType, IntPtr pContext)
- {
- DebugLog("Stream start");
- }
- public void IKapC_OnTimeOutFunc(uint eventType, IntPtr pContext)
- {
- DebugLog("Timeout");
- }
- public void IKapC_OnFrameLostFunc(uint eventType, IntPtr pContext)
- {
- DebugLog("Frame lost");
- }
- public void IKapC_OnStreamEndFunc(uint eventType, IntPtr pContext)
- {
- DebugLog("Stream end");
- }
- public void IKapC_OnFrameReadyFunc(uint eventType, IntPtr pContext)
- {
- //获取buffer句柄
- ITKBUFFER hCurrBuffer = new ITKBUFFER();
- uint res = IKapC.ItkStreamGetCurrentBuffer(m_hStream, ref hCurrBuffer);
- if (!CheckIKapC(res))
- {
- DebugLog("Get buffer falied!");
- }
- else
- {
- //获取buffer信息
- ITK_BUFFER_INFO bufferInfo = new ITK_BUFFER_INFO();
- res = IKapC.ItkBufferGetInfo(hCurrBuffer, bufferInfo);
- if (!CheckIKapC(res))
- {
- DebugLog("Get buffer info failed");
- }
- else
- {
- int status = bufferInfo.State;
- if (status == IKapC.ITKBUFFER_VAL_STATE_FULL)
- {
- if (!m_bUpdateImage)
- {
- if (Monitor.TryEnter(m_mutexImage))
- {
- DebugLog("m_mutexImage Monitor.TryEnter successed!");
- CopyLargeMemory(m_pUserBuffer, bufferInfo.ImageAddress, m_nImageSize);
- DebugLog("OnFrameReadyFunc: finish buffer data copy!");
- m_bUpdateImage = true;
- Monitor.Exit(m_mutexImage);
- DebugLog("m_mutexImage Monitor.Exit!");
- }
- }
- }
- else
- {
- DebugLog("Read data error:Buffer is not full");
- }
- }
- }
- }
- #endregion Callback
- }
- }
|