443 lines
17 KiB
C#
443 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
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 MvCamCtrl.NET;
|
||
using Newtonsoft.Json.Linq;
|
||
using static ControllerDllCSharp.ClassLibControllerDll;
|
||
namespace ProductionControl.Device
|
||
{
|
||
public class Scanner : IDisposable
|
||
{
|
||
[DllImport("user32.dll")]
|
||
[return: MarshalAs(UnmanagedType.Bool)]
|
||
private static extern bool IsWindow(IntPtr hWnd);
|
||
|
||
public enum ScannerType
|
||
{
|
||
[Description("板卡相机")]
|
||
GENTL = 0,
|
||
[Description("网口相机")]
|
||
CC = 1,
|
||
}
|
||
private ScannerType scannerType;
|
||
|
||
public Action<int, string> log;
|
||
/// <summary>
|
||
/// 拍照回传 (1-num,文件名.bmp)
|
||
/// </summary>
|
||
public Action<int, string> ScanEvent;
|
||
|
||
/// <summary>
|
||
/// 曝光
|
||
/// </summary>
|
||
public float ExposureTime { get; private set; }
|
||
/// <summary>
|
||
/// 增益
|
||
/// </summary>
|
||
public float Gain { get; private set; }
|
||
/// <summary>
|
||
/// 帧率
|
||
/// </summary>
|
||
public float ResultingFrameRate { get; private set; }
|
||
/// <summary>
|
||
/// 是否连续模式
|
||
/// </summary>
|
||
public bool isContinuousMode { 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();
|
||
|
||
#region
|
||
private MyCamera.MV_GENTL_DEV_INFO_LIST m_stGentDeviceList = new MyCamera.MV_GENTL_DEV_INFO_LIST();
|
||
private MyCamera.MV_GENTL_IF_INFO_LIST m_stIFInfoList = new MyCamera.MV_GENTL_IF_INFO_LIST();
|
||
|
||
private MyCamera.MV_CC_DEVICE_INFO_LIST m_stCCDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
|
||
|
||
private MyCamera m_MyCamera = new MyCamera();
|
||
private bool m_bGrabbing = false;//开始采集TAG
|
||
private Thread m_hReceiveThread = null;
|
||
|
||
//显示图像控件句柄
|
||
private IntPtr previewHwnd = IntPtr.Zero;
|
||
//拍照数量
|
||
private int scanNum = 0;
|
||
#endregion
|
||
public Scanner(ScannerType type)
|
||
{
|
||
this.scannerType = type;
|
||
}
|
||
public bool open()
|
||
{
|
||
if (IsInit) return true;
|
||
|
||
System.GC.Collect();
|
||
int nRet;
|
||
if (this.scannerType==ScannerType.GENTL)
|
||
{
|
||
nRet = MyCamera.MV_CC_EnumInterfacesByGenTL_NET(ref m_stIFInfoList, Config.Scanner_GENTL_CTI);
|
||
if (0 != nRet || m_stIFInfoList.nInterfaceNum<1)
|
||
{
|
||
log?.Invoke(2, $"Enumerate interfaces fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
//
|
||
MyCamera.MV_GENTL_IF_INFO stIFInfo = (MyCamera.MV_GENTL_IF_INFO)Marshal.PtrToStructure(m_stIFInfoList.pIFInfo[0], typeof(MyCamera.MV_GENTL_IF_INFO));
|
||
nRet = MyCamera.MV_CC_EnumDevicesByGenTL_NET(ref stIFInfo, ref m_stGentDeviceList);
|
||
if (0 != nRet || m_stGentDeviceList.nDeviceNum<1)
|
||
{
|
||
log?.Invoke(2, $"Enumerate devices fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
// ch:获取选择的设备信息 | en:Get selected device information
|
||
MyCamera.MV_GENTL_DEV_INFO device = (MyCamera.MV_GENTL_DEV_INFO)Marshal.PtrToStructure(m_stGentDeviceList.pDeviceInfo[0], typeof(MyCamera.MV_GENTL_DEV_INFO));
|
||
// ch:打开设备 | en:Open device
|
||
if (null == m_MyCamera)
|
||
{
|
||
m_MyCamera = new MyCamera();
|
||
if (null == m_MyCamera)
|
||
{
|
||
log?.Invoke(2, $"Open device fail!");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_CreateDeviceByGenTL_NET(ref device);
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
log?.Invoke(2, $"Open device fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_OpenDevice_NET();
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
m_MyCamera.MV_CC_DestroyDevice_NET();
|
||
log?.Invoke(2, $"Device open fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
}
|
||
else //CC
|
||
{
|
||
nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stCCDeviceList);
|
||
if (0 != nRet || m_stCCDeviceList.nDeviceNum<1)
|
||
{
|
||
log?.Invoke(2, $"Enumerate devices fail! ({nRet})");
|
||
return false;
|
||
}
|
||
// ch:获取选择的设备信息
|
||
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stCCDeviceList.pDeviceInfo[0], typeof(MyCamera.MV_CC_DEVICE_INFO));
|
||
// ch:打开设备 | en:Open device
|
||
if (null == m_MyCamera)
|
||
{
|
||
m_MyCamera = new MyCamera();
|
||
if (null == m_MyCamera)
|
||
{
|
||
log?.Invoke(2, $"Open device fail!");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
log?.Invoke(2, $"Open device fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_OpenDevice_NET();
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
m_MyCamera.MV_CC_DestroyDevice_NET();
|
||
log?.Invoke(2, $"Open device fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
|
||
if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
|
||
{
|
||
int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET();
|
||
if (nPacketSize > 0)
|
||
{
|
||
nRet = m_MyCamera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
|
||
//if (nRet != MyCamera.MV_OK)
|
||
//{
|
||
// ShowErrorMsg("Set Packet Size failed!", nRet);
|
||
//}
|
||
}
|
||
else
|
||
{
|
||
//ShowErrorMsg("Get Packet Size failed!", nPacketSize);
|
||
}
|
||
}
|
||
}
|
||
// ch:设置采集[软触发/连续]模式 | en:Set Continues Aquisition Mode
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
|
||
setMode(false); //软触发
|
||
|
||
//
|
||
getParam();
|
||
|
||
IsInit = true;
|
||
//timer.Elapsed += Timer_Elapsed;
|
||
//timer.Interval = 100;
|
||
//timer.Enabled = true;
|
||
|
||
return true;
|
||
}
|
||
public void close()
|
||
{
|
||
if (!IsInit) return;
|
||
|
||
IsInit = false;
|
||
// ch:取流标志位清零 | en:Reset flow flag bit
|
||
if (m_bGrabbing == true)
|
||
{
|
||
m_bGrabbing = false;
|
||
m_hReceiveThread.Join();
|
||
}
|
||
// ch:关闭设备 | en:Close Device
|
||
m_MyCamera.MV_CC_CloseDevice_NET();
|
||
m_MyCamera.MV_CC_DestroyDevice_NET();
|
||
}
|
||
/// <summary>
|
||
///
|
||
/// </summary>
|
||
/// <param name="hwnd">显示图像控件句柄</param>
|
||
/// <returns></returns>
|
||
public bool start(IntPtr preview_Hwnd)
|
||
{
|
||
if (!IsInit) return false;
|
||
if (m_bGrabbing) return true;
|
||
|
||
this.previewHwnd= preview_Hwnd;
|
||
// ch:标志位置位true | en:Set position bit true
|
||
m_bGrabbing = true;
|
||
m_hReceiveThread = new Thread(ReceiveThreadProcess);
|
||
m_hReceiveThread.Start();
|
||
|
||
// ch:开始采集 | en:Start Grabbing
|
||
int nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
m_bGrabbing = false;
|
||
m_hReceiveThread.Join();
|
||
log?.Invoke(2, $"Start Grabbing Fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
public bool stop()
|
||
{
|
||
if (!IsInit) return false;
|
||
if (!m_bGrabbing) return true;
|
||
|
||
// ch:标志位设为false | en:Set flag bit false
|
||
m_bGrabbing = false;
|
||
m_hReceiveThread.Join();
|
||
|
||
// ch:停止采集 | en:Stop Grabbing
|
||
int nRet = m_MyCamera.MV_CC_StopGrabbing_NET();
|
||
if (nRet != MyCamera.MV_OK)
|
||
{
|
||
log?.Invoke(2, $"Stop Grabbing Fail! ({nRet})");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
#region private
|
||
/// <summary>
|
||
/// false-软触发 true-连续
|
||
/// </summary>
|
||
/// <param name="type"></param>
|
||
public void setMode(bool isContinuous)
|
||
{
|
||
if (isContinuous)
|
||
{
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
|
||
}
|
||
else
|
||
{
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
|
||
|
||
// ch:触发源选择:0 - Line0;
|
||
// 1 - Line1;
|
||
// 2 - Line2;
|
||
// 3 - Line3;
|
||
// 4 - Counter;
|
||
// 7 - Software;
|
||
//if (cbSoftTrigger.Checked)
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
|
||
//else
|
||
// m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
|
||
}
|
||
|
||
isContinuousMode = isContinuous;
|
||
}
|
||
public void setPreviewWin(IntPtr preview_Hwnd)
|
||
{
|
||
this.previewHwnd = preview_Hwnd;
|
||
}
|
||
public void ReceiveThreadProcess()
|
||
{
|
||
MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
|
||
MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
|
||
int nRet = MyCamera.MV_OK;
|
||
|
||
while (m_bGrabbing)
|
||
{
|
||
nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);
|
||
if (nRet == MyCamera.MV_OK)
|
||
{
|
||
if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType)
|
||
|| stFrameInfo.stFrameInfo.nFrameLen == 0)
|
||
{
|
||
m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
|
||
continue;
|
||
}
|
||
//pictureBox1显示
|
||
if (this.previewHwnd != IntPtr.Zero && IsWindow(this.previewHwnd))
|
||
{
|
||
stDisplayInfo.hWnd = this.previewHwnd;// pictureBox1.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;
|
||
m_MyCamera.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo);
|
||
}
|
||
|
||
//保存
|
||
if (this.scanNum>0)//save tag
|
||
{
|
||
MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
|
||
//lock (BufForDriverLock)
|
||
{
|
||
stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp;
|
||
stSaveFileParam.enPixelType = stFrameInfo.stFrameInfo.enPixelType;
|
||
stSaveFileParam.pData = stFrameInfo.pBufAddr;//m_BufForDriver;
|
||
stSaveFileParam.nDataLen = stFrameInfo.stFrameInfo.nFrameLen;
|
||
stSaveFileParam.nHeight = stFrameInfo.stFrameInfo.nHeight;
|
||
stSaveFileParam.nWidth = stFrameInfo.stFrameInfo.nWidth;
|
||
stSaveFileParam.iMethodValue = 2;
|
||
//Save path
|
||
stSaveFileParam.pImagePath = "Image_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + stFrameInfo.stFrameInfo.nFrameNum.ToString() + ".bmp";
|
||
nRet = m_MyCamera.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
|
||
if (MyCamera.MV_OK == nRet)
|
||
{
|
||
ScanEvent?.Invoke(this.scanNum--, stSaveFileParam.pImagePath);
|
||
}
|
||
}
|
||
}
|
||
//free
|
||
m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
|
||
}
|
||
else
|
||
{
|
||
Thread.Sleep(5);
|
||
}
|
||
}
|
||
}
|
||
// ch:去除自定义的像素格式 | en:Remove custom pixel formats
|
||
private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
|
||
{
|
||
Int32 nResult = ((int)enPixelFormat) & (unchecked((Int32)0x80000000));
|
||
if (0x80000000 == nResult)
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
public void getParam()
|
||
{
|
||
if (!IsInit) return;
|
||
|
||
MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
|
||
int nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
|
||
if (MyCamera.MV_OK == nRet)
|
||
{
|
||
ExposureTime = stParam.fCurValue;//.ToString("F1");
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
|
||
if (MyCamera.MV_OK == nRet)
|
||
{
|
||
Gain = stParam.fCurValue;//.ToString("F1");
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);
|
||
if (MyCamera.MV_OK == nRet)
|
||
{
|
||
ResultingFrameRate = stParam.fCurValue;//.ToString("F1");
|
||
}
|
||
}
|
||
public void setParam(float exposureTime, float gain, float resultingFrameRate)
|
||
{
|
||
if (!IsInit) return;
|
||
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
|
||
int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("ExposureTime", exposureTime);
|
||
if (nRet != MyCamera.MV_OK)
|
||
{
|
||
log?.Invoke(0, $"Set Exposure Time Fail! ({nRet})");
|
||
}
|
||
|
||
m_MyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
|
||
nRet = m_MyCamera.MV_CC_SetFloatValue_NET("Gain", gain);
|
||
if (nRet != MyCamera.MV_OK)
|
||
{
|
||
log?.Invoke(0, $"Set Gain Time Fail! ({nRet})");
|
||
}
|
||
|
||
nRet = m_MyCamera.MV_CC_SetFloatValue_NET("AcquisitionFrameRate", resultingFrameRate);
|
||
if (nRet != MyCamera.MV_OK)
|
||
{
|
||
log?.Invoke(0, $"Set AcquisitionFrameRate Time Fail! ({nRet})");
|
||
}
|
||
}
|
||
|
||
public bool scan(int num)
|
||
{
|
||
if (!IsInit) return false;
|
||
|
||
if (!isContinuousMode)
|
||
{
|
||
// ch:触发命令 | en:Trigger command
|
||
int nRet = m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
|
||
if (MyCamera.MV_OK != nRet)
|
||
{
|
||
log?.Invoke(0, $"Trigger Software Fail! ({nRet})");
|
||
return false;
|
||
}
|
||
}
|
||
this.scanNum= num;
|
||
return true;
|
||
}
|
||
public void Dispose()
|
||
{
|
||
stop();
|
||
}
|
||
}
|
||
}
|