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 CamList; // 相机列表 private IDevice device = null; // 相机实例 private bool isGrabbing = false; // 是否正在取图 private Thread receiveThread = null; // 接收图像线程 private ConcurrentQueue FrameOuts = new ConcurrentQueue(); private ConcurrentQueue ImageBytes = new ConcurrentQueue(); //图像接受队列 private int OnImageSelectRows = 2; private long lastframeNum = -1; #endregion #region 公共方法 /// /// 获取相机列表 /// /// /// public void GetCameraList(out List CameraInfoList) { CamList = new List(); CameraInfoList = new List(); 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; } /// /// 加载指定相机 /// /// public bool LoadCamereDevice(string DeviceSN) { bool Blresult = false; List 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; } /// /// 开启相机采集 /// public void StartCamera() { //StartEventGetImage(); StartReceiveFuntion(); //// 开始采集 if (!isGrabbing) { isGrabbing = false; receiveThread.Join(); Console.WriteLine(string.Format("{0}:采集线程开启失败", "CameraClass-StartCamera")); return; } } /// /// 关闭相机采集 /// 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); } } } /// /// 获取第一张缓存中的图像,并把这个图像从缓存中清楚 /// /// public bool GetOnceImage(out IFrameOut ImageData) { bool result = false; //判断是否可以给图像数据赋值 device.StreamGrabber.GetImageBuffer(1000, out ImageData); if (ImageData != null) { result = true; } return result; } /// /// 获取相机图像尺寸信息 /// /// 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; } /// /// 开启事件获取图像 /// 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; } } /// /// 停止事件获取图像 /// 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; } /// /// 获取当前相机的参数生成Config信息 /// /// 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 私有方法 /// /// 采集线程 /// private void ReceiveThreadProcess() { IFrameOut frameOut; Queue 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(); } } } /// /// 开启采集 /// 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; } } /// /// 关闭采集线程 /// 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; } } /// /// 读取图像像素信息(单行) /// /// 帧数据 /// 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; } /// /// 读取图像像素信息(多行) /// /// /// private Queue GetImageRowsData(IImage frameOut) { //创建 Queue PixelDatas = new Queue(); 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; } /// /// 帧获取回调事件 /// /// /// 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; } } }