geboshi_V1/LeatherProject/LeatherApp/Device/CamerCardDevIK.cs

911 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define NT //新流程
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using IKapBoardClassLibrary;
using IKapC.NET;
using LeatherApp.Device.CamerUtil;
using LeatherApp.Interface;
using Newtonsoft.Json.Linq;
using OpenCvSharp;
using OpenCvSharp.Dnn;
using ErrorCode = IKapBoardClassLibrary.ErrorCode;
namespace LeatherApp.Device
{
public class CamerCardDevIK : ABSCamerCardDev,IDisposable
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindow(IntPtr hWnd);
[DllImport("kernel32.dll")]
public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
// 相机句柄
//private IKDeviceCL m_pDev = new IKDeviceCL();
public IntPtr m_pDev = new IntPtr(-1);
// 采集卡句柄
public IntPtr m_pBoard = new IntPtr(-1);
// 用户缓冲区,用于图像数据转换
public IntPtr m_pUserBuffer = new IntPtr(-1);
// 是否正在采集
public volatile bool m_bGrabingImage = false;
// 是否已更新用户缓冲区
public volatile bool m_bUpdateImage = false;
// 相机类型0为GV相机1为CL相机2为CXP相机
public int m_nType = -1;
// 图像宽度
public int m_nWidth = -1;
// 图像高度
public int m_nHeight = -1;
// 像素位数
public int m_nDepth = 8;
// 图像通道数
public int m_nChannels = 1;
// 相机索引
public int m_nDevIndex = -1;
// 采集卡索引
public int m_nBoardIndex = -1;
// 相机缓冲区个数
public int m_nFrameCount = 2;//只能1
// 当前帧索引
public int m_nCurFrameIndex = 0;
// 相机缓冲区大小
public int m_nBufferSize = 0;
// 用户缓冲区锁
public object m_mutexImage = new object();
//显示图像控件句柄
private PictureBox previewHwnd = null;
//
// 保存图像的文件名。
public string m_strFileName = "C:\\CSharpImage.bmp";
//
private int scanIndex = 0; //实际拍照从1开始命名因先加的1
private string bmpSavePath;
private Thread readerThread;
private Queue<MyData> frameQueue =new Queue<MyData>();
/// <summary>
/// 曝光 3.00-10000.00
/// </summary>
public float ExposureTime { get; private set; }
/// <summary>
/// 增益 0-23.981199
/// </summary>
public float Gain { get; private set; }
/// <summary>
/// 帧率 0-429496.718750
/// </summary>
public float ResultingFrameRate { get; private set; }
/// <summary>
/// 图片大小
/// </summary>
public System.Drawing.Size size { get; private set; }
/// <summary>
/// 是否打开设备成功
/// </summary>
public bool IsInit { get; private set; } = false;
//public string ErrInfo { get; private set; }
//private System.Timers.Timer timer = new System.Timers.Timer();
private int _scannerCardIndex = 0;//采集卡索引
private int _scannerIndex=0;//相机索引(一个采集卡上可插多个相机)
private IKDeviceInfo devInfo;
BufferToImage hBuffer;
private class MyData
{
public MyData(int _index,Mat _mat)
{
index= _index;
mat = _mat;
}
public int index;
public Mat mat;
}
// 设备类型枚举
enum IKDeviceType
{
DEVICE_NIL = 0,
DEVICE_CML,
DEVICE_CXP,
DEVICE_USB,
DEVICE_GIGEVISION
}
// 设备信息结构体
struct IKDeviceInfo
{
public IKDeviceType nType;
public int nDevIndex;
public int nBoardIndex;
public string sDevName;
}
/// <summary>
/// 读取缓存队列线程
/// </summary>
private void readDataThread()
{
MyData mydate;
while (IsInit)
{
if (frameQueue.Count > 0) // 如果队列不为空则从队列中获取元素
{
lock (frameQueue)
{
mydate = frameQueue.Dequeue();
}
PhotoNumCacheEvent?.Invoke(frameQueue.Count);
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, $"相机({_scannerCardIndex})从缓存队列提取一帧图像({mydate.index}),开始回调(队列剩余帧数:{frameQueue.Count})...", null, null);
ScanEvent?.Invoke(mydate.index, mydate.mat, _scannerCardIndex);
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, $"相机({_scannerCardIndex})图像({mydate.index})回调完成.", null, null);
}
else
{
Thread.Sleep(10);
}
}
}
public override bool readDataImage(out int index, out Mat img, out int dev)
{
MyData mydate;
index = -1;
img = null;
dev = -1;
if (frameQueue.Count > 0) // 如果队列不为空则从队列中获取元素
{
lock (frameQueue)
{
mydate = frameQueue.Dequeue();
}
PhotoNumCacheEvent?.Invoke(frameQueue.Count);
WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"相机({_scannerCardIndex})从缓存队列提取一帧图像({mydate.index}),开始回调(队列剩余帧数:{frameQueue.Count})...", null, null);
//ScanEvent?.Invoke(mydate.index, mydate.mat, _scannerCardIndex);
WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"相机({_scannerCardIndex})图像({mydate.index})回调完成.", null, null);
index = mydate.index;
img = mydate.mat.Clone();
dev = _scannerCardIndex;
return true;
}
else
{
return false;
}
}
public CamerCardDevIK( )
{
m_nType = 1;
}
public override bool open(int nBoardIndex,int nDevIndex)
{
if (IsInit) return true;
_scannerCardIndex = nBoardIndex;
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, "open ....",null,null);
try
{
closeDevice();
scanIndex = 0;
devInfo = new IKDeviceInfo();
readerThread = new Thread(readDataThread); // 创建读取线程
//
uint nDevCount = 2;
uint res = IKapCLib.ItkManGetDeviceCount(ref nDevCount);
if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "ItkManGetDeviceCount failed");
return false;
}
IKapCLib.ITKDEV_INFO pDevInfo = new IKapCLib.ITKDEV_INFO();
IKapCLib.ITK_CL_DEV_INFO pClDevInfo = new IKapCLib.ITK_CL_DEV_INFO();
for (uint i = 0; i < nDevCount; ++i)
{
IKapCLib.ItkManGetDeviceInfo(i, ref pDevInfo);
if (pDevInfo.DeviceClass.CompareTo("CameraLink") == 0)
{
res = IKapCLib.ItkManGetCLDeviceInfo(i, ref pClDevInfo);
//if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK)
// return;
if ((int)pClDevInfo.BoardIndex == nBoardIndex)
{
devInfo.nType = IKDeviceType.DEVICE_CML;
devInfo.nDevIndex = (int)i;
devInfo.nBoardIndex = (int)pClDevInfo.BoardIndex;
devInfo.sDevName = pDevInfo.FullName;
}
}
}
if(devInfo.nType != IKDeviceType.DEVICE_CML)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "对应索引相机不存在 failed");
return false;
}
//
res = IKapCLib.ItkDevOpen((uint)devInfo.nDevIndex
, (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL)
, ref m_pDev);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Camera error:Open camera failed");
return false;
}
//打开采集卡
m_pBoard = IKapBoard.IKapOpen((uint)BoardType.IKBoardPCIE, (uint)devInfo.nBoardIndex);
if (m_pBoard == new IntPtr(-1))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "IKapOpen failed");
return false;
}
IsInit = true;
#if NT
;
#else
readerThread.Start();
#endif
return true;
}
catch (Exception ex)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, ex.Message);
return false;
}
}
public override void close()
{
if (!IsInit) return;
try
{
IsInit = false;
// 清除回调函数。
UnRegisterCallback();
// 关闭设备。
CloseDevice();
}
catch { }
}
/// <summary>
///
/// </summary>
/// <param name="hwnd">显示图像控件句柄</param>
/// <returns></returns>
public override bool start(PictureBox preview_Hwnd,string bmp_save_path)
{
if (!IsInit) return false;
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, "start ....");
// 导入配置文件。
string configFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\" + (_scannerCardIndex==0?Config.Carmer1ConfigFilePath: Config.Carmer2ConfigFilePath);
if (!File.Exists(configFileName))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Fail to get configuration, using default setting!");
return false;
}
var b=loadConfiguration(configFileName);
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, "开始采集 ..."+b.ToString());
this.previewHwnd= preview_Hwnd;
this.bmpSavePath = bmp_save_path;
//开始采集
//第二个参数 nFrameCount 表示希望 IKapBoardClassLibrary 采集的帧数。
//如果 nFrameCount = 1IKapBoardClassLibrary 会从相机中采集一帧图像;
//如果 nFrameCount = N 且 N> 1则 IKapBoardClassLibrary 从相机中采集连续的 N 帧图 像;
//如果 nFrameCount = 0则 IKapBoardClassLibrary 开始连续采集图像。
int ret;
// 设置抓取模式IKP_GRAB_NON_BLOCK为非阻塞模式
//int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK;
//ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode);
//if (ret != (int)ErrorCode.IK_RTN_OK)
// return false;
//// 设置帧传输模式IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT为同步保存模式
//int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT;
//ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode);
//if (ret != (int)ErrorCode.IK_RTN_OK)
// return false;
//设置缓冲区格式
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_COUNT, 1);//
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
// 设置帧超时时间
int timeout = -1;
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_TIME_OUT, timeout);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
// 设置采集模式。
//
// Set grab mode.
int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK;
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
// 设置传输模式。
int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT;
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
// 注册回调函数
IntPtr hPtr = new IntPtr(-1);
OnGrabStartProc = new IKapCallBackProc(OnGrabStartFunc);
ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStart, Marshal.GetFunctionPointerForDelegate(OnGrabStartProc), hPtr);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
OnFrameReadyProc = new IKapCallBackProc(OnFrameReadyFunc);
ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameReady, Marshal.GetFunctionPointerForDelegate(OnFrameReadyProc), hPtr);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
OnFrameLostProc = new IKapCallBackProc(OnFrameLostFunc);
ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameLost, Marshal.GetFunctionPointerForDelegate(OnFrameLostProc), hPtr);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
OnTimeoutProc = new IKapCallBackProc(OnTimeoutFunc);
ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_TimeOut, Marshal.GetFunctionPointerForDelegate(OnTimeoutProc), hPtr);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
OnGrabStopProc = new IKapCallBackProc(OnGrabStopFunc);
ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStop, Marshal.GetFunctionPointerForDelegate(OnGrabStopProc), hPtr);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
m_bUpdateImage = false;
m_nCurFrameIndex = 0;
ret = IKapBoard.IKapStartGrab(m_pBoard, 0);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
//createBuffer
b = createBuffer();
if (!b)
return false;
getParam();
//
m_bGrabingImage = true;
return true;
}
/// <summary>
/// 停止采集
/// </summary>
public override void stop()
{
if (!IsInit) return;
try
{
// 停止图像采集。
var ret = IKapBoard.IKapStopGrab(m_pBoard);
clearBuffer();
CheckIKapBoard(ret);
}
catch
{
return;
}
}
/// <summary>
/// num 因拍了一张后回传的当前已经是1了
/// </summary>
/// <param name="num"></param>
public override void resetScanIndex()
{
scanIndex = 0;//
}
public override void getParam()
{
if (!IsInit) return;
string result;
result = getFeatureValue("ExposureTime");
if (!string.IsNullOrEmpty(result))
ExposureTime = Convert.ToSingle(result);
result = getFeatureValue("Gain");
if (!string.IsNullOrEmpty(result))
Gain = Convert.ToSingle(result);
}
/// <summary>
///
/// </summary>
/// <param name="exposureTime">曝光</param>
/// <param name="gain">增益</param>
/// <param name="resultingFrameRate">帧率</param>
public override bool setParam(float exposureTime, float gain =-1, float resultingFrameRate =-1)
{
if (!IsInit) return false;
bool change = false;
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"ExposureTime: {exposureTime},{ExposureTime}");
if (exposureTime != ExposureTime && exposureTime != -1)
{
if(setFeatureValue("ExposureTime", exposureTime.ToString()))
change = true;
}
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"Gain: {gain},{Gain}");
if (gain != Gain && gain != -1)
{
if (setFeatureValue("Gain", gain.ToString()))
change = true;
}
//if (resultingFrameRate != ResultingFrameRate && resultingFrameRate != -1)
//{
// cDeviceParam.SetFloatValue("AcquisitionFrameRate", resultingFrameRate);
// change = true;
//}
//
if (change)
getParam();
return change;
}
public void Dispose()
{
stop();
close();
}
//---------------
/* @brief设置行触发参数。
*
* @briefSet line trigger parameters. */
void SetLineTrigger()
{
int ret = (int)ErrorCode.IK_RTN_OK;
// 设置CC1信号源。
//
// Set CC1 signal source.
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_CC1_SOURCE, (int)CCSource.IKP_CC_SOURCE_VAL_INTEGRATION_SIGNAL1);
CheckIKapBoard(ret);
// 设置积分控制方法触发信号源。
//
// Set integration control method trigger source.
ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_INTEGRATION_TRIGGER_SOURCE, (int)IntegrationTriggerSource.IKP_INTEGRATION_TRIGGER_SOURCE_VAL_SHAFT_ENCODER1);
CheckIKapBoard(ret);
}
/* @brief清除回调函数。
*
* @briefUnregister callback functions. */
private void UnRegisterCallback()
{
int ret = (int)ErrorCode.IK_RTN_OK;
ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStart);
ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameReady);
ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameLost);
ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_TimeOut);
ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStop);
}
/* @brief关闭设备。
*
* @briefClose device. */
private void CloseDevice()
{
// 关闭采集卡设备。
//
// Close frame grabber device.
if (!m_pBoard.Equals(-1))
{
IKapBoard.IKapClose(m_pBoard);
m_pBoard = (IntPtr)(-1);
}
}
/* @brief判断 IKapBoard 函数是否成功调用。
* @param[in] ret函数返回值。
*
* @briefDetermine whether the IKapBoard function is called successfully.
* @param[in] retFunction return value. */
static void CheckIKapBoard(int ret)
{
if (ret != (int)ErrorCode.IK_RTN_OK)
{
string sErrMsg = "";
IKapBoard.IKAPERRORINFO tIKei = new IKapBoardClassLibrary.IKapBoard.IKAPERRORINFO();
// 获取错误码信息。
IKapBoard.IKapGetLastError(ref tIKei, true);
// 打印错误信息。
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"
);
throw new Exception(sErrMsg);
}
}
#region Callback
delegate void IKapCallBackProc(IntPtr pParam);
/* @brief本函数被注册为一个回调函数。当图像采集开始时函数被调用。
*
* @briefThis function is registered as a callback function. When starting grabbing images, the function will be called. */
private IKapCallBackProc OnGrabStartProc;
/* @brief本函数被注册为一个回调函数。当采集丢帧时函数被调用。
*
* @briefThis function is registered as a callback function. When grabbing frame lost, the function will be called. */
private IKapCallBackProc OnFrameLostProc;
/* @brief本函数被注册为一个回调函数。当图像采集超时时函数被调用。
*
* @briefThis function is registered as a callback function. When grabbing images time out, the function will be called. */
private IKapCallBackProc OnTimeoutProc;
/* @brief本函数被注册为一个回调函数。当一帧图像采集完成时函数被调用。
*
* @briefThis function is registered as a callback function. When a frame of image grabbing ready, the function will be called. */
private IKapCallBackProc OnFrameReadyProc;
/* @brief本函数被注册为一个回调函数。当图像采集停止时函数被调用。
*
* @briefThis function is registered as a callback function. When stopping grabbing images, the function will be called. */
private IKapCallBackProc OnGrabStopProc;
#endregion
#region Callback
/* @brief本函数被注册为一个回调函数。当图像采集开始时函数被调用。
* @param[in] pParam输入参数。
*
* @briefThis function is registered as a callback function. When starting grabbing images, the function will be called.
* @param[in] pParamInput parameter. */
public void OnGrabStartFunc(IntPtr pParam)
{
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, "图像开始采集...", null, null);
}
/* @brief本函数被注册为一个回调函数。当采集丢帧时函数被调用。
* @param[in] pParam输入参数。
*
* @briefThis function is registered as a callback function. When grabbing frame lost, the function will be called.
* @param[in] pParamInput parameter. */
public void OnFrameLostFunc(IntPtr pParam)
{
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.High, $"相机({_scannerCardIndex})采集图像({scanIndex})丢帧(Image frame lost),急停告警,需结束重新开始!!!", null, null);
}
/* @brief本函数被注册为一个回调函数。当图像采集超时时函数被调用。
* @param[in] pParam输入参数。
*
* @briefThis function is registered as a callback function. When grabbing images time out, the function will be called.
* @param[in] pParamInput parameter. */
public void OnTimeoutFunc(IntPtr pParam)
{
WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.High, $"相机({_scannerCardIndex})采集图像({scanIndex})超时(Grab image timeout),请检查采集卡!", null, null);
}
/* @brief本函数被注册为一个回调函数。当一帧图像采集完成时函数被调用。
* @param[in] pParam输入参数。
*
* @briefThis function is registered as a callback function. When a frame of image grabbing ready, the function will be called.
* @param[in] pParamInput parameter. */
public void OnFrameReadyFunc(IntPtr pParam)
{
try
{
Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Start();
int index = ++scanIndex;
WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"OnFrameReadyFunc 相机({_scannerCardIndex})一帧图像({index})采集完成,正在加入队列({frameQueue.Count})...", null, null);
IntPtr hPtr = new IntPtr(-1);
// 获取当前帧状态
var ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_CURRENT_BUFFER_INDEX, ref m_nCurFrameIndex);
if (ret != (int)ErrorCode.IK_RTN_OK)
return;
//IKapBoard.IKAPBUFFERSTATUS status = new IKapBoard.IKAPBUFFERSTATUS();
//IKapBoard.IKapGetBufferStatus(m_pBoard, m_nCurFrameIndex, ref status);
//var uFull = status.uFull;
//if (uFull == 1)//指明缓冲区是否为满
{
IKapBoard.IKapGetBufferAddress(m_pBoard, m_nCurFrameIndex, ref hPtr);
//Monitor.Enter(m_mutexImage);
lock (m_mutexImage)
{
CopyMemory(m_pUserBuffer, hPtr, m_nBufferSize);
m_bUpdateImage = true;
Mat mat = new Mat(m_nHeight, m_nWidth, MatType.CV_8UC3, m_pUserBuffer);
//var bmp = hBuffer.toBmp(m_pUserBuffer);
//Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
//bmp.Dispose();
//bmp = null;
//Monitor.Enter(frameQueue);
lock (frameQueue)
frameQueue.Enqueue(new MyData(index, mat.Clone()));
PhotoNumCacheEvent?.BeginInvoke(frameQueue.Count, null, null);
}
}
//m_nCurFrameIndex++;
//m_nCurFrameIndex = m_nCurFrameIndex % m_nFrameCount;
stopwatch.Stop();
WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"OnFrameReadyFunc 相机({_scannerCardIndex})一帧图像({index})已加入队列({frameQueue.Count}).缓冲区索引={m_nCurFrameIndex};用时:{stopwatch.ElapsedMilliseconds}ms", null, null);
}
catch (Exception ex)
{
WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.High, $"OnFrameReadyFunc 异常,急停告警,需结束重新开始!!!{ex.Message}\r\n{ex.StackTrace}", null, null);
}
}
/* @brief本函数被注册为一个回调函数。当图像采集停止时函数被调用。
* @param[in] pParam输入参数。
*
* @briefThis function is registered as a callback function. When stopping grabbing images, the function will be called.
* @param[in] pParamInput parameter. */
public void OnGrabStopFunc(IntPtr pParam)
{
Console.WriteLine("Stop grabbing image");
}
#endregion
private byte[] bmp2bytes(Bitmap bmp)
{
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释
ms.Close();
bmp.Dispose();
return bytes;
}
private Bitmap bytes2bmp(byte[] bytes)
{
MemoryStream ms1 = new MemoryStream(bytes);
Bitmap bm = (Bitmap)Image.FromStream(ms1);
ms1.Close();
return bm;
}
/*
* @brief:设置相机特征值
* @param [in] featureName:特征名[ExposureTime,Gain]
* @param [in] featureValue:特征值
* @return: 是否设置成功
*/
private bool setFeatureValue(string featureName, string featureValue)
{
IntPtr itkFeature = new IntPtr(-1);
uint nType = 0;
uint res = IKapCLib.ItkDevAllocFeature(m_pDev, featureName, ref itkFeature);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Allocate feature failed");
return false;
}
res = IKapCLib.ItkFeatureGetType(itkFeature, ref nType);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Get feature type failed");
return false;
}
switch (nType)
{
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT32:
res = IKapCLib.ItkFeatureSetInt32(itkFeature, Convert.ToInt32(featureValue));
break;
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT64:
res = IKapCLib.ItkFeatureSetInt64(itkFeature, Convert.ToInt64(featureValue));
break;
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_FLOAT:
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_DOUBLE:
res = IKapCLib.ItkFeatureSetDouble(itkFeature, Convert.ToDouble(featureValue));
break;
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_ENUM:
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_STRING:
res = IKapCLib.ItkFeatureFromString(itkFeature, featureValue);
break;
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_COMMAND:
res = IKapCLib.ItkFeatureExecuteCommand(itkFeature);
break;
}
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Set feature failed:" + res);
return false;
}
return true;
}
private string getFeatureValue(string featureName)
{
IntPtr itkFeature = new IntPtr(-1);
uint nType = 0;
uint res = IKapCLib.ItkDevAllocFeature(m_pDev, featureName, ref itkFeature);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Allocate feature failed");
return "";
}
res = IKapCLib.ItkFeatureGetType(itkFeature, ref nType);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature type failed");
return "";
}
switch (nType)
{
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT32:
int result = 0;
res = IKapCLib.ItkFeatureGetInt32(itkFeature,ref result);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res);
return "";
}
return result.ToString();
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT64:
long resultL = 0;
res = IKapCLib.ItkFeatureGetInt64(itkFeature, ref resultL);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res);
return "";
}
return resultL.ToString();
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_FLOAT:
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_DOUBLE:
double resultD = 0;
res = IKapCLib.ItkFeatureGetDouble(itkFeature, ref resultD);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res);
return "";
}
return resultD.ToString();
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_ENUM:
case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_STRING:
string results = "";
res = IKapCLib.ItkFeatureFromString(itkFeature, results);
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res);
return "";
}
return results;
}
if (!Check(res))
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res);
return "";
}
return "";
}
public override double[] getFeatureRangeValue(string featureName)
{
switch (featureName)
{
case "ExposureTime":
//return new double[2] {3.2,63997};
return new double[2] { 10, 200 };
case "Gain":
return new double[2] { 0.01, 8.00 };
default: return new double[0] { };
}
}
/*
*@brief:检查错误码
*@param [in] err:错误码
*@return:是否错误
*/
private static bool Check(uint err)
{
if (err != (uint)ItkStatusErrorId.ITKSTATUS_OK)
{
System.Diagnostics.Debug.WriteLine("Error code: {0}.\n", err.ToString("x8"));
return false;
}
return true;
}
//----
private bool isOpen()
{
return m_pDev != new IntPtr(-1) && m_pBoard != new IntPtr(-1);
}
private bool closeDevice()
{
frameQueue.Clear();
if (isOpen())
{
IKapBoard.IKapClose(m_pBoard);
IKapCLib.ItkDevClose(m_pDev);
}
return true;
}
private bool loadConfiguration(string sFilePath)
{
int ret = IKapBoard.IKapLoadConfigurationFromFile(m_pBoard, sFilePath);
return ret == (int)ErrorCode.IK_RTN_OK;
}
private bool createBuffer()
{
int ret = (int)ErrorCode.IK_RTN_OK;
int nImageType = 0;
ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_WIDTH, ref m_nWidth);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_HEIGHT, ref m_nHeight);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_TYPE, ref nImageType);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_DATA_FORMAT, ref m_nDepth);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_SIZE, ref m_nBufferSize);
if (ret != (int)ErrorCode.IK_RTN_OK)
return false;
switch (nImageType)
{
case 0:
m_nChannels = 1;
break;
case 1:
case 3:
m_nChannels = 3;
break;
case 2:
case 4:
m_nChannels = 4;
break;
}
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"图片类型:{nImageType},通道数:{m_nChannels},size:{m_nWidth}*{m_nHeight}");
m_pUserBuffer = Marshal.AllocHGlobal(m_nBufferSize);
//
hBuffer = new BufferToImage(m_nBufferSize , m_nDepth, m_nChannels , m_nWidth, m_nHeight);
return true;
}
private void clearBuffer()
{
if (m_pUserBuffer == new IntPtr(-1))
return;
Marshal.FreeHGlobal(m_pUserBuffer);
m_pUserBuffer = new IntPtr(-1);
}
}
}