MvCamera.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. using Cognex.VisionPro;
  2. using MvCamCtrl.NET;
  3. using SqlSugar.DistributedSystem.Snowflake;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Collections.ObjectModel;
  7. using System.ComponentModel;
  8. using System.Data.SqlTypes;
  9. using System.Diagnostics;
  10. using System.Linq;
  11. using System.Runtime.CompilerServices;
  12. using System.Runtime.InteropServices;
  13. using System.Text;
  14. using System.Threading;
  15. using System.Threading.Tasks;
  16. using static MvCamCtrl.NET.MyCamera;
  17. namespace LampInspectionMachine.Cameralibs.HKCamera
  18. {
  19. public class MvCamera : ICamera, INotifyPropertyChanged
  20. {
  21. #region 字段
  22. private Thread m_hReceiveThread;
  23. #endregion
  24. #region 属性
  25. public CameraBrand CameraBrand { get => CameraBrand.HikRobot_MVS; }
  26. public string Name { get; private set; }
  27. public Guid ID { get; private set; }
  28. public string ManufacturerName { get; private set; }
  29. public string ModelName { get; private set; }
  30. public string SerialNumber { get; private set; }
  31. public CameraType CameraType { get; private set; }
  32. MvCameraAcqTool.MvCameraAcqTool mvCameraAcq;
  33. public MyCamera.MV_CC_DEVICE_INFO CameraInfo { get; private set; }
  34. public UInt32 ImageWidth { get; private set; }
  35. public UInt32 ImageHeight { get; private set; }
  36. public MvCamCtrl.NET.MvGvspPixelType PixelType { get; private set; }
  37. private bool _IsGrabbing;
  38. /// <summary>
  39. /// 正在采集
  40. /// </summary>
  41. public bool IsGrabbing
  42. {
  43. get { return _IsGrabbing; }
  44. private set { SetProperty(ref _IsGrabbing, value); }
  45. }
  46. private ICogImage _Image;
  47. public ICogImage Image
  48. {
  49. get { return _Image; }
  50. private set { SetProperty(ref _Image, value); }
  51. }
  52. public bool IsConnected { get; private set; }
  53. private bool IsHaveCamera = false;
  54. /// <summary>
  55. /// 采集用时
  56. /// </summary>
  57. public TimeSpan TotalTime { get; private set; }
  58. /// <summary>
  59. /// 错误信息
  60. /// </summary>
  61. public string ErrorMessage { get; private set; }
  62. #endregion
  63. #region 事件
  64. public event Action<ICogImage,TimeSpan,string> ImageCallbackEvent;
  65. public event Action<Guid, bool> CameraConnectChangedEvent;
  66. #endregion
  67. public MvCamera(Guid _ID, string _SerialNumber)
  68. {
  69. ID = _ID;
  70. SerialNumber = _SerialNumber;
  71. mvCameraAcq = new MvCameraAcqTool.MvCameraAcqTool();
  72. MyCamera.MV_CC_DEVICE_INFO_LIST stDeviceList = default(MyCamera.MV_CC_DEVICE_INFO_LIST);
  73. mvCameraAcq.EnumDeivce(ref stDeviceList);
  74. MyCamera.MV_CC_DEVICE_INFO device = default(MyCamera.MV_CC_DEVICE_INFO);
  75. for ( int i = 0; i < stDeviceList.nDeviceNum; i++ )
  76. {
  77. device = ( MyCamera.MV_CC_DEVICE_INFO ) Marshal.PtrToStructure(stDeviceList.pDeviceInfo[ i ], typeof(MyCamera.MV_CC_DEVICE_INFO));
  78. if ( device.nTLayerType == CSystem.MV_GIGE_DEVICE )
  79. {
  80. MV_GIGE_DEVICE_INFO stGigEDeviceInfo = (MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MV_GIGE_DEVICE_INFO));
  81. if ( string.Equals(stGigEDeviceInfo.chSerialNumber, _SerialNumber) )
  82. {
  83. ManufacturerName = stGigEDeviceInfo.chManufacturerName;
  84. ModelName = stGigEDeviceInfo.chModelName;
  85. SerialNumber = stGigEDeviceInfo.chSerialNumber;
  86. CameraType = CameraType.GIGE;
  87. CameraInfo = device;
  88. IsHaveCamera = true;
  89. break;
  90. }
  91. }
  92. else if ( device.nTLayerType == CSystem.MV_USB_DEVICE )
  93. {
  94. MV_USB3_DEVICE_INFO usbInfo = (MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MV_USB3_DEVICE_INFO));
  95. if ( string.Equals(usbInfo.chSerialNumber, _SerialNumber) )
  96. {
  97. ManufacturerName = usbInfo.chManufacturerName;
  98. ModelName = usbInfo.chModelName;
  99. SerialNumber = usbInfo.chSerialNumber;
  100. CameraType = CameraType.USB;
  101. CameraInfo = device;
  102. IsHaveCamera = true;
  103. break;
  104. }
  105. }
  106. }
  107. IsConnected = false;
  108. }
  109. #region 方法
  110. public List<string> GetListEnum()
  111. {
  112. GC.Collect();
  113. mvCameraAcq = new MvCameraAcqTool.MvCameraAcqTool();
  114. MyCamera.MV_CC_DEVICE_INFO_LIST stDeviceList = default(MyCamera.MV_CC_DEVICE_INFO_LIST);
  115. mvCameraAcq.EnumDeivce(ref stDeviceList);
  116. List<string> listsn = new List<string>();
  117. MyCamera.MV_CC_DEVICE_INFO device = default(MyCamera.MV_CC_DEVICE_INFO);
  118. for ( int i = 0; i < stDeviceList.nDeviceNum; i++ )
  119. {
  120. device = ( MyCamera.MV_CC_DEVICE_INFO ) Marshal.PtrToStructure(stDeviceList.pDeviceInfo[ i ], typeof(MyCamera.MV_CC_DEVICE_INFO));
  121. if ( device.nTLayerType == CSystem.MV_GIGE_DEVICE )
  122. {
  123. MV_GIGE_DEVICE_INFO stGigEDeviceInfo = (MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MV_GIGE_DEVICE_INFO));
  124. listsn.Add(stGigEDeviceInfo.chSerialNumber);
  125. }
  126. else if ( device.nTLayerType == CSystem.MV_USB_DEVICE )
  127. {
  128. MV_USB3_DEVICE_INFO usbInfo = (MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MV_USB3_DEVICE_INFO));
  129. listsn.Add(usbInfo.chSerialNumber);
  130. }
  131. }
  132. return listsn;
  133. }
  134. /// <summary>
  135. /// 打开相机
  136. /// </summary>
  137. /// <returns></returns>
  138. /// <exception cref="Exception"></exception>
  139. public bool OpenDevice()
  140. {
  141. if ( !IsHaveCamera )
  142. {
  143. mvCameraAcq = new MvCameraAcqTool.MvCameraAcqTool();
  144. MyCamera.MV_CC_DEVICE_INFO_LIST stDeviceList = default(MyCamera.MV_CC_DEVICE_INFO_LIST);
  145. mvCameraAcq.EnumDeivce(ref stDeviceList);
  146. MyCamera.MV_CC_DEVICE_INFO device = default(MyCamera.MV_CC_DEVICE_INFO);
  147. for ( int i = 0; i < stDeviceList.nDeviceNum; i++ )
  148. {
  149. device = ( MyCamera.MV_CC_DEVICE_INFO ) Marshal.PtrToStructure(stDeviceList.pDeviceInfo[ i ], typeof(MyCamera.MV_CC_DEVICE_INFO));
  150. if ( device.nTLayerType == CSystem.MV_GIGE_DEVICE )
  151. {
  152. MV_GIGE_DEVICE_INFO stGigEDeviceInfo = (MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MV_GIGE_DEVICE_INFO));
  153. if ( string.Equals(stGigEDeviceInfo.chSerialNumber, SerialNumber) )
  154. {
  155. ManufacturerName = stGigEDeviceInfo.chManufacturerName;
  156. ModelName = stGigEDeviceInfo.chModelName;
  157. SerialNumber = stGigEDeviceInfo.chSerialNumber;
  158. CameraType = CameraType.GIGE;
  159. CameraInfo = device;
  160. IsHaveCamera = true;
  161. break;
  162. }
  163. }
  164. else if ( device.nTLayerType == CSystem.MV_USB_DEVICE )
  165. {
  166. MV_USB3_DEVICE_INFO usbInfo = (MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MV_USB3_DEVICE_INFO));
  167. if ( string.Equals(usbInfo.chSerialNumber, SerialNumber) )
  168. {
  169. ManufacturerName = usbInfo.chManufacturerName;
  170. ModelName = usbInfo.chModelName;
  171. SerialNumber = usbInfo.chSerialNumber;
  172. CameraType = CameraType.USB;
  173. CameraInfo = device;
  174. IsHaveCamera = true;
  175. break;
  176. }
  177. }
  178. }
  179. if ( !IsHaveCamera )
  180. {
  181. throw new Exception("没有发现相机");
  182. }
  183. }
  184. mvCameraAcq.OpenDevice(CameraInfo);
  185. mvCameraAcq.AutoExposure = false;
  186. mvCameraAcq.TriggerMode = false;
  187. if ( !IsConnected )
  188. {
  189. CameraConnectChangedEvent?.Invoke(ID, true);
  190. }
  191. IsConnected = mvCameraAcq.bIsOpened;
  192. return IsConnected;
  193. }
  194. /// <summary>
  195. /// 关闭相机
  196. /// </summary>
  197. public void CloseDevice()
  198. {
  199. // ch:关闭设备 | en:Close Device
  200. mvCameraAcq.CloseDevice();
  201. }
  202. public void SetTriggerModeOn()
  203. {
  204. mvCameraAcq.TriggerMode = true;
  205. }
  206. public void SetTriggerModeOff()
  207. {
  208. mvCameraAcq.TriggerMode = false;
  209. }
  210. public void SetTriggerSoftware(int value = 7)
  211. {
  212. // 设置触发源为Line0
  213. mvCameraAcq.TriggerSoftware =value ;
  214. CCamera.RegisterImageCallBackEx(, IntPtr.Zero);
  215. }
  216. /// <summary>
  217. /// 采集图像
  218. /// </summary>
  219. /// <returns></returns>
  220. public ICogImage Grab()
  221. {
  222. Stopwatch sw = Stopwatch.StartNew();
  223. for ( int i = 0; i < 5; i++ )
  224. {
  225. try
  226. {
  227. if ( !mvCameraAcq.bIsOpened )
  228. {
  229. OpenDevice();
  230. }
  231. mvCameraAcq.Run();
  232. if ( mvCameraAcq.RunStatus.Result == CogToolResultConstants.Accept )
  233. {
  234. ErrorMessage = "";
  235. Image = mvCameraAcq.OutputImage;
  236. if ( !IsConnected )
  237. {
  238. IsConnected = true;
  239. CameraConnectChangedEvent?.Invoke(ID, true);
  240. }
  241. TotalTime = sw.Elapsed;
  242. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  243. return Image;
  244. }
  245. else
  246. {
  247. ErrorMessage = mvCameraAcq.RunStatus.Message;
  248. CloseDevice();
  249. OpenDevice();
  250. }
  251. }
  252. catch ( Exception ex )
  253. {
  254. CloseDevice();
  255. OpenDevice();
  256. ErrorMessage = ex.Message;
  257. }
  258. }
  259. if ( IsConnected )
  260. {
  261. IsConnected = false;
  262. CameraConnectChangedEvent?.Invoke(ID, false);
  263. }
  264. return null;
  265. }
  266. /// <summary>
  267. /// 开始采集图像
  268. /// </summary>
  269. public void StartGrabbing()
  270. {
  271. if ( IsGrabbing )
  272. return;
  273. IsGrabbing = true;
  274. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  275. m_hReceiveThread.Start();
  276. }
  277. /// <summary>
  278. /// 停止采集图像
  279. /// </summary>
  280. public void StopGrabbing()
  281. {
  282. try
  283. {
  284. if ( IsGrabbing )
  285. {
  286. IsGrabbing = false;
  287. Thread.Sleep(1000);
  288. if ( m_hReceiveThread != null )
  289. {
  290. m_hReceiveThread.Abort();
  291. m_hReceiveThread = null;
  292. }
  293. }
  294. }
  295. catch ( Exception )
  296. {
  297. }
  298. }
  299. /// <summary>
  300. /// 设置曝光时间
  301. /// </summary>
  302. /// <param name="ExposureTime"></param>
  303. /// <returns></returns>
  304. public bool SetExposureTime(float ExposureTime)
  305. {
  306. if ( !mvCameraAcq.bIsOpened )
  307. return false;
  308. mvCameraAcq.ExposureTime = ( double ) ExposureTime;
  309. return true;
  310. }
  311. /// <summary>
  312. /// 获取曝光时间
  313. /// </summary>
  314. /// <returns></returns>
  315. public float GetExposureTime()
  316. {
  317. if ( !mvCameraAcq.bIsOpened )
  318. return 0;
  319. return ( float ) mvCameraAcq.ExposureTime;
  320. }
  321. /// <summary>
  322. /// 设置增益
  323. /// </summary>
  324. /// <param name="Gain"></param>
  325. /// <returns></returns>
  326. public bool SetGain(float Gain)
  327. {
  328. if ( !mvCameraAcq.bIsOpened )
  329. return false;
  330. mvCameraAcq.AnalogGain = ( double ) Gain;
  331. return true;
  332. }
  333. /// <summary>
  334. /// 获取增益
  335. /// </summary>
  336. /// <returns></returns>
  337. public float GetGain()
  338. {
  339. if ( !mvCameraAcq.bIsOpened )
  340. return 0;
  341. return ( float ) mvCameraAcq.AnalogGain;
  342. }
  343. private void GetStreamThreadProc()
  344. {
  345. while ( IsGrabbing )
  346. {
  347. try
  348. {
  349. Grab();
  350. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  351. }
  352. catch ( Exception )
  353. {
  354. }
  355. Thread.Sleep(10);
  356. }
  357. IsGrabbing = false;
  358. }
  359. #endregion
  360. #region 属性通知
  361. /// <summary>
  362. /// Occurs when a property value changes.
  363. /// </summary>
  364. public event PropertyChangedEventHandler PropertyChanged;
  365. /// <summary>
  366. /// Checks if a property already matches a desired value. Sets the property and
  367. /// notifies listeners only when necessary.
  368. /// </summary>
  369. /// <typeparam name="T">Type of the property.</typeparam>
  370. /// <param name="storage">Reference to a property with both getter and setter.</param>
  371. /// <param name="value">Desired value for the property.</param>
  372. /// <param name="propertyName">Name of the property used to notify listeners. This
  373. /// value is optional and can be provided automatically when invoked from compilers that
  374. /// support CallerMemberName.</param>
  375. /// <returns>True if the value was changed, false if the existing value matched the
  376. /// desired value.</returns>
  377. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  378. {
  379. if ( EqualityComparer<T>.Default.Equals(storage, value) ) return false;
  380. storage = value;
  381. RaisePropertyChanged(propertyName);
  382. return true;
  383. }
  384. /// <summary>
  385. /// Checks if a property already matches a desired value. Sets the property and
  386. /// notifies listeners only when necessary.
  387. /// </summary>
  388. /// <typeparam name="T">Type of the property.</typeparam>
  389. /// <param name="storage">Reference to a property with both getter and setter.</param>
  390. /// <param name="value">Desired value for the property.</param>
  391. /// <param name="propertyName">Name of the property used to notify listeners. This
  392. /// value is optional and can be provided automatically when invoked from compilers that
  393. /// support CallerMemberName.</param>
  394. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  395. /// <returns>True if the value was changed, false if the existing value matched the
  396. /// desired value.</returns>
  397. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  398. {
  399. if ( EqualityComparer<T>.Default.Equals(storage, value) ) return false;
  400. storage = value;
  401. onChanged?.Invoke();
  402. RaisePropertyChanged(propertyName);
  403. return true;
  404. }
  405. /// <summary>
  406. /// Raises this object's PropertyChanged event.
  407. /// </summary>
  408. /// <param name="propertyName">Name of the property used to notify listeners. This
  409. /// value is optional and can be provided automatically when invoked from compilers
  410. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  411. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  412. {
  413. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  414. }
  415. /// <summary>
  416. /// Raises this object's PropertyChanged event.
  417. /// </summary>
  418. /// <param name="args">The PropertyChangedEventArgs</param>
  419. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  420. {
  421. PropertyChanged?.Invoke(this, args);
  422. }
  423. public bool CheckImageCallbackEvent(Action<ICogImage, TimeSpan, string> CamCallBack)
  424. {
  425. if ( ImageCallbackEvent==null||!ImageCallbackEvent.GetInvocationList().Contains(CamCallBack) )
  426. {
  427. return true;
  428. }
  429. return false;
  430. }
  431. #endregion
  432. }
  433. }