using MVSDK;
|
using LB_VisionProcesses;
|
using Newtonsoft.Json.Linq;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Drawing.Imaging;
|
using System.Dynamic;
|
using System.Linq;
|
using System.Net.NetworkInformation;
|
using System.Runtime.InteropServices;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
|
|
|
//相机句柄,SDK支持同时打开多个相机,用该句柄区分多相机
|
using CameraHandle = System.Int32;
|
using LB_VisionProcesses.Cameras;
|
|
namespace LB_VisionProcesses.Cameras.MindCameras
|
{
|
public class MindCamera : BaseCamera
|
{
|
#region variable
|
public CameraHandle m_hCamera = 0; // 句柄
|
protected IntPtr m_ImageBuffer; // 预览通道RGB图像缓存
|
protected IntPtr m_ImageBufferSnapshot; // 抓拍通道RGB图像缓存
|
protected tSdkCameraCapbility tCameraCapability; // 相机特性描述
|
protected int m_iDisplayedFrames = 0; //已经显示的总帧数
|
protected CAMERA_SNAP_PROC m_CaptureCallback;
|
protected IntPtr m_iCaptureCallbackCtx; //图像回调函数的上下文参数
|
protected Thread m_tCaptureThread; //图像抓取线程
|
public bool m_bExitCaptureThread = false;//采用线程采集时,让线程退出的标志
|
protected IntPtr m_iSettingPageMsgCallbackCtx; //相机配置界面消息回调函数的上下文参数
|
protected tSdkFrameHead m_tFrameHead;
|
protected tSdkFrameHead m_pFrameHead;
|
//protected SnapshotDlg m_DlgSnapshot = new SnapshotDlg(); //显示抓拍图像的窗口
|
protected bool m_bEraseBk = false;
|
protected bool m_bSaveImage = false;
|
public const Int32 EXT_TRIG_MASK_LEVEL_MODE = 2;
|
public IntPtr m_Grabber = IntPtr.Zero;
|
protected tSdkCameraDevInfo m_DevInfo;
|
protected tSdkCameraCapbility m_tSdkCameraCapbility; // 相机特性描述
|
protected ColorPalette m_GrayPal;
|
protected pfnCameraGrabberFrameCallback m_FrameCallback;
|
|
// 创建 CancellationTokenSource 实例
|
CancellationTokenSource cts = new CancellationTokenSource();
|
#endregion
|
|
public MindCamera() : base()
|
{
|
Brand = CameraBrand.MindCamera;
|
}
|
|
public override bool AutoBalanceWhite()
|
{
|
throw new NotImplementedException();
|
}
|
|
public override bool CloseDevice()
|
{
|
try
|
{
|
if (m_hCamera == 0)
|
return true;
|
MvApi.CameraUnInit(m_hCamera);
|
Marshal.FreeHGlobal(m_ImageBuffer);
|
Marshal.FreeHGlobal(m_ImageBufferSnapshot);
|
MvApi.CameraGrabber_Destroy(m_Grabber);
|
m_hCamera = 0;
|
SN = string.Empty;
|
m_bExitCaptureThread = true;
|
isGrabbing = false;
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public override bool GetExpouseTime(out double value)
|
{
|
try
|
{
|
double exp = 0;
|
MvApi.CameraGetExposureTime(m_hCamera, ref exp);
|
value = Convert.ToDouble(exp);
|
return true;
|
}
|
catch { value = 0; return false; }
|
}
|
|
public override bool GetGain(out double value)
|
{
|
try
|
{
|
MvApi.CameraGetAnalogGainX(m_hCamera, out float Gain);
|
value = Convert.ToDouble(Gain);
|
return true;
|
}
|
catch { value = 0; return false; }
|
}
|
|
public override bool GetLineStatus(IOLines line, out LineStatus lineStatus)
|
{
|
try
|
{
|
uint bchek = 0;
|
MvApi.CameraGetIOState(m_hCamera, (int)line, ref bchek);
|
lineStatus = (LineStatus)bchek;
|
return true;
|
}
|
catch { lineStatus = LineStatus.Low; return false; }
|
}
|
|
public override List<string> GetListEnum()
|
{
|
tSdkCameraDevInfo[] tCameraDevInfoList;
|
List<string> CamInfo = new List<string>();
|
CameraSdkStatus status = MvApi.CameraEnumerateDevice(out tCameraDevInfoList);
|
if (status == CameraSdkStatus.CAMERA_STATUS_SUCCESS)
|
{
|
foreach (var tCameraDevInfo in tCameraDevInfoList)
|
{
|
string sn = System.Text.Encoding.UTF8.GetString(tCameraDevInfo.acSn);
|
// 查找第一个 \0 的位置
|
int nullIndex = System.Text.Encoding.UTF8.GetString(tCameraDevInfo.acSn).IndexOf('\0');
|
if (nullIndex != -1)
|
{
|
// 截取 \0 之前的部分
|
sn = sn.Substring(0, nullIndex);
|
}
|
CamInfo.Add(sn);
|
|
}
|
}
|
return CamInfo;
|
}
|
|
public override bool GetTriggerDelay(out double delay)
|
{
|
try
|
{
|
uint value = 0;
|
MvApi.CameraGetTriggerDelayTime(m_hCamera, ref value);
|
delay = Convert.ToDouble(value);
|
return true;
|
}
|
catch { delay = 0; return false; }
|
}
|
|
public override bool GetTriggerFliter(out double flitertime)
|
{
|
try
|
{
|
uint value = 0;
|
MvApi.CameraGetExtTrigJitterTime(m_hCamera, ref value);
|
flitertime = Convert.ToDouble(value);
|
return true;
|
}
|
catch { flitertime = 0; return false; }
|
}
|
|
public override bool GetTriggerMode(out TriggerMode mode, out TriggerSource source)
|
{
|
try
|
{
|
int nRet = 0;
|
MvApi.CameraGetTriggerMode(m_hCamera, ref nRet);
|
switch (nRet)
|
{
|
case 0:
|
mode = TriggerMode.Off;
|
source = TriggerSource.Software;
|
break;
|
case 1:
|
mode = TriggerMode.On;
|
source = TriggerSource.Software;
|
break;
|
case 2:
|
mode = TriggerMode.On;
|
source = TriggerSource.Line0;
|
break;
|
default:
|
mode = TriggerMode.Off;
|
source = TriggerSource.Software;
|
break;
|
}
|
return true;
|
}
|
catch
|
{
|
mode = TriggerMode.Off;
|
source = TriggerSource.Software;
|
return false;
|
}
|
}
|
|
public override bool GetTriggerPolarity(out TriggerPolarity polarity)
|
{
|
try
|
{
|
int nRet = 0;
|
MvApi.CameraGetExtTrigSignalType(m_hCamera, ref nRet);
|
polarity = (TriggerPolarity)nRet;
|
return true;
|
}
|
catch { polarity = TriggerPolarity.RisingEdge; return false; }
|
}
|
|
public override bool InitDevice(string CamSN, object handle)
|
{
|
if (!(handle is IntPtr) || handle == null)
|
{
|
MessageBox.Show("初始化失败,窗体句柄为null !", "异常");
|
return false;
|
}
|
|
tSdkCameraDevInfo[] tCameraDevInfoList;
|
CameraSdkStatus status = MvApi.CameraEnumerateDevice(out tCameraDevInfoList);
|
if (status == CameraSdkStatus.CAMERA_STATUS_SUCCESS)
|
{
|
foreach (var item in tCameraDevInfoList)
|
{
|
string acSn = System.Text.Encoding.UTF8.GetString(item.acSn);
|
if (acSn.Contains(CamSN))
|
{
|
tSdkCameraDevInfo tCameraDevInfo = item;
|
status = MvApi.CameraGrabber_Create(out m_Grabber, ref tCameraDevInfo);
|
|
if (status == 0)
|
{
|
MvApi.CameraGrabber_GetCameraDevInfo(m_Grabber, out m_DevInfo);
|
MvApi.CameraGrabber_GetCameraHandle(m_Grabber, out m_hCamera);
|
MvApi.CameraGetCapability(m_hCamera, out m_tSdkCameraCapbility);
|
|
//让SDK来根据相机的型号动态创建该相机的配置窗口。
|
MvApi.CameraCreateSettingPage(m_hCamera, (IntPtr)handle, m_DevInfo.acFriendlyName, null, (IntPtr)0, 0);
|
|
// 黑白相机设置ISP输出灰度图像
|
// 彩色相机ISP默认会输出BGR24图像
|
//获得相机特性描述
|
MvApi.CameraGetCapability(m_hCamera, out tCameraCapability);
|
|
m_ImageBuffer = Marshal.AllocHGlobal(tCameraCapability.sResolutionRange.iWidthMax * tCameraCapability.sResolutionRange.iHeightMax * 3 + 1024);
|
|
if (tCameraCapability.sIspCapacity.bMonoSensor != 0)
|
{
|
MvApi.CameraSetIspOutFormat(m_hCamera, (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
|
|
// 创建灰度调色板
|
Bitmap Image = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
|
m_GrayPal = Image.Palette;
|
for (int Y = 0; Y < m_GrayPal.Entries.Length; Y++)
|
m_GrayPal.Entries[Y] = System.Drawing.Color.FromArgb(255, Y, Y, Y);
|
}
|
|
m_ImageBufferSnapshot = Marshal.AllocHGlobal(tCameraCapability.sResolutionRange.iWidthMax * tCameraCapability.sResolutionRange.iHeightMax * 3 + 1024);
|
//设置抓拍通道的分辨率。
|
tSdkImageResolution tResolution;
|
tResolution.uSkipMode = 0;
|
tResolution.uBinAverageMode = 0;
|
tResolution.uBinSumMode = 0;
|
tResolution.uResampleMask = 0;
|
tResolution.iVOffsetFOV = 0;
|
tResolution.iHOffsetFOV = 0;
|
tResolution.iWidthFOV = tCameraCapability.sResolutionRange.iWidthMax;
|
tResolution.iHeightFOV = tCameraCapability.sResolutionRange.iHeightMax;
|
tResolution.iWidth = tResolution.iWidthFOV;
|
tResolution.iHeight = tResolution.iHeightFOV;
|
//tResolution.iIndex = 0xff;表示自定义分辨率,如果tResolution.iWidth和tResolution.iHeight
|
//定义为0,则表示跟随预览通道的分辨率进行抓拍。抓拍通道的分辨率可以动态更改。
|
//本例中将抓拍分辨率固定为最大分辨率。
|
tResolution.iIndex = 0xff;
|
tResolution.acDescription = new byte[32];//描述信息可以不设置
|
tResolution.iWidthZoomHd = 0;
|
tResolution.iHeightZoomHd = 0;
|
tResolution.iWidthZoomSw = 0;
|
tResolution.iHeightZoomSw = 0;
|
|
// 设置为Off会一直触发回调
|
SetTriggerMode(TriggerMode.On, TriggerSource.Software);
|
|
MvApi.CameraSetResolutionForSnap(m_hCamera, ref tResolution);
|
#if USE_CALL_BACK
|
//m_CaptureCallback = new CAMERA_SNAP_PROC(ImageCaptureCallback);
|
//MvApi.CameraSetCallbackFunction(m_hCamera, m_CaptureCallback, m_iCaptureCallbackCtx, ref pCaptureCallOld);
|
// 为了演示如何在回调中使用相机数据创建Bitmap并显示到PictureBox中,这里不使用SDK内置的绘制操作
|
//MvApi.CameraGrabber_SetHWnd(m_Grabber, this.DispWnd.Handle);
|
//MvApi.CameraGrabber_StartLive(m_Grabber);
|
|
//设置回调函数
|
m_FrameCallback = new pfnCameraGrabberFrameCallback(CameraGrabberFrameCallback);
|
MvApi.CameraGrabber_SetRGBCallback(m_Grabber, m_FrameCallback, IntPtr.Zero);
|
#else //如果需要采用多线程,使用下面的方式
|
m_bExitCaptureThread = false;
|
cts = new CancellationTokenSource();
|
m_tCaptureThread = new Thread(() => CaptureThreadProc(cts.Token));
|
//m_tCaptureThread.Start();
|
cts.Cancel(); // 请求取消线程
|
#endif
|
|
//设置回调函数
|
m_FrameCallback = new pfnCameraGrabberFrameCallback(CameraGrabberFrameCallback);
|
MvApi.CameraGrabber_SetRGBCallback(m_Grabber, m_FrameCallback, IntPtr.Zero);
|
|
//设置相机参数组
|
MvApi.CameraLoadParameter(m_hCamera, (int)emSdkParameterTeam.PARAMETER_TEAM_A);
|
|
if (!StartGrabbing())
|
{
|
Debug.WriteLine("开始采集失败");
|
return false;
|
}
|
|
this.SN = CamSN;
|
return true;
|
}
|
else
|
{
|
MessageBox.Show(String.Format("打开相机失败,原因:{0}", status), "异常");
|
return false;
|
}
|
}
|
}
|
}
|
return false;
|
}
|
|
private void CameraGrabberFrameCallback(IntPtr Grabber, IntPtr pFrameBuffer, ref tSdkFrameHead pFrameHead, IntPtr Context)
|
{
|
try
|
{
|
//说明相机处于实时
|
if (!cts.Token.IsCancellationRequested)
|
return;
|
|
// 数据处理回调
|
|
// 由于黑白相机在相机打开后设置了ISP输出灰度图像
|
// 因此此处pFrameBuffer=8位灰度数据
|
// 否则会和彩色相机一样输出BGR24数据
|
|
// 彩色相机ISP默认会输出BGR24图像
|
// pFrameBuffer=BGR24数据
|
|
// 执行一次GC,释放出内存
|
GC.Collect();
|
|
// 由于SDK输出的数据默认是从底到顶的,转换为Bitmap需要做一下垂直镜像
|
MvApi.CameraFlipFrameBuffer(pFrameBuffer, ref pFrameHead, 1);
|
|
int w = pFrameHead.iWidth;
|
int h = pFrameHead.iHeight;
|
Boolean gray = (pFrameHead.uiMediaType == (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
|
|
// 如果是灰度图要设置调色板
|
try
|
{
|
if (this.ImageGrabbed != null)
|
{
|
Bitmap Image = new Bitmap(w, h, gray ? w : w * 3,
|
gray ? System.Drawing.Imaging.PixelFormat.Format8bppIndexed : System.Drawing.Imaging.PixelFormat.Format24bppRgb,
|
pFrameBuffer);
|
if (gray)
|
Image.Palette = m_GrayPal;
|
|
this.ImageGrabbed(this, new CameraEventArgs(SN, Image));
|
}
|
|
CallBackImg = new Bitmap(w, h, gray ? w : w * 3,
|
gray ? System.Drawing.Imaging.PixelFormat.Format8bppIndexed : System.Drawing.Imaging.PixelFormat.Format24bppRgb,
|
pFrameBuffer);
|
|
if (gray)
|
CallBackImg.Palette = m_GrayPal;
|
|
try
|
{
|
if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
|
{
|
if (mode == TriggerMode.On && source != TriggerSource.Software)
|
TriggerRunMessageReceived?.Invoke(SN, source.ToString()); // 触发运行事件
|
}
|
}
|
catch { }
|
}
|
catch { }
|
}
|
catch { }
|
}
|
|
public void CaptureThreadProc(CancellationToken token)
|
{
|
CameraSdkStatus eStatus;
|
tSdkFrameHead FrameHead;
|
IntPtr uRawBuffer;//rawbuffer由SDK内部申请。应用层不要调用delete之类的释放函数
|
|
while (m_bExitCaptureThread == false || !token.IsCancellationRequested)
|
{
|
try
|
{
|
//500毫秒超时,图像没捕获到前,线程会被挂起,释放CPU,所以该线程中无需调用sleep
|
eStatus = MvApi.CameraGetImageBuffer(m_hCamera, out FrameHead, out uRawBuffer, 500);
|
|
if (eStatus == CameraSdkStatus.CAMERA_STATUS_SUCCESS)//如果是触发模式,则有可能超时
|
{
|
//图像处理,将原始输出转换为RGB格式的位图数据,同时叠加白平衡、饱和度、LUT等ISP处理。
|
MvApi.CameraImageProcess(m_hCamera, uRawBuffer, m_ImageBuffer, ref FrameHead);
|
//叠加十字线、自动曝光窗口、白平衡窗口信息(仅叠加设置为可见状态的)。
|
MvApi.CameraImageOverlay(m_hCamera, m_ImageBuffer, ref FrameHead);
|
//调用SDK封装好的接口,显示预览图像
|
MvApi.CameraDisplayRGB24(m_hCamera, m_ImageBuffer, ref FrameHead);
|
|
if (FrameHead.iWidth != m_tFrameHead.iWidth || FrameHead.iHeight != m_tFrameHead.iHeight)
|
{
|
m_bEraseBk = true;
|
m_tFrameHead = FrameHead;
|
}
|
|
// 由于SDK输出的数据默认是从底到顶的,转换为Bitmap需要做一下垂直镜像
|
MvApi.CameraFlipFrameBuffer(m_ImageBuffer, ref m_tFrameHead, 1);
|
int w = m_tFrameHead.iWidth;
|
int h = m_tFrameHead.iHeight;
|
Boolean gray = (m_tFrameHead.uiMediaType == (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
|
// 如果是灰度图要设置调色板
|
try
|
{
|
if (this.ImageGrabbed != null)
|
{
|
Bitmap Image = new Bitmap(w, h, gray ? w : w * 3,
|
gray ? System.Drawing.Imaging.PixelFormat.Format8bppIndexed : System.Drawing.Imaging.PixelFormat.Format24bppRgb,
|
m_ImageBuffer);
|
if (gray)
|
Image.Palette = m_GrayPal;
|
|
this.ImageGrabbed(this, new CameraEventArgs(SN, Image));
|
}
|
|
CallBackImg = new Bitmap(w, h, gray ? w : w * 3,
|
gray ? System.Drawing.Imaging.PixelFormat.Format8bppIndexed : System.Drawing.Imaging.PixelFormat.Format24bppRgb,
|
m_ImageBuffer);
|
|
if (gray)
|
CallBackImg.Palette = m_GrayPal;
|
|
try
|
{
|
if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
|
{
|
if (mode == TriggerMode.On && source != TriggerSource.Software)
|
TriggerRunMessageReceived?.Invoke(SN, source.ToString()); // 触发运行事件
|
}
|
}
|
catch { }
|
}
|
catch { }
|
}
|
|
//成功调用CameraGetImageBuffer后必须释放,下次才能继续调用CameraGetImageBuffer捕获图像。
|
MvApi.CameraReleaseImageBuffer(m_hCamera, uRawBuffer);
|
}
|
catch { }
|
}
|
}
|
|
public override bool SetExpouseTime(double value)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
MvApi.CameraSetExposureTime(m_hCamera, value);
|
return true;
|
}
|
|
public override bool SetGain(double gain)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
|
MvApi.CameraSetAnalogGainX(m_hCamera, Convert.ToSingle(gain));
|
return true;
|
}
|
|
public override bool SetLineMode(IOLines line, LineMode mode)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
//MvApi.CameraShowSettingPage(m_hCamera, 1);
|
return true;
|
}
|
|
public override bool SetLineStatus(IOLines line, LineStatus linestatus)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
//MvApi.CameraShowSettingPage(m_hCamera, 1);
|
return true;
|
}
|
|
public override bool SetTriggerDelay(double delay)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
MvApi.CameraSetTriggerDelayTime(m_hCamera, (uint)delay);
|
return true;
|
}
|
|
public override bool SetTriggerFliter(double flitertime)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
/*设置电平触发方式下的去抖时间
|
只有在电平触发模式下,去抖时间才有效,在边沿触发下,忽略去抖时间。
|
因此边沿触发方式,请一定要使用电子开关。电平触发方式加上去抖时间,可以去掉
|
机械开关的抖动。
|
*/
|
MvApi.CameraSetExtTrigJitterTime(m_hCamera, (uint)flitertime);
|
return true;
|
}
|
|
public override bool SetTriggerMode(TriggerMode mode, TriggerSource source = TriggerSource.None)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
cts.Cancel(); // 请求取消线程
|
|
GetTriggerMode(out TriggerMode m, out TriggerSource s);
|
|
if (m == TriggerMode.Off)
|
{
|
// 等待一段时间,避免实时线程未关闭
|
Thread.Sleep(2000); // 模拟等待 2 秒
|
}
|
|
//0表示连续模式,1是软触发,2是硬触发。
|
if (mode == TriggerMode.Off)
|
{
|
MvApi.CameraSetTriggerMode(m_hCamera, 0);
|
cts = new CancellationTokenSource();
|
m_tCaptureThread = new Thread(() => CaptureThreadProc(cts.Token));
|
m_tCaptureThread.Start();
|
return true;
|
}
|
else
|
{
|
cts.Cancel(); // 请求取消线程
|
}
|
|
//没有提供触发源说明只改变触发模式
|
if (source == TriggerSource.None)
|
GetTriggerMode(out mode, out source);
|
|
//0表示连续模式,1是软触发,2是硬触发。
|
if (source == TriggerSource.Software)
|
MvApi.CameraSetTriggerMode(m_hCamera, 1);
|
else
|
MvApi.CameraSetTriggerMode(m_hCamera, 2);
|
|
return true;
|
}
|
|
public override bool SetTriggerPolarity(TriggerPolarity polarity)
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
MvApi.CameraSetExtTrigSignalType(m_hCamera, (int)polarity);
|
|
////硬件外触发的信号种类
|
//{
|
//EXT_TRIG_LEADING_EDGE = 0, //上升沿触发,默认为该方式
|
//EXT_TRIG_TRAILING_EDGE, //下降沿触发
|
//EXT_TRIG_HIGH_LEVEL, //高电平触发,电平宽度决定曝光时间,仅部分型号的相机支持电平触发方式。
|
//EXT_TRIG_LOW_LEVEL //低电平触发,
|
//}
|
|
/*
|
CameraSetExtTrigSignalType(m_hCamera,0); //设置为上升沿信号触发。
|
CameraSetExtTrigSignalType(m_hCamera,1); //设置为下降沿信号触发。
|
CameraSetExtTrigSignalType(m_hCamera,2); //设置为高电平信号触发,如果一直为高电平,则会一直触发,相当于连续预览。
|
CameraSetExtTrigSignalType(m_hCamera,3); //设置为低电平信号触发,如果一直为低电平,则会一直触发,相当于连续预览。。
|
*/
|
return true;
|
}
|
|
public override bool SoftTrigger()
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
int mode = 0;
|
if (m_Grabber != IntPtr.Zero)
|
{
|
MvApi.CameraGetTriggerMode(m_hCamera, ref mode);
|
if (mode != 0)
|
{
|
// 只触发模式下调用软触发指令
|
MvApi.CameraSoftTrigger(m_hCamera);
|
}
|
}
|
|
return true;
|
}
|
|
public override bool StartGrabbing()
|
{
|
try
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
CallBackImg = null;
|
MvApi.CameraGrabber_StartLive(m_Grabber);
|
isGrabbing = true;
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public override bool StopGrabbing()
|
{
|
try
|
{
|
if (m_Grabber == IntPtr.Zero)
|
return false;
|
|
MvApi.CameraGrabber_StopLive(m_Grabber);
|
isGrabbing = false;
|
CallBackImg = null;
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public void SetSetting(int show = 1)
|
{
|
if (m_hCamera > 0)
|
MvApi.CameraShowSettingPage(m_hCamera, (uint)show);//1 show ; 0 hide
|
}
|
|
public override bool GetImage(out Bitmap bitmap, int outtime = 3000)
|
{
|
bitmap = null;
|
|
try
|
{
|
// 设置超时时间
|
DateTime lastTime = DateTime.Now.AddMilliseconds(outtime);
|
// 判断是否超时
|
while (lastTime > DateTime.Now)// 设置超时时间为 3 秒
|
{
|
try
|
{
|
if (CallBackImg != null)
|
{
|
// 保存旧 Bitmap 并释放
|
bitmap = CallBackImg.Clone() as Bitmap; // 创建副本
|
|
// 释放旧资源
|
CallBackImg.Dispose();
|
CallBackImg = null;
|
return true;
|
}
|
}
|
catch { }
|
Thread.Sleep(10);
|
}
|
return false;
|
}
|
catch { return bitmap == null ? false : true; }
|
}
|
|
public override bool GetImageWithSoftTrigger(out Bitmap bitmap, int outtime = 3000)
|
{
|
if (!isGrabbing)
|
{
|
StartGrabbing();
|
}
|
GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
|
if (triggerMode != TriggerMode.On && triggerSource != TriggerSource.Software)
|
{
|
SetTriggerMode(TriggerMode.On, TriggerSource.Software);
|
}
|
bitmap = null;
|
CallBackImg = null;
|
if (!SoftTrigger())
|
{
|
return false;
|
}
|
// 开始时间
|
DateTime startTime = DateTime.Now; // 当前时间
|
// 判断是否超时
|
while (DateTime.Now < startTime.AddMilliseconds(outtime))// 设置超时时间为 3 秒
|
{
|
GetImage(out bitmap, 50);
|
if (bitmap != null)
|
{
|
break;
|
}
|
Thread.Sleep(10);
|
}
|
if (triggerMode != TriggerMode.On)
|
{
|
SetTriggerMode(TriggerMode.On, triggerSource);
|
}
|
return (bitmap != null);
|
}
|
|
|
public override void SetCamConfig(CameraConfig config)
|
{
|
if (Enum.TryParse(config.Params.Inputs["触发模式"].ToString(), out TriggerMode TriggerMode)
|
&& Enum.TryParse(config.Params.Inputs["触发方式"].ToString(), out TriggerSource TriggerSource)
|
&& Enum.TryParse(config.Params.Inputs["触发极性"].ToString(), out TriggerPolarity TriggerPolarity)
|
)
|
{
|
SetTriggerMode(TriggerMode, TriggerSource);
|
SetTriggerPolarity(TriggerPolarity);
|
//SetTriggerFliter(Convert.ToDouble(config.Params.Inputs["触发消抖"].ToString()));
|
//SetTriggerDelay(Convert.ToDouble(config.Params.Inputs["触发延时"].ToString()));
|
SetExpouseTime(Convert.ToDouble(config.Params.Inputs["曝光时间"].ToString()));
|
SetGain(Convert.ToDouble(config.Params.Inputs["增益"].ToString()));
|
}
|
}
|
|
public override void GetCamConfig(out CameraConfig config)
|
{
|
GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
|
GetTriggerPolarity(out TriggerPolarity triggerPolarity);
|
//GetTriggerFliter(out double triggerfilter);
|
//GetTriggerDelay(out double triggerdelay);
|
GetExpouseTime(out double expouseTime);
|
GetGain(out double gain);
|
|
config = new CameraConfig(null);
|
config.Params.Inputs.Add("触发模式", triggerMode);
|
config.Params.Inputs.Add("触发方式", triggerSource);
|
config.Params.Inputs.Add("触发极性", triggerPolarity);
|
//config.Params.Inputs.Add("触发消抖", triggerfilter);
|
//config.Params.Inputs.Add("触发延时", triggerdelay);
|
config.Params.Inputs.Add("曝光时间", expouseTime);
|
config.Params.Inputs.Add("增益", gain);
|
}
|
|
public override bool StartWith_SoftTriggerModel()
|
{
|
SetTriggerMode(TriggerMode.Off, TriggerSource.Software);
|
return StartGrabbing();
|
}
|
|
public override bool StartWith_HardTriggerModel(TriggerSource hardtriggeritem = TriggerSource.Line0)
|
{
|
if (hardtriggeritem == TriggerSource.Software) hardtriggeritem = TriggerSource.Line0;
|
SetTriggerMode(TriggerMode.On, hardtriggeritem);
|
return StartGrabbing();
|
}
|
|
public override bool StartContinuousGrab()
|
{
|
throw new NotImplementedException();
|
}
|
}
|
}
|