CameraClass.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. using CCDCount.MODEL.CameraClass;
  2. using CCDCount.MODEL.ConfigModel;
  3. using LogClass;
  4. using MvCameraControl;
  5. using System;
  6. using System.Collections.Concurrent;
  7. using System.Collections.Generic;
  8. using System.Diagnostics;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Runtime.InteropServices;
  12. using System.Threading;
  13. namespace CCDCount.DLL
  14. {
  15. public class CameraClass
  16. {
  17. #region 常量
  18. readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
  19. | DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice
  20. | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;
  21. #endregion
  22. #region 变量
  23. private List<IDeviceInfo> CamList; // 相机列表
  24. private IDevice device = null; // 相机实例
  25. private Thread receiveThread = null; // 接收图像线程
  26. private ConcurrentQueue<IFrameOut> FrameOuts = new ConcurrentQueue<IFrameOut>();
  27. private ConcurrentQueue<byte[]> ImageBytes = new ConcurrentQueue<byte[]>(); //图像接受队列
  28. private int OnImageSelectRows = 20;
  29. private long lastframeNum = -1;
  30. public int CamereNo { get { return _cameraNo; } }
  31. public int ImageNum { get { return FrameOuts.Count; }}
  32. private int _cameraNo = -1;
  33. private string cameraName = string.Empty;
  34. #endregion
  35. #region 公共方法
  36. /// <summary>
  37. /// 获取相机列表
  38. /// </summary>
  39. /// <param name="CamList"></param>
  40. /// <returns></returns>
  41. public void GetCameraList(out List<CameraInfoClass> CameraInfoList)
  42. {
  43. CamList = new List<IDeviceInfo>();
  44. CameraInfoList = new List<CameraInfoClass>();
  45. int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out CamList);
  46. if (nRet != MvError.MV_OK)
  47. {
  48. return;
  49. }
  50. else
  51. {
  52. //输出相机名称及SN码以方便选择设备
  53. foreach (var item in CamList)
  54. {
  55. CameraInfoList.Add(new CameraInfoClass
  56. {
  57. //DeviceName = item.UserDefinedName == "" ? item.ModelName : item.UserDefinedName,
  58. DeviceName = item.ModelName,
  59. DeviceSN = item.SerialNumber,
  60. });
  61. }
  62. }
  63. return;
  64. }
  65. /// <summary>
  66. /// 更新相机列表
  67. /// </summary>
  68. public void UpdateCameraList()
  69. {
  70. CamList = new List<IDeviceInfo>();
  71. int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out CamList);
  72. if (nRet != MvError.MV_OK)
  73. {
  74. Console.WriteLine("相机列表更新失败");
  75. return;
  76. }
  77. }
  78. /// <summary>
  79. /// 加载指定相机
  80. /// </summary>
  81. /// <param name="DeviceSN"></param>
  82. public bool LoadCamereDevice(CameraConfig DeviceConfig)
  83. {
  84. bool Blresult = false;
  85. List<IDeviceInfo> deviceInfos = CamList.Where(o => o.SerialNumber == DeviceConfig.CameraSNNum).ToList();
  86. if(deviceInfos.Count == 0) return Blresult;
  87. IDeviceInfo deviceInfo = deviceInfos.First();
  88. try
  89. {
  90. // 打开设备
  91. device = DeviceFactory.CreateDevice(deviceInfo);
  92. }
  93. catch (Exception ex)
  94. {
  95. LOG.error("Create Device fail!" + ex.Message);
  96. return Blresult;
  97. }
  98. int result = device.Open();
  99. if (result != MvError.MV_OK)
  100. {
  101. LOG.error("Open Device fail!" + result);
  102. return Blresult;
  103. }
  104. // 判断是否为gige设备
  105. if (device is IGigEDevice)
  106. {
  107. // 转换为gigE设备
  108. IGigEDevice gigEDevice = device as IGigEDevice;
  109. // 探测网络最佳包大小(只对GigE相机有效)
  110. int optionPacketSize;
  111. result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
  112. if (result != MvError.MV_OK)
  113. {
  114. //Log("Warning: Get Packet Size failed!", result);
  115. }
  116. else
  117. {
  118. result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
  119. if (result != MvError.MV_OK)
  120. {
  121. //Log("Warning: Set Packet Size failed!", result);
  122. }
  123. }
  124. }
  125. //判断是否从配置文件读取的参数,是则设置参数,否则加载相机默认参数
  126. if(DeviceConfig.IsLoadCanfig)
  127. {
  128. //设置从配置文件读取的参数
  129. device.Parameters.GetStringValue("DeviceModelName", out IStringValue deviceModelName);
  130. _cameraNo = DeviceConfig.CamerNo;
  131. if (DeviceConfig.CameraName != deviceModelName.CurValue)
  132. device.Parameters.SetStringValue("DeviceUserID", DeviceConfig.CameraName);
  133. device.Parameters.SetFloatValue("ExposureTime", DeviceConfig.ExposureTimeValue);
  134. device.Parameters.SetIntValue("AcquisitionLineRate", DeviceConfig.AcquistionLineRateValue);
  135. device.Parameters.SetIntValue("Height", DeviceConfig.Height);
  136. device.Parameters.SetIntValue("Width", DeviceConfig.Width);
  137. device.Parameters.SetIntValue("OffsetX", DeviceConfig.OffsetX);
  138. }
  139. // 设置采集连续模式
  140. device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
  141. device.Parameters.SetEnumValueByString("TriggerMode", "Off");
  142. Blresult = true;
  143. return Blresult;
  144. }
  145. /// <summary>
  146. /// 重新加载指定相机
  147. /// </summary>
  148. /// <param name="CameraSN"></param>
  149. /// <returns></returns>
  150. public bool ReLoadCameraDevice(string CameraSN)
  151. {
  152. bool Blresult = false;
  153. if(device!=null && device.IsConnected)
  154. {
  155. device.Close();
  156. device.Dispose();
  157. }
  158. UpdateCameraList();
  159. List<IDeviceInfo> deviceInfos = CamList.Where(o => o.SerialNumber == CameraSN).ToList();
  160. if (deviceInfos.Count == 0) return Blresult;
  161. IDeviceInfo deviceInfo = deviceInfos.First();
  162. try
  163. {
  164. // 打开设备
  165. device = DeviceFactory.CreateDevice(deviceInfo);
  166. Blresult = true;
  167. }
  168. catch (Exception ex)
  169. {
  170. LOG.error("Create Device fail!" + ex.Message);
  171. return Blresult;
  172. }
  173. int result = device.Open();
  174. if (result != MvError.MV_OK)
  175. {
  176. Blresult = false;
  177. LOG.error("Open Device fail!" + result);
  178. return Blresult;
  179. }
  180. // 判断是否为gige设备
  181. if (device is IGigEDevice)
  182. {
  183. // 转换为gigE设备
  184. IGigEDevice gigEDevice = device as IGigEDevice;
  185. // 探测网络最佳包大小(只对GigE相机有效)
  186. int optionPacketSize;
  187. result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
  188. if (result != MvError.MV_OK)
  189. {
  190. //Log("Warning: Get Packet Size failed!", result);
  191. }
  192. else
  193. {
  194. result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
  195. if (result != MvError.MV_OK)
  196. {
  197. //Log("Warning: Set Packet Size failed!", result);
  198. }
  199. }
  200. }
  201. return Blresult;
  202. }
  203. /// <summary>
  204. /// 开启相机采集
  205. /// </summary>
  206. public void StartCamera()
  207. {
  208. StartReceiveFuntion();
  209. }
  210. /// <summary>
  211. /// 关闭相机采集
  212. /// </summary>
  213. public void StopCamera()
  214. {
  215. StopReceiveFuntion();
  216. //StopEventGetImage();
  217. if(device!=null)
  218. {
  219. int result = device.StreamGrabber.StopGrabbing();
  220. device.Close();
  221. device.Dispose();
  222. if (result != MvError.MV_OK)
  223. {
  224. LOG.log(("Stop Grabbing Fail!", result));
  225. }
  226. }
  227. }
  228. public bool GetOnceImage(out IFrameOut IFrameData)
  229. {
  230. bool result = false;
  231. int BRet = device.StreamGrabber.GetImageBuffer(1000, out IFrameData);
  232. if (BRet == 0 && IFrameData != null) result = true;
  233. else return result;
  234. if (lastframeNum == -1)
  235. {
  236. lastframeNum = IFrameData.FrameNum;
  237. }
  238. else if (lastframeNum == IFrameData.FrameNum - 1)
  239. {
  240. lastframeNum = IFrameData.FrameNum;
  241. }
  242. else
  243. {
  244. //丢帧记录
  245. LOG.log(string.Format("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
  246. IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum - 1, lastframeNum), 6);
  247. Console.WriteLine("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
  248. IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum - 1, lastframeNum);
  249. lastframeNum = IFrameData.FrameNum;
  250. }
  251. return result;
  252. }
  253. /// <summary>
  254. /// 获取相机图像尺寸信息
  255. /// </summary>
  256. /// <returns></returns>
  257. public CameraImageSizeClass GetCamereImageSize()
  258. {
  259. CameraImageSizeClass cameraImageSize =new CameraImageSizeClass();
  260. IIntValue PixWidth;
  261. IIntValue PixHeight;
  262. device.Parameters.GetIntValue("Width", out PixWidth);
  263. device.Parameters.GetIntValue("Height", out PixHeight);
  264. cameraImageSize.Height = (int)PixHeight.CurValue;
  265. cameraImageSize.Width = (int)PixWidth.CurValue;
  266. return cameraImageSize;
  267. }
  268. /// <summary>
  269. /// 获取Config信息
  270. /// </summary>
  271. /// <returns></returns>
  272. public CameraConfig GetConfigValue()
  273. {
  274. CameraConfig result = null;
  275. device.Parameters.GetFloatValue("ExposureTime", out IFloatValue exposureTime);
  276. device.Parameters.GetIntValue("AcquisitionLineRate", out IIntValue acquisitionLineRate);
  277. device.Parameters.GetIntValue("OffsetX", out IIntValue offsetX);
  278. device.Parameters.GetIntValue("Height", out IIntValue pixHeight);
  279. device.Parameters.GetIntValue("Width", out IIntValue pixWidth);
  280. device.Parameters.GetStringValue("DeviceUserID", out IStringValue deviceUserID);
  281. device.Parameters.GetStringValue("DeviceModelName", out IStringValue deviceModelName);
  282. device.Parameters.GetStringValue("DeviceSerialNumber", out IStringValue deviceSerialNumber);
  283. result = new CameraConfig()
  284. {
  285. CameraSNNum = deviceSerialNumber.CurValue,
  286. ExposureTimeValue = exposureTime.CurValue,
  287. AcquistionLineRateValue = (int)acquisitionLineRate.CurValue,
  288. Height = (int)pixHeight.CurValue,
  289. Width = (int)pixWidth.CurValue,
  290. OffsetX = (int)offsetX.CurValue,
  291. CameraName = deviceUserID.CurValue,
  292. DeviceName = deviceModelName.CurValue,
  293. CamerNo = _cameraNo
  294. };
  295. return result;
  296. }
  297. /// <summary>
  298. /// 保存参数
  299. /// </summary>
  300. public void SaveConfig()
  301. {
  302. CameraConfig camerasConfig = null;
  303. if (!Directory.Exists(".\\Config\\")) Directory.CreateDirectory(".\\Config\\");
  304. XmlStorage.SerializeToXml(camerasConfig, ".\\Config\\CameraConfig.xml");
  305. }
  306. public bool IsLoadCamera()
  307. {
  308. return device == null ? false : true;
  309. }
  310. public bool IsConnectCamera()
  311. {
  312. if (device == null) return false;
  313. else
  314. {
  315. return device.IsConnected;
  316. }
  317. }
  318. #endregion
  319. #region 私有方法
  320. /// <summary>
  321. /// 开启采集
  322. /// </summary>
  323. private void StartReceiveFuntion()
  324. {
  325. try
  326. {
  327. device.StreamGrabber.SetImageNodeNum(100);
  328. device.StreamGrabber.StartGrabbing();
  329. }
  330. catch (Exception ex)
  331. {
  332. LOG.error("Start thread failed!, " + ex.Message);
  333. throw;
  334. }
  335. }
  336. /// <summary>
  337. /// 关闭采集
  338. /// </summary>
  339. private void StopReceiveFuntion()
  340. {
  341. try
  342. {
  343. if (device == null) return;
  344. int ret = device.StreamGrabber.StopGrabbing();
  345. if (ret != MvError.MV_OK)
  346. {
  347. LOG.error(("Stop grabbing failed:{0:x8}", ret));
  348. return;
  349. }
  350. }
  351. catch (Exception ex)
  352. {
  353. LOG.error("Stop thread failed!, " + ex.Message);
  354. throw;
  355. }
  356. }
  357. /// <summary>
  358. /// 读取图像像素信息(单行)
  359. /// </summary>
  360. /// <param name="frameOut">帧数据</param>
  361. /// <returns></returns>
  362. private byte[] GetImageFristRowsData(IFrameOut frameOut)
  363. {
  364. //创建
  365. byte[] PixelData = new byte[(int)frameOut.Image.Width];
  366. //从相机缓存中拷贝出图像数据
  367. Marshal.Copy(frameOut.Image.PixelDataPtr, PixelData, 0, (int)frameOut.Image.Width);
  368. return PixelData;
  369. }
  370. /// <summary>
  371. /// 读取图像像素信息(多行)
  372. /// </summary>
  373. /// <param name="frameOut"></param>
  374. /// <returns></returns>
  375. private Queue<byte[]> GetImageRowsData(IFrameOut frameOut)
  376. {
  377. //创建
  378. Queue<byte[]> PixelDatas = new Queue<byte[]>();
  379. for (int i = 0;i< OnImageSelectRows;i++)
  380. //for (int i = 0;i< frameOut.Image.Height;i++)
  381. {
  382. byte[] PixelData = new byte[frameOut.Image.Width];
  383. Marshal.Copy(IntPtr.Add(frameOut.Image.PixelDataPtr,i * (int)frameOut.Image.Width), PixelData, 0, (int)frameOut.Image.Width);
  384. PixelDatas.Enqueue(PixelData.Clone() as byte[]);
  385. PixelData = null;
  386. }
  387. return PixelDatas;
  388. }
  389. #endregion
  390. }
  391. }