| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- using MvCameraControl;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading;
- namespace CCDCount.DLL
- {
- public class CameraClass
- {
- #region 常量
- readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
- | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice
- | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;
- #endregion
- #region 变量
- private List<IDeviceInfo> CamList; // 相机列表
- private IDevice device = null; // 相机实例
- private bool isGrabbing = false; // 是否正在取图
- private Thread receiveThread = null; // 接收图像线程
- private ConcurrentQueue<ImageMessageClass> FrameOuts = new ConcurrentQueue<ImageMessageClass>();
- private ConcurrentQueue<byte[]> ImageBytes = new ConcurrentQueue<byte[]>(); //图像接受队列
- private int OnImageSelectRows = 2;
- private long lastframeNum = -1;
- #endregion
- #region 公共方法
- /// <summary>
- /// 获取相机列表
- /// </summary>
- /// <param name="CamList"></param>
- /// <returns></returns>
- public void GetCameraList(out List<CameraInfoClass> CameraInfoList)
- {
- CamList = new List<IDeviceInfo>();
- CameraInfoList = new List<CameraInfoClass>();
- int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out CamList);
- if (nRet != MvError.MV_OK)
- {
- return;
- }
- else
- {
- //输出相机名称及SN码以方便选择设备
- foreach (var item in CamList)
- {
- CameraInfoList.Add(new CameraInfoClass
- {
- DeviceName = item.UserDefinedName == "" ? item.ModelName : item.UserDefinedName,
- DeviceSN = item.SerialNumber,
- });
- }
- }
- return;
- }
- /// <summary>
- /// 加载指定相机
- /// </summary>
- /// <param name="DeviceSN"></param>
- public bool LoadCamereDevice(string DeviceSN)
- {
- bool Blresult = false;
- List<IDeviceInfo> deviceInfos = CamList.Where(o => o.SerialNumber == DeviceSN).ToList();
- if(deviceInfos.Count == 0) return Blresult;
- IDeviceInfo deviceInfo = deviceInfos.First();
- try
- {
- // 打开设备
- device = DeviceFactory.CreateDevice(deviceInfo);
- }
- catch (Exception ex)
- {
- Console.WriteLine("Create Device fail!" + ex.Message);
- return Blresult;
- }
- int result = device.Open();
- if (result != MvError.MV_OK)
- {
- Console.WriteLine("Open Device fail!" + result);
- return Blresult;
- }
- // 判断是否为gige设备
- if (device is IGigEDevice)
- {
- // 转换为gigE设备
- IGigEDevice gigEDevice = device as IGigEDevice;
- // 探测网络最佳包大小(只对GigE相机有效)
- int optionPacketSize;
- result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
- if (result != MvError.MV_OK)
- {
- //Log("Warning: Get Packet Size failed!", result);
- }
- else
- {
- result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
- if (result != MvError.MV_OK)
- {
- //Log("Warning: Set Packet Size failed!", result);
- }
- }
- }
- // 设置采集连续模式
- device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
- device.Parameters.SetEnumValueByString("TriggerMode", "Off");
- Blresult = true;
- return Blresult;
- }
- /// <summary>
- /// 开启相机采集
- /// </summary>
- public void StartCamera()
- {
- //StartEventGetImage();
- StartReceiveFuntion();
- //// 开始采集
- if (!isGrabbing)
- {
- isGrabbing = false;
- receiveThread.Join();
- Console.WriteLine(string.Format("{0}:采集线程开启失败", "CameraClass-StartCamera"));
- return;
- }
- }
- /// <summary>
- /// 关闭相机采集
- /// </summary>
- public void StopCamera()
- {
- StopReceiveFuntion();
- StopEventGetImage();
- if(device!=null)
- {
- int result = device.StreamGrabber.StopGrabbing();
- device.Close();
- device.Dispose();
- if (result != MvError.MV_OK)
- {
- //Log("Stop Grabbing Fail!", result);
- }
- }
- }
- /// <summary>
- /// 获取第一张缓存中的图像,并把这个图像从缓存中清楚
- /// </summary>
- /// <param name="ImageData"></param>
- public bool GetOnceImage(out IFrameOut ImageData)
- {
- bool result = false;
- //判断是否可以给图像数据赋值
- device.StreamGrabber.GetImageBuffer(1000, out ImageData);
- if (ImageData != null)
- {
- result = true;
- }
- return result;
- }
- /// <summary>
- /// 获取相机图像尺寸信息
- /// </summary>
- /// <returns></returns>
- public CameraImageSizeClass GetCamereImageSize()
- {
- CameraImageSizeClass cameraImageSize =new CameraImageSizeClass();
- IIntValue PixWidth;
- IIntValue PixHeight;
- device.Parameters.GetIntValue("Width", out PixWidth);
- device.Parameters.GetIntValue("Height", out PixHeight);
- cameraImageSize.Height = (int)PixHeight.CurValue;
- cameraImageSize.Width = (int)PixWidth.CurValue;
- return cameraImageSize;
- }
- /// <summary>
- /// 开启事件获取图像
- /// </summary>
- public void StartEventGetImage()
- {
- //ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
- device.StreamGrabber.SetImageNodeNum(50);
- // ch:注册回调函数 | en:Register image callback
- device.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler;
- // ch:开启抓图 || en: start grab image
- int ret = device.StreamGrabber.StartGrabbing();
- if (ret != MvError.MV_OK)
- {
- Console.WriteLine(string.Format("Start grabbing failed:{0}", ret));
- return;
- }
- }
- /// <summary>
- /// 停止事件获取图像
- /// </summary>
- public void StopEventGetImage()
- {
- if(device==null) return;
- int ret = device.StreamGrabber.StopGrabbing();
- if (ret != MvError.MV_OK)
- {
- Console.WriteLine("Stop grabbing failed:{0:x8}", ret);
- return;
- }
- // ch:注册回调函数 | en:Register image callback
- device.StreamGrabber.FrameGrabedEvent -= FrameGrabedEventHandler;
- }
- /// <summary>
- /// 获取当前相机的参数生成Config信息
- /// </summary>
- /// <returns></returns>
- public void GetCamValue()
- {
- device.Parameters.GetFloatValue("ExposureTime", out IFloatValue exposureTime);
- device.Parameters.GetIntValue("AcquisitionLineRate", out IIntValue acquisitionLineRate);
- device.Parameters.GetIntValue("OffsetX", out IIntValue offsetX);
- device.Parameters.GetIntValue("Height", out IIntValue pixHeight);
- device.Parameters.GetIntValue("Width", out IIntValue pixWidth);
- Console.WriteLine(pixHeight.Min);
- device.Parameters.GetStringValue("DeviceUserID", out IStringValue deviceUserID);
- device.Parameters.GetStringValue("DeviceModelName", out IStringValue deviceModelName);
- device.Parameters.GetStringValue("DeviceSerialNumber", out IStringValue deviceSerialNumber);
- }
- #endregion
- #region 私有方法
- /// <summary>
- /// 采集线程
- /// </summary>
- private void ReceiveThreadProcess()
- {
- IFrameOut frameOut;
- Queue<byte[]> frameDatas;
- byte[] data = null;
- while (isGrabbing)
- {
- //bool BRet = FrameOuts.TryDequeue(out frameOut);
- bool BRet = GetOnceImage(out frameOut);
- if (frameOut!=null && frameOut.Image != null)
- {
- frameDatas = GetImageRowsData(frameOut.Image);
- if (lastframeNum == -1)
- {
- lastframeNum = frameOut.FrameNum;
- }
- else if (lastframeNum == frameOut.FrameNum - 1)
- {
- lastframeNum = frameOut.FrameNum;
- }
- else
- {
- //丢帧记录
- Console.WriteLine(string.Format("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
- frameOut.Image.Width, frameOut.Image.Height, frameOut.FrameNum - 1, lastframeNum), 5);
- lastframeNum = frameOut.FrameNum;
- }
- Console.WriteLine("FrameNum[{0}]", frameOut.FrameNum);
- frameOut.Dispose();
- }
- }
- }
- /// <summary>
- /// 开启采集
- /// </summary>
- private void StartReceiveFuntion()
- {
- try
- {
- device.StreamGrabber.StartGrabbing();
- // 标志位置位true
- isGrabbing = true;
- // 开启线程
- receiveThread = new Thread(ReceiveThreadProcess);
- receiveThread.Start();
- }
- catch (Exception ex)
- {
- Console.WriteLine("Start thread failed!, " + ex.Message);
- throw;
- }
- }
- /// <summary>
- /// 关闭采集线程
- /// </summary>
- private void StopReceiveFuntion()
- {
- try
- {
- // 标志位设为false
- isGrabbing = false;
- if(receiveThread != null&&receiveThread.IsAlive)
- receiveThread.Join();
- }
- catch (Exception ex)
- {
- Console.WriteLine("Start thread failed!, " + ex.Message);
- throw;
- }
- }
- /// <summary>
- /// 读取图像像素信息(单行)
- /// </summary>
- /// <param name="frameOut">帧数据</param>
- /// <returns></returns>
- private byte[] GetImageFristRowsData(IFrameOut frameOut)
- {
- //创建
- byte[] PixelData = new byte[(int)frameOut.Image.Width];
- //从相机缓存中拷贝出图像数据
- Marshal.Copy(frameOut.Image.PixelDataPtr, PixelData, 0, (int)frameOut.Image.Width);
- return PixelData;
- }
- /// <summary>
- /// 读取图像像素信息(多行)
- /// </summary>
- /// <param name="frameOut"></param>
- /// <returns></returns>
- private Queue<byte[]> GetImageRowsData(IImage frameOut)
- {
- //创建
- Queue<byte[]> PixelDatas = new Queue<byte[]>();
- for (int i = 0;i< OnImageSelectRows;i++)
- {
- byte[] PixelData = new byte[frameOut.Width];
- Marshal.Copy(IntPtr.Add(frameOut.PixelDataPtr,i * (int)frameOut.Width), PixelData, 0, (int)frameOut.Width);
- PixelDatas.Enqueue(PixelData.Clone() as byte[]);
- PixelData = null;
- }
- return PixelDatas;
- }
- /// <summary>
- /// 帧获取回调事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
- {
- if (lastframeNum == -1)
- {
- lastframeNum = e.FrameOut.FrameNum;
- }
- else if (lastframeNum == e.FrameOut.FrameNum - 1)
- {
- lastframeNum = e.FrameOut.FrameNum;
- }
- else
- {
- //丢帧记录
- Console.WriteLine(string.Format("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
- e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.FrameNum - 1, lastframeNum), 5);
- lastframeNum = e.FrameOut.FrameNum;
- }
- ImageMessageClass imageMessage = new ImageMessageClass()
- {
- ImageData = e.FrameOut.Image.Clone() as IImage,
- FrameNo = (int)e.FrameOut.FrameNum
- };
- FrameOuts.Enqueue(imageMessage);
- }
- #endregion
- }
- public class CameraInfoClass
- {
- public string DeviceName { get; set; }
- public string DeviceSN { get; set; }
- }
- public class CameraImageSizeClass
- {
- public int Width { get; set; }
- public int Height { get; set; }
- }
- public class ImageMessageClass
- {
- public IImage ImageData { get; set; }
- public int FrameNo { get; set; }
- }
- }
|