using CCDCount.MODEL.CameraClass; using CCDCount.MODEL.ConfigModel; using LogClass; using MvCameraControl; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; 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; // 相机实例 public bool IsGrabbing { get { return _isGrabbing; }} private bool _isGrabbing = false; // 是否正在取图 private Thread receiveThread = null; // 接收图像线程 private ConcurrentQueue FrameOuts = new ConcurrentQueue(); private ConcurrentQueue ImageBytes = new ConcurrentQueue(); //图像接受队列 private int OnImageSelectRows = 20; private long lastframeNum = -1; public int CamereNo { get { return _cameraNo; } } public int ImageNum { get { return FrameOuts.Count; }} private int _cameraNo = -1; private string cameraName = string.Empty; #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, DeviceName = item.ModelName, DeviceSN = item.SerialNumber, }); } } return; } /// /// 更新相机列表 /// public void UpdateCameraList() { CamList = new List(); int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out CamList); if (nRet != MvError.MV_OK) { Console.WriteLine("相机列表更新失败"); return; } } /// /// 加载指定相机 /// /// public bool LoadCamereDevice(CameraConfig DeviceConfig) { bool Blresult = false; List deviceInfos = CamList.Where(o => o.SerialNumber == DeviceConfig.CameraSNNum).ToList(); if(deviceInfos.Count == 0) return Blresult; IDeviceInfo deviceInfo = deviceInfos.First(); try { // 打开设备 device = DeviceFactory.CreateDevice(deviceInfo); } catch (Exception ex) { LOG.error("Create Device fail!" + ex.Message); return Blresult; } int result = device.Open(); if (result != MvError.MV_OK) { LOG.error("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); } } } //判断是否从配置文件读取的参数,是则设置参数,否则加载相机默认参数 if(DeviceConfig.IsLoadCanfig) { //设置从配置文件读取的参数 device.Parameters.GetStringValue("DeviceModelName", out IStringValue deviceModelName); _cameraNo = DeviceConfig.CamerNo; if (DeviceConfig.CameraName != deviceModelName.CurValue) device.Parameters.SetStringValue("DeviceUserID", DeviceConfig.CameraName); device.Parameters.SetFloatValue("ExposureTime", DeviceConfig.ExposureTimeValue); device.Parameters.SetIntValue("AcquisitionLineRate", DeviceConfig.AcquistionLineRateValue); device.Parameters.SetIntValue("Height", DeviceConfig.Height); device.Parameters.SetIntValue("Width", DeviceConfig.Width); device.Parameters.SetIntValue("OffsetX", DeviceConfig.OffsetX); } // 设置采集连续模式 device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous"); device.Parameters.SetEnumValueByString("TriggerMode", "Off"); Blresult = true; return Blresult; } /// /// 重新加载指定相机 /// /// /// public bool ReLoadCameraDevice(string CameraSN) { bool Blresult = false; if(device!=null && device.IsConnected) { device.Close(); device.Dispose(); } UpdateCameraList(); List deviceInfos = CamList.Where(o => o.SerialNumber == CameraSN).ToList(); if (deviceInfos.Count == 0) return Blresult; IDeviceInfo deviceInfo = deviceInfos.First(); try { // 打开设备 device = DeviceFactory.CreateDevice(deviceInfo); Blresult = true; } catch (Exception ex) { LOG.error("Create Device fail!" + ex.Message); return Blresult; } int result = device.Open(); if (result != MvError.MV_OK) { Blresult = false; LOG.error("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); } } } return Blresult; } /// /// 开启相机采集 /// public void StartCamera() { //StartEventGetImage(); StartReceiveFuntion(); //StartImageRowsDataFuntion(); // 开始采集 if (!_isGrabbing) { _isGrabbing = false; receiveThread.Join(); LOG.log(string.Format("{0}:采集线程开启失败", "CameraClass-StartCamera")); return; } } /// /// 关闭相机采集 /// public void StopCamera() { StopReceiveAndImageRowsDataFuntion(); //StopEventGetImage(); if(device!=null) { int result = device.StreamGrabber.StopGrabbing(); device.Close(); device.Dispose(); if (result != MvError.MV_OK) { LOG.log(("Stop Grabbing Fail!", result)); } } } /// /// 获取第一张缓存中的图像,并把这个图像从缓存中清楚 /// /// public bool GetOnceImage(out byte[] ImageData) { bool result = false; //初始化图像数据 ImageData = null; //判断是否可以给图像数据赋值 if(ImageBytes.Count()!=0) { ImageData = new byte[ImageBytes.Last().Count()]; ImageBytes.TryDequeue(out ImageData); result = true; } return result; } public bool GetOnceImage(out IFrameOut IFrameData) { bool result = false; //初始化图像数据 IFrameData = null; //判断是否可以给图像数据赋值 if (FrameOuts.Count() != 0) { FrameOuts.TryDequeue(out IFrameData); 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; } /// /// 获取Config信息 /// /// public CameraConfig GetConfigValue() { CameraConfig result = null; 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); device.Parameters.GetStringValue("DeviceUserID", out IStringValue deviceUserID); device.Parameters.GetStringValue("DeviceModelName", out IStringValue deviceModelName); device.Parameters.GetStringValue("DeviceSerialNumber", out IStringValue deviceSerialNumber); result = new CameraConfig() { CameraSNNum = deviceSerialNumber.CurValue, ExposureTimeValue = exposureTime.CurValue, AcquistionLineRateValue = (int)acquisitionLineRate.CurValue, Height = (int)pixHeight.CurValue, Width = (int)pixWidth.CurValue, OffsetX = (int)offsetX.CurValue, CameraName = deviceUserID.CurValue, DeviceName = deviceModelName.CurValue, CamerNo = _cameraNo }; return result; } /// /// 保存参数 /// public void SaveConfig() { CameraConfig camerasConfig = null; if (!Directory.Exists(".\\Config\\")) Directory.CreateDirectory(".\\Config\\"); XmlStorage.SerializeToXml(camerasConfig, ".\\Config\\CameraConfig.xml"); } public bool IsLoadCamera() { return device == null ? false : true; } public bool IsConnectCamera() { if (device == null) return false; else { return device.IsConnected; } } #endregion #region 私有方法 /// /// 图像分割线程 /// private void ImageRowsDataProcess() { IFrameOut frameOut; Queue frameDatas = null; byte[] data = null; while (_isGrabbing) { if(FrameOuts.Count == 0) Thread.Sleep(5); bool BRet = FrameOuts.TryDequeue(out frameOut); if (BRet) { frameDatas = GetImageRowsData(frameOut); try { while (frameDatas!= null && frameDatas.Count > 0) { data = frameDatas.Dequeue(); ImageBytes.Enqueue(data.Clone() as byte[]); if (ImageBytes.Count > 500) Console.WriteLine("ImageBytes.Count:" + ImageBytes.Count); data = null; } } catch (Exception e) { LOG.error("CameraClass_ImageRowsDataProcess " + e.Message); return; } device.StreamGrabber.FreeImageBuffer(frameOut); } } } /// /// 开启图像分割 /// private void StartImageRowsDataFuntion() { try { // 开启线程 if(_isGrabbing) { receiveThread = new Thread(ImageRowsDataProcess); receiveThread.Start(); } } catch (Exception ex) { LOG.error("Start thread failed!, " + ex.Message); throw; } } /// /// 开启采集 /// private void StartReceiveFuntion() { try { // 标志位置位true _isGrabbing = true; device.StreamGrabber.SetImageNodeNum(100); device.StreamGrabber.StartGrabbing(); // 开启线程 receiveThread = new Thread(ReceiveThreadProcess) { Priority = ThreadPriority.Highest }; receiveThread.Start(); } catch (Exception ex) { LOG.error("Start thread failed!, " + ex.Message); throw; } } /// /// 关闭采集线程 /// private void StopReceiveAndImageRowsDataFuntion() { try { // 标志位设为false _isGrabbing = false; if (device == null) return; int ret = device.StreamGrabber.StopGrabbing(); if (ret != MvError.MV_OK) { LOG.error(("Stop grabbing failed:{0:x8}", ret)); return; } if (receiveThread != null&&receiveThread.IsAlive) receiveThread.Join(); } catch (Exception ex) { LOG.error("Stop thread failed!, " + ex.Message); throw; } } /// /// 采集线程 /// private void ReceiveThreadProcess() { while (_isGrabbing) { IFrameOut frameOut; int BRet = device.StreamGrabber.GetImageBuffer(100, out frameOut); if (BRet == MvError.MV_OK) { FrameOuts.Enqueue(frameOut.Clone() as IFrameOut); if (lastframeNum == -1) { lastframeNum = frameOut.FrameNum; } else if (lastframeNum == frameOut.FrameNum - 1) { lastframeNum = frameOut.FrameNum; } else { //丢帧记录 LOG.log(string.Format("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]", frameOut.Image.Width, frameOut.Image.Height, frameOut.FrameNum - 1, lastframeNum), 5); Console.WriteLine("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]", frameOut.Image.Width, frameOut.Image.Height, frameOut.FrameNum - 1, lastframeNum); lastframeNum = frameOut.FrameNum; } device.StreamGrabber.FreeImageBuffer(frameOut); } } } /// /// 读取图像像素信息(单行) /// /// 帧数据 /// 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(IFrameOut frameOut) { //创建 Queue PixelDatas = new Queue(); for (int i = 0;i< OnImageSelectRows;i++) //for (int i = 0;i< frameOut.Image.Height;i++) { byte[] PixelData = new byte[frameOut.Image.Width]; Marshal.Copy(IntPtr.Add(frameOut.Image.PixelDataPtr,i * (int)frameOut.Image.Width), PixelData, 0, (int)frameOut.Image.Width); PixelDatas.Enqueue(PixelData.Clone() as byte[]); PixelData = null; } return PixelDatas; } /// /// 帧获取回调事件 /// /// /// private void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e) { if (e.FrameOut.Image.PixelData.Count() == 0) { LOG.log("FrameGrabedEventHandler: PixelData is null", 0); return; } if (!_isGrabbing) return; FrameOuts.Enqueue(e.FrameOut.Clone() as IFrameOut); if (lastframeNum == -1) { lastframeNum = e.FrameOut.FrameNum; } else if (lastframeNum == e.FrameOut.FrameNum - 1) { lastframeNum = e.FrameOut.FrameNum; } else { //丢帧记录 LOG.log(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; } } /// /// 开启事件获取图像 /// private 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) { LOG.error(string.Format("Start grabbing failed:{0}", ret)); return; } Console.ReadLine(); } /// /// 停止事件获取图像 /// private 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; } #endregion } }