GalaxyCamera.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. using Cognex.VisionPro;
  2. using GxIAPINET;
  3. using MathNet.Numerics.LinearAlgebra;
  4. using Microsoft.Win32;
  5. using NPOI.Util;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Diagnostics;
  10. using System.Drawing;
  11. using System.Drawing.Imaging;
  12. using System.Runtime.CompilerServices;
  13. using System.Runtime.InteropServices;
  14. using System.Text.RegularExpressions;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using TeamAAS_VP.Core.GalaxyMethod;
  18. using TeamAAS_VP.Enums;
  19. using TeamAAS_VP.Interfaces;
  20. using TeamAAS_VP.Models;
  21. using TeamAAS_VP.Resources.Languages;
  22. namespace TeamAAS_VP.Core.Cameras
  23. {
  24. public class GalaxyCamera : CameraBase, ICamera, INotifyPropertyChanged
  25. {
  26. #region 字段
  27. private Thread m_hReceiveThread;
  28. static IGXFactory m_objIGXFactory = null; //Factory对像
  29. IGXDevice m_objIGXDevice = null; //设备对像
  30. IGXStream m_objIGXStream = null; //流对像
  31. static List<IGXDeviceInfo> m_listIGXDeviceInfo = new List<IGXDeviceInfo>(); //设备信息列表
  32. IGXFeatureControl m_objIGXFeatureControl = null; //远端设备属性控制器对像
  33. IGXFeatureControl m_objIGXStreamFeatureControl = null; //流层属性控制器对象
  34. IntPtr m_pOutBuffer = IntPtr.Zero; //图像质量提升或图像格式转换输出Buffer
  35. IntPtr m_pBitmapInfo = IntPtr.Zero;
  36. bool m_bIsColor = false; ///<是否支持彩色相机
  37. byte[] m_byMonoBuffer = null; ///<黑白相机buffer
  38. byte[] m_byColorBuffer = null; ///<彩色相机buffer
  39. int m_nWidth = 0; ///<图像宽度
  40. int m_nHeight = 0; ///<图像高度
  41. IGXImageFormatConvert m_objImageFormatConvert = null; ///<IGXImageFormatConvert对象,仅供图像格式转换使用
  42. CWin32Bitmaps.BITMAPINFO m_objBitmapInfo = new CWin32Bitmaps.BITMAPINFO();
  43. #endregion
  44. #region 属性
  45. public string Name { get; private set; }
  46. public Guid ID { get; private set; }
  47. public int Index { get; set; }
  48. public CameraBrand CameraBrand { get => CameraBrand.Galaxy; }
  49. public bool IsFindByIp { get; private set; }
  50. public string ManufacturerName { get; private set; }
  51. public string ModelName { get; private set; }
  52. public string SerialNumber { get; private set; }
  53. public string CameraIp { get; private set; }
  54. public CameraType CameraType { get; private set; }
  55. private bool _IsGrabbing;
  56. /// <summary>
  57. /// 正在采集
  58. /// </summary>
  59. public bool IsGrabbing
  60. {
  61. get { return _IsGrabbing; }
  62. private set { SetProperty(ref _IsGrabbing, value); }
  63. }
  64. private ICogImage _Image;
  65. public ICogImage Image
  66. {
  67. get { return _Image; }
  68. private set { SetProperty(ref _Image, value); }
  69. }
  70. public bool IsConnected { get; private set; }
  71. public TimeSpan TotalTime { get; private set; }
  72. public string ErrorMessage { get; private set; }
  73. public uint ImageWidth { get; private set; }
  74. public uint ImageHeight { get; private set; }
  75. private bool IsHaveCamera = false;
  76. #endregion
  77. #region 事件
  78. public event Action<ICogImage, TimeSpan, string> ImageCallbackEvent;
  79. public event Action<Guid, bool> CameraConnectChangedEvent;
  80. #endregion
  81. public GalaxyCamera(Guid id, int index, string name, string serialNumber, string cameraip, bool isFindByIp)
  82. {
  83. ID = id;
  84. Name = serialNumber;
  85. Index = index;
  86. CameraIp = cameraip;
  87. SerialNumber = serialNumber;
  88. IsFindByIp = isFindByIp;
  89. var list = GetDevices();
  90. foreach (var device in list)
  91. {
  92. if (device.CameraType== CameraType.GIGE)
  93. {
  94. if (IsFindByIp)
  95. {
  96. if (device.CameraIp == CameraIp)
  97. {
  98. IsHaveCamera = true;
  99. ManufacturerName = device.ManufacturerName;
  100. ModelName = device.Model;
  101. SerialNumber = device.SerialNumber;
  102. CameraType = CameraType.GIGE;
  103. break;
  104. }
  105. }
  106. else
  107. {
  108. if (device.SerialNumber == serialNumber)
  109. {
  110. IsHaveCamera = true;
  111. ManufacturerName = device.ManufacturerName;
  112. ModelName = device.Model;
  113. SerialNumber = device.SerialNumber;
  114. CameraType = CameraType.GIGE;
  115. break;
  116. }
  117. }
  118. }
  119. else
  120. {
  121. if (device.SerialNumber == serialNumber)
  122. {
  123. IsHaveCamera = true;
  124. ManufacturerName = device.ManufacturerName;
  125. ModelName = device.Model;
  126. SerialNumber = device.SerialNumber;
  127. CameraType = CameraType.GIGE;
  128. break;
  129. }
  130. }
  131. }
  132. IsConnected = false;
  133. }
  134. #region 方法
  135. /// <summary>
  136. /// 获取设备
  137. /// </summary>
  138. /// <returns></returns>
  139. public static CameraInfo[] GetDevices()
  140. {
  141. m_objIGXFactory = IGXFactory.GetInstance();
  142. m_objIGXFactory.Init();//相机初始化
  143. List<CameraInfo> cameras = new List<CameraInfo>();
  144. if (!CheckSoftwareInstalled().isInstalled)
  145. {
  146. LogHelper.WriteLogInfo(Lang.未安装GalaxyViewer);
  147. return cameras.ToArray();
  148. }
  149. m_listIGXDeviceInfo.Clear();
  150. if (null != m_objIGXFactory)
  151. {
  152. m_objIGXFactory.UpdateAllDeviceList(200, m_listIGXDeviceInfo);
  153. }
  154. // 判断当前连接设备个数
  155. if (m_listIGXDeviceInfo.Count <= 0)
  156. {
  157. LogHelper.WriteLogInfo(Lang.未检测到设备请确保设备正常连接然后重启程序);
  158. return cameras.ToArray();
  159. }
  160. for (int i = 0; i < m_listIGXDeviceInfo.Count; i++)
  161. {
  162. var deviceType = m_listIGXDeviceInfo[i].GetDeviceClass();
  163. if (deviceType == GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV)
  164. {
  165. cameras.Add(new Models.CameraInfo()
  166. {
  167. CameraNo = i + 1,
  168. CameraName = m_listIGXDeviceInfo[i].GetDisplayName(),
  169. CameraBrand = CameraBrand.Galaxy,
  170. CameraType = CameraType.GIGE,
  171. ManufacturerName = m_listIGXDeviceInfo[i].GetVendorName(),
  172. Model = m_listIGXDeviceInfo[i].GetModelName(),
  173. SerialNumber = m_listIGXDeviceInfo[i].GetSN(),
  174. CameraIp = m_listIGXDeviceInfo[i].GetIP(),
  175. IsFindByIp=true,
  176. });
  177. }
  178. else if (deviceType == GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_USB2 || deviceType == GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_U3V)
  179. {
  180. cameras.Add(new Models.CameraInfo()
  181. {
  182. CameraNo = i + 1,
  183. CameraName = m_listIGXDeviceInfo[i].GetDisplayName(),
  184. CameraBrand = CameraBrand.Galaxy,
  185. CameraType = CameraType.USB,
  186. ManufacturerName = m_listIGXDeviceInfo[i].GetVendorName(),
  187. Model = m_listIGXDeviceInfo[i].GetModelName(),
  188. SerialNumber = m_listIGXDeviceInfo[i].GetSN(),
  189. CameraIp = "",
  190. });
  191. }
  192. else if (deviceType == GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_UNKNOWN)
  193. {
  194. cameras.Add(new Models.CameraInfo()
  195. {
  196. CameraNo = i + 1,
  197. CameraName = m_listIGXDeviceInfo[i].GetDisplayName(),
  198. CameraBrand = CameraBrand.Galaxy,
  199. CameraType = CameraType.Unknown,
  200. ManufacturerName = m_listIGXDeviceInfo[i].GetVendorName(),
  201. Model = m_listIGXDeviceInfo[i].GetModelName(),
  202. SerialNumber = m_listIGXDeviceInfo[i].GetSN(),
  203. CameraIp = "",
  204. });
  205. }
  206. }
  207. return cameras.ToArray();
  208. }
  209. /// <summary>
  210. /// 检查相机软件是否安装
  211. /// </summary>
  212. /// <returns></returns>
  213. public static (bool isInstalled, string version) CheckSoftwareInstalled()
  214. {
  215. string softwareName = "Galaxy";
  216. string softwareVersion = "2.4.2504";
  217. string[] registryPaths = new[]
  218. {
  219. @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
  220. @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  221. };
  222. foreach (var path in registryPaths)
  223. {
  224. using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))
  225. {
  226. if (key == null) continue;
  227. foreach (string subKeyName in key.GetSubKeyNames())
  228. {
  229. using (RegistryKey subKey = key.OpenSubKey(subKeyName))
  230. {
  231. string displayName = subKey.GetValue("DisplayName")?.ToString();
  232. if (displayName != null && displayName.Contains(softwareName))
  233. {
  234. string version = subKey.GetValue("DisplayName")?.ToString();
  235. var match = Regex.Match(version, @"\d+(?:\.\d+)+");
  236. if (match.Success)
  237. {
  238. version = match.Value;
  239. }
  240. else
  241. {
  242. continue;
  243. }
  244. Version v1 = new Version(version);
  245. Version v2 = new Version(softwareVersion);
  246. if (v1 >= v2)
  247. {
  248. return (true, version);
  249. }
  250. else
  251. {
  252. return (false, version);
  253. }
  254. }
  255. }
  256. }
  257. }
  258. }
  259. return (false, "");
  260. }
  261. public void CloseDevice()
  262. {
  263. EnterOperation();
  264. try
  265. {
  266. try
  267. {
  268. if (null != m_objIGXFeatureControl)
  269. {
  270. m_objIGXFeatureControl.GetCommandFeature("AcquisitionStop").Execute();
  271. m_objIGXFeatureControl = null;
  272. }
  273. //停止流通道、注销采集回调和关闭流
  274. if (null != m_objIGXStream)
  275. {
  276. m_objIGXStream.StopGrab();
  277. //注销采集回调函数
  278. m_objIGXStream.UnregisterCaptureCallback();
  279. m_objIGXStream.Close();
  280. m_objIGXStream = null;
  281. m_objIGXStreamFeatureControl = null;
  282. }
  283. //关闭设备
  284. if (null != m_objIGXDevice)
  285. {
  286. m_objIGXDevice.Close();
  287. m_objIGXDevice = null;
  288. }
  289. //反初始化
  290. if (null != m_objIGXFactory)
  291. {
  292. m_objIGXFactory.Uninit();
  293. }
  294. }
  295. catch (Exception)
  296. {
  297. }
  298. ReleaseBuffer();
  299. }
  300. finally
  301. {
  302. ExitOperation();
  303. }
  304. }
  305. public float GetExposureTime()
  306. {
  307. EnterOperation();
  308. try
  309. {
  310. if (null != m_objIGXFeatureControl)
  311. {
  312. double dCurShuter = m_objIGXFeatureControl.GetFloatFeature("ExposureTime").GetValue();
  313. return (float)dCurShuter;
  314. }
  315. else
  316. { return 0; }
  317. }
  318. finally
  319. {
  320. ExitOperation();
  321. }
  322. }
  323. public float GetGain()
  324. {
  325. EnterOperation();
  326. try
  327. {
  328. if (null != m_objIGXFeatureControl)
  329. {
  330. double dCurGain = m_objIGXFeatureControl.GetFloatFeature("Gain").GetValue();
  331. return (float)dCurGain;
  332. }
  333. else
  334. { return 0; }
  335. }
  336. finally
  337. {
  338. ExitOperation();
  339. }
  340. }
  341. public ICogImage Grab()
  342. {
  343. EnterOperation();
  344. try
  345. {
  346. IImageData objIImageData = null;
  347. Stopwatch sw = Stopwatch.StartNew();
  348. for (int j = 0; j < 5; j++)
  349. {
  350. try
  351. {
  352. if (null == m_objIGXDevice)
  353. {
  354. OpenDevice();
  355. }
  356. //开启采集流通道
  357. if (null != m_objIGXStream)
  358. {
  359. m_objIGXStream.StartGrab();
  360. }
  361. //发送开采命令
  362. if (null != m_objIGXFeatureControl)
  363. {
  364. m_objIGXFeatureControl.GetCommandFeature("AcquisitionStart").Execute();
  365. }
  366. objIImageData = m_objIGXStream.GetImageNoThrow(500);
  367. //===================================
  368. GX_VALID_BIT_LIST emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
  369. if (null != objIImageData)
  370. {
  371. emValidBits = GetBestValudBit(objIImageData.GetPixelFormat());
  372. if (GX_FRAME_STATUS_LIST.GX_FRAME_STATUS_SUCCESS == objIImageData.GetStatus())
  373. {
  374. if (m_bIsColor)
  375. {
  376. IntPtr pRGB24Buffer = IntPtr.Zero;
  377. if (objIImageData.GetPixelFormat() == GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8)
  378. {
  379. byte[] byColorBufferTmp = new byte[__GetStride(m_nWidth, m_bIsColor) * m_nHeight];
  380. Marshal.Copy(objIImageData.GetBuffer(), byColorBufferTmp, 0, __GetStride(m_nWidth, m_bIsColor) * m_nHeight);
  381. pRGB24Buffer = objIImageData.GetBuffer();
  382. //BGR8格式需要翻转数据后显示
  383. for (int i = 0; i < m_nHeight; i++)
  384. {
  385. Buffer.BlockCopy(byColorBufferTmp, (m_nHeight - i - 1) * m_nWidth * 3, m_byColorBuffer, i * m_nWidth * 3, m_nWidth * 3);
  386. }
  387. }
  388. else
  389. {
  390. // 设置目标像素格式
  391. m_objImageFormatConvert.SetDstFormat(GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8);
  392. // 获取目标像素格式Buffer大小
  393. UInt64 i64DstBufferize = m_objImageFormatConvert.GetBufferSizeForConversion(objIImageData);
  394. // 设置目标有效位数
  395. m_objImageFormatConvert.SetValidBits(emValidBits);
  396. // 进行图像格式转换
  397. m_objImageFormatConvert.Convert(objIImageData, m_pOutBuffer, i64DstBufferize, true);
  398. Marshal.Copy(m_pOutBuffer, m_byColorBuffer, 0, __GetStride(m_nWidth, m_bIsColor) * m_nHeight);
  399. pRGB24Buffer = m_pOutBuffer;
  400. }
  401. Image = ConvertImage((uint)m_nWidth, (uint)m_nHeight, pRGB24Buffer, GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8);
  402. }
  403. else
  404. {
  405. IntPtr pRaw8Buffer = IntPtr.Zero;
  406. if (__IsPixelFormat8(objIImageData.GetPixelFormat()))
  407. {
  408. byte[] byMonoBufferTmp = new byte[__GetStride(m_nWidth, m_bIsColor) * m_nHeight];
  409. Marshal.Copy(objIImageData.GetBuffer(), byMonoBufferTmp, 0, __GetStride(m_nWidth, m_bIsColor) * m_nHeight);
  410. pRaw8Buffer = objIImageData.GetBuffer();
  411. // 黑白相机需要翻转数据后显示
  412. for (int i = 0; i < m_nHeight; i++)
  413. {
  414. Buffer.BlockCopy(byMonoBufferTmp, (m_nHeight - i - 1) * m_nWidth, m_byMonoBuffer, i * m_nWidth, m_nWidth);
  415. }
  416. }
  417. else
  418. {
  419. // 设置目标像素格式
  420. m_objImageFormatConvert.SetDstFormat(GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8);
  421. // 获取目标像素格式Buffer大小
  422. UInt64 i64DstBufferize = m_objImageFormatConvert.GetBufferSizeForConversion(objIImageData);
  423. // 设置目标有效位数
  424. m_objImageFormatConvert.SetValidBits(emValidBits);
  425. // 进行图像格式转换
  426. m_objImageFormatConvert.Convert(objIImageData, m_pOutBuffer, i64DstBufferize, true);
  427. Marshal.Copy(m_pOutBuffer, m_byMonoBuffer, 0, __GetStride(m_nWidth, m_bIsColor) * m_nHeight);
  428. pRaw8Buffer = m_pOutBuffer;
  429. }
  430. Image = ConvertImage((uint)m_nWidth, (uint)m_nHeight, pRaw8Buffer, GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8);
  431. }
  432. }
  433. }
  434. if (Image != null)
  435. {
  436. ErrorMessage = "";
  437. TotalTime = sw.Elapsed;
  438. return Image;
  439. }
  440. }
  441. catch (Exception ex)
  442. {
  443. CloseDevice();
  444. OpenDevice();
  445. ErrorMessage = ex.Message;
  446. }
  447. finally
  448. {
  449. if (null != objIImageData)
  450. {
  451. //用完之后释放资源
  452. objIImageData.Destroy();
  453. }
  454. }
  455. }
  456. if (IsConnected)
  457. {
  458. IsConnected = false;
  459. CameraConnectChangedEvent?.Invoke(ID, false);
  460. }
  461. return null;
  462. }
  463. finally
  464. {
  465. ExitOperation();
  466. }
  467. }
  468. public bool OpenDevice()
  469. {
  470. EnterOperation();
  471. try
  472. {
  473. IsConnected = false;
  474. var list = GetDevices();
  475. foreach (var device in list)
  476. {
  477. if (device.CameraType == CameraType.GIGE)
  478. {
  479. if (IsFindByIp)
  480. {
  481. if (device.CameraIp == CameraIp)
  482. {
  483. IsHaveCamera = true;
  484. ManufacturerName = device.ManufacturerName;
  485. ModelName = device.Model;
  486. SerialNumber = device.SerialNumber;
  487. CameraType = CameraType.GIGE;
  488. break;
  489. }
  490. }
  491. else
  492. {
  493. if (device.SerialNumber == SerialNumber)
  494. {
  495. IsHaveCamera = true;
  496. ManufacturerName = device.ManufacturerName;
  497. ModelName = device.Model;
  498. SerialNumber = device.SerialNumber;
  499. CameraType = CameraType.GIGE;
  500. break;
  501. }
  502. }
  503. }
  504. else
  505. {
  506. if (device.SerialNumber == SerialNumber)
  507. {
  508. IsHaveCamera = true;
  509. ManufacturerName = device.ManufacturerName;
  510. ModelName = device.Model;
  511. SerialNumber = device.SerialNumber;
  512. CameraType = CameraType.GIGE;
  513. break;
  514. }
  515. }
  516. }
  517. if (!IsHaveCamera)
  518. {
  519. //throw new Exception("没有发现相机");
  520. return false;
  521. }
  522. // 如果设备已经打开则关闭,保证相机在初始化出错情况下能再次打开
  523. if (null != m_objIGXDevice)
  524. {
  525. m_objIGXDevice.Close();
  526. m_objIGXDevice = null;
  527. }
  528. //打开设备
  529. m_objIGXDevice = m_objIGXFactory.OpenDeviceBySN(SerialNumber, GxIAPINET.GX_ACCESS_MODE.GX_ACCESS_EXCLUSIVE);
  530. m_objIGXFeatureControl = m_objIGXDevice.GetRemoteFeatureControl();
  531. //打开流
  532. if (null != m_objIGXDevice)
  533. {
  534. m_objIGXStream = m_objIGXDevice.OpenStream(0);
  535. m_objIGXStreamFeatureControl = m_objIGXStream.GetFeatureControl();
  536. }
  537. // 建议用户在打开网络相机之后,根据当前网络环境设置相机的流通道包长值,
  538. // 以提高网络相机的采集性能,设置方法参考以下代码。
  539. GX_DEVICE_CLASS_LIST objDeviceClass = m_objIGXDevice.GetDeviceInfo().GetDeviceClass();
  540. if (GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV == objDeviceClass)
  541. {
  542. // 判断设备是否支持流通道数据包功能
  543. if (true == m_objIGXFeatureControl.IsImplemented("GevSCPSPacketSize"))
  544. {
  545. // 获取当前网络环境的最优包长值
  546. uint nPacketSize = m_objIGXStream.GetOptimalPacketSize();
  547. // 将最优包长值设置为当前设备的流通道包长值
  548. m_objIGXFeatureControl.GetIntFeature("GevSCPSPacketSize").SetValue(nPacketSize);
  549. }
  550. }
  551. //初始化相机参数
  552. if (null != m_objIGXFeatureControl)
  553. {
  554. //设置采集模式连续采集
  555. m_objIGXFeatureControl.GetEnumFeature("AcquisitionMode").SetValue("Continuous");
  556. //设置触发模式为关
  557. m_objIGXFeatureControl.GetEnumFeature("TriggerMode").SetValue("Off");
  558. }
  559. ReleaseBuffer();
  560. GxBitmap();
  561. if (null != m_objIGXStreamFeatureControl)
  562. {
  563. try
  564. {
  565. //设置流层Buffer处理模式为OldestFirst
  566. m_objIGXStreamFeatureControl.GetEnumFeature("StreamBufferHandlingMode").SetValue("OldestFirst");
  567. }
  568. catch (Exception)
  569. {
  570. }
  571. }
  572. if (!IsConnected)
  573. {
  574. CameraConnectChangedEvent?.Invoke(ID, true);
  575. }
  576. IsConnected = true;
  577. return IsConnected;
  578. }
  579. finally
  580. {
  581. ExitOperation();
  582. }
  583. }
  584. /// <summary>
  585. /// 打开相机异步
  586. /// </summary>
  587. /// <returns></returns>
  588. public Task<bool> OpenDeviceAsync()
  589. {
  590. return Task.Run(() =>
  591. {
  592. return OpenDevice();
  593. });
  594. }
  595. public bool SetExposureTime(float ExposureTime)
  596. {
  597. EnterOperation();
  598. try
  599. {
  600. if (null == m_objIGXFeatureControl)
  601. return false;
  602. if (GetExposureTime() != ExposureTime)
  603. {
  604. bool success = false;
  605. for (int i = 0; i < 5; i++)
  606. {
  607. m_objIGXFeatureControl.GetFloatFeature("ExposureTime").SetValue(ExposureTime);
  608. success = true;
  609. }
  610. return success;
  611. }
  612. return true;
  613. }
  614. finally
  615. {
  616. ExitOperation();
  617. }
  618. }
  619. public bool SetGain(float Gain)
  620. {
  621. EnterOperation();
  622. try
  623. {
  624. if (null == m_objIGXFeatureControl)
  625. return false;
  626. if (GetGain() != Gain)
  627. {
  628. bool success = false;
  629. for (int i = 0; i < 5; i++)
  630. {
  631. m_objIGXFeatureControl.GetFloatFeature("Gain").SetValue(Gain);
  632. success = true;
  633. }
  634. return success;
  635. }
  636. return true;
  637. }
  638. finally
  639. {
  640. ExitOperation();
  641. }
  642. }
  643. public void StartGrabbing()
  644. {
  645. lock (_stateLock)
  646. {
  647. if (IsGrabbing)
  648. return;
  649. IsGrabbing = true;
  650. }
  651. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  652. m_hReceiveThread.Start();
  653. }
  654. public void StopGrabbing()
  655. {
  656. try
  657. {
  658. lock (_stateLock)
  659. {
  660. IsGrabbing = false;
  661. }
  662. Thread.Sleep(1000);
  663. if (m_hReceiveThread != null)
  664. {
  665. m_hReceiveThread.Abort();
  666. m_hReceiveThread = null;
  667. }
  668. }
  669. catch (Exception)
  670. {
  671. }
  672. }
  673. private void GetStreamThreadProc()
  674. {
  675. while (IsGrabbing)
  676. {
  677. try
  678. {
  679. Grab();
  680. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  681. }
  682. catch (Exception)
  683. {
  684. }
  685. Thread.Sleep(10);
  686. }
  687. IsGrabbing = false;
  688. }
  689. #endregion
  690. #region method
  691. /// <summary>
  692. /// 初始化设备对象
  693. /// </summary>
  694. /// <param name="objIGXDevice">设备对象</param>
  695. public void GxBitmap()
  696. {
  697. // 初始化图像格式转换对象
  698. m_objImageFormatConvert = m_objIGXFactory.CreateImageFormatConvert();
  699. if (null != m_objIGXDevice)
  700. {
  701. m_nWidth = (int)m_objIGXDevice.GetRemoteFeatureControl().GetIntFeature("Width").GetValue();
  702. m_nHeight = (int)m_objIGXDevice.GetRemoteFeatureControl().GetIntFeature("Height").GetValue();
  703. ImageWidth = (uint)m_nWidth;
  704. ImageHeight = (uint)m_nHeight;
  705. //获取是否为彩色相机
  706. IsSupportColor(ref m_bIsColor);
  707. }
  708. //申请用于缓存图像数据的buffer
  709. m_byMonoBuffer = new byte[__GetStride(m_nWidth, m_bIsColor) * m_nHeight];
  710. m_byColorBuffer = new byte[__GetStride(m_nWidth, m_bIsColor) * m_nHeight];
  711. m_pOutBuffer = Marshal.AllocCoTaskMem(__GetStride(m_nWidth, m_bIsColor) * m_nHeight);
  712. if (m_bIsColor)
  713. {
  714. m_objBitmapInfo.bmiHeader.biSize = (uint)Marshal.SizeOf(typeof(CWin32Bitmaps.BITMAPINFOHEADER));
  715. m_objBitmapInfo.bmiHeader.biWidth = m_nWidth;
  716. m_objBitmapInfo.bmiHeader.biHeight = m_nHeight;
  717. m_objBitmapInfo.bmiHeader.biPlanes = 1;
  718. m_objBitmapInfo.bmiHeader.biBitCount = 24;
  719. m_objBitmapInfo.bmiHeader.biCompression = 0;
  720. m_objBitmapInfo.bmiHeader.biSizeImage = 0;
  721. m_objBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
  722. m_objBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
  723. m_objBitmapInfo.bmiHeader.biClrUsed = 0;
  724. m_objBitmapInfo.bmiHeader.biClrImportant = 0;
  725. }
  726. else
  727. {
  728. m_objBitmapInfo.bmiHeader.biSize = (uint)Marshal.SizeOf(typeof(CWin32Bitmaps.BITMAPINFOHEADER));
  729. m_objBitmapInfo.bmiHeader.biWidth = m_nWidth;
  730. m_objBitmapInfo.bmiHeader.biHeight = m_nHeight;
  731. m_objBitmapInfo.bmiHeader.biPlanes = 1;
  732. m_objBitmapInfo.bmiHeader.biBitCount = 8;
  733. m_objBitmapInfo.bmiHeader.biCompression = 0;
  734. m_objBitmapInfo.bmiHeader.biSizeImage = 0;
  735. m_objBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
  736. m_objBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
  737. m_objBitmapInfo.bmiHeader.biClrUsed = 0;
  738. m_objBitmapInfo.bmiHeader.biClrImportant = 0;
  739. m_objBitmapInfo.bmiColors = new CWin32Bitmaps.RGBQUAD[256];
  740. // 黑白图像需要初始化调色板
  741. for (int i = 0; i < 256; i++)
  742. {
  743. m_objBitmapInfo.bmiColors[i].rgbBlue = (byte)i;
  744. m_objBitmapInfo.bmiColors[i].rgbGreen = (byte)i;
  745. m_objBitmapInfo.bmiColors[i].rgbRed = (byte)i;
  746. m_objBitmapInfo.bmiColors[i].rgbReserved = 0;
  747. }
  748. }
  749. m_pBitmapInfo = Marshal.AllocHGlobal(2048);
  750. Marshal.StructureToPtr(m_objBitmapInfo, m_pBitmapInfo, false);
  751. }
  752. /// <summary>
  753. /// 释放buffer
  754. /// </summary>
  755. public void ReleaseBuffer()
  756. {
  757. // 释放输出Buffer内存
  758. if (m_pOutBuffer != IntPtr.Zero)
  759. {
  760. Marshal.FreeCoTaskMem(m_pOutBuffer);
  761. m_pOutBuffer = IntPtr.Zero;
  762. }
  763. if (m_pBitmapInfo != IntPtr.Zero)
  764. {
  765. Marshal.FreeHGlobal(m_pBitmapInfo);
  766. m_pBitmapInfo = IntPtr.Zero;
  767. }
  768. }
  769. /// <summary>
  770. /// 是否支持彩色
  771. /// </summary>
  772. /// <param name="bIsColorFilter">是否支持彩色</param>
  773. public void IsSupportColor(ref bool bIsColorFilter)
  774. {
  775. bool bIsImplemented = false;
  776. bool bIsMono = false;
  777. string strPixelFormat = "";
  778. uint nPixelFormatValue = 0;
  779. strPixelFormat = m_objIGXDevice.GetRemoteFeatureControl().GetEnumFeature("PixelFormat").GetValue();
  780. if (0 == string.Compare(strPixelFormat, 0, "Mono", 0, 4))
  781. {
  782. bIsMono = true;
  783. }
  784. else
  785. {
  786. bIsMono = false;
  787. }
  788. // 通过当前像素格式判断是否为彩色相机
  789. CDecide.GetConvertPixelFormat(strPixelFormat, ref nPixelFormatValue);
  790. bIsImplemented = CDecide.GetIsGray(nPixelFormatValue);
  791. if ((!bIsMono) && (!bIsImplemented))
  792. {
  793. bIsColorFilter = true;
  794. }
  795. else
  796. {
  797. bIsColorFilter = false;
  798. }
  799. }
  800. /// <summary>
  801. /// 计算宽度所占的字节数
  802. /// </summary>
  803. /// <param name="nWidth">图像宽度</param>
  804. /// <param name="bIsColor">是否是彩色相机</param>
  805. /// <returns>图像一行所占的字节数</returns>
  806. private int __GetStride(int nWidth, bool bIsColor)
  807. {
  808. return bIsColor ? nWidth * 3 : nWidth;
  809. }
  810. /// <summary>
  811. /// 通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位
  812. /// </summary>
  813. /// <param name="em">图像数据格式</param>
  814. /// <returns>最优Bit位</returns>
  815. public GX_VALID_BIT_LIST GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry)
  816. {
  817. GX_VALID_BIT_LIST emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
  818. switch (emPixelFormatEntry)
  819. {
  820. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8:
  821. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR8:
  822. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG8:
  823. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB8:
  824. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG8:
  825. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8:
  826. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8:
  827. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_R8:
  828. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_G8:
  829. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_B8:
  830. {
  831. emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
  832. break;
  833. }
  834. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10:
  835. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_P:
  836. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_PACKED:
  837. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10:
  838. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10:
  839. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10:
  840. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10:
  841. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_P:
  842. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_PACKED:
  843. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_P:
  844. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_PACKED:
  845. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_P:
  846. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_PACKED:
  847. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_P:
  848. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_PACKED:
  849. {
  850. emValidBits = GX_VALID_BIT_LIST.GX_BIT_2_9;
  851. break;
  852. }
  853. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12:
  854. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_P:
  855. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_PACKED:
  856. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12:
  857. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12:
  858. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12:
  859. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12:
  860. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_P:
  861. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_PACKED:
  862. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_P:
  863. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_PACKED:
  864. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_P:
  865. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_PACKED:
  866. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_P:
  867. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_PACKED:
  868. {
  869. emValidBits = GX_VALID_BIT_LIST.GX_BIT_4_11;
  870. break;
  871. }
  872. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14:
  873. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14:
  874. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14:
  875. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14:
  876. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14:
  877. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14_P:
  878. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14_P:
  879. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14_P:
  880. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14_P:
  881. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14_P:
  882. {
  883. emValidBits = GX_VALID_BIT_LIST.GX_BIT_6_13;
  884. break;
  885. }
  886. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO16:
  887. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR16:
  888. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG16:
  889. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB16:
  890. case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG16:
  891. {
  892. emValidBits = GX_VALID_BIT_LIST.GX_BIT_8_15;
  893. break;
  894. }
  895. default:
  896. break;
  897. }
  898. return emValidBits;
  899. }
  900. /// <summary>
  901. /// 判断PixelFormat是否为8位
  902. /// </summary>
  903. /// <param name="emPixelFormatEntry">图像数据格式</param>
  904. /// <returns>true为8为数据,false为非8位数据</returns>
  905. private bool __IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry)
  906. {
  907. const uint PIXEL_FORMATE_BIT = 0x00FF0000; //用于与当前的数据格式进行与运算得到当前的数据位数
  908. const uint GX_PIXEL_8BIT = 0x00080000; //8位数据图像格式
  909. bool bIsPixelFormat8 = false;
  910. uint uiPixelFormatEntry = (uint)emPixelFormatEntry;
  911. if ((uiPixelFormatEntry & PIXEL_FORMATE_BIT) == GX_PIXEL_8BIT)
  912. {
  913. bIsPixelFormat8 = true;
  914. }
  915. return bIsPixelFormat8;
  916. }
  917. /// <summary>
  918. /// 转换图片
  919. /// </summary>
  920. /// <param name="nHeight">高</param>
  921. /// <param name="nWidth">宽</param>
  922. /// <param name="pImageBuf">图片数据</param>
  923. /// <param name="enPixelType">像素格式</param>
  924. public ICogImage ConvertImage(UInt32 nWidth, UInt32 nHeight, IntPtr pImageBuf, GX_PIXEL_FORMAT_ENTRY enPixelType)
  925. {
  926. try
  927. {
  928. if (enPixelType == GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8)
  929. {
  930. CogImage8Root cogImage8Root = new CogImage8Root();
  931. cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null);
  932. CogImage8Grey cogImage8Grey = new CogImage8Grey();
  933. cogImage8Grey.SetRoot(cogImage8Root);
  934. var image = cogImage8Grey.ScaleImage((int)nWidth, (int)nHeight);
  935. System.GC.Collect();
  936. return image;
  937. }
  938. else
  939. {
  940. int stride = (int)nWidth * 3;
  941. CogImage24PlanarColor cogImage24PlanarColor = new CogImage24PlanarColor(new Bitmap((int)nWidth, (int)nHeight, stride, PixelFormat.Format24bppRgb, pImageBuf));
  942. var m_InputImageRgb24 = cogImage24PlanarColor.Copy(CogImageCopyModeConstants.CopyPixels);
  943. return m_InputImageRgb24;
  944. }
  945. }
  946. catch (System.Exception)
  947. {
  948. return null;
  949. }
  950. }
  951. #endregion
  952. #region 属性通知
  953. /// <summary>
  954. /// Occurs when a property value changes.
  955. /// </summary>
  956. public event PropertyChangedEventHandler PropertyChanged;
  957. /// <summary>
  958. /// Checks if a property already matches a desired value. Sets the property and
  959. /// notifies listeners only when necessary.
  960. /// </summary>
  961. /// <typeparam name="T">Type of the property.</typeparam>
  962. /// <param name="storage">Reference to a property with both getter and setter.</param>
  963. /// <param name="value">Desired value for the property.</param>
  964. /// <param name="propertyName">Name of the property used to notify listeners. This
  965. /// value is optional and can be provided automatically when invoked from compilers that
  966. /// support CallerMemberName.</param>
  967. /// <returns>True if the value was changed, false if the existing value matched the
  968. /// desired value.</returns>
  969. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  970. {
  971. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  972. storage = value;
  973. RaisePropertyChanged(propertyName);
  974. return true;
  975. }
  976. /// <summary>
  977. /// Checks if a property already matches a desired value. Sets the property and
  978. /// notifies listeners only when necessary.
  979. /// </summary>
  980. /// <typeparam name="T">Type of the property.</typeparam>
  981. /// <param name="storage">Reference to a property with both getter and setter.</param>
  982. /// <param name="value">Desired value for the property.</param>
  983. /// <param name="propertyName">Name of the property used to notify listeners. This
  984. /// value is optional and can be provided automatically when invoked from compilers that
  985. /// support CallerMemberName.</param>
  986. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  987. /// <returns>True if the value was changed, false if the existing value matched the
  988. /// desired value.</returns>
  989. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  990. {
  991. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  992. storage = value;
  993. onChanged?.Invoke();
  994. RaisePropertyChanged(propertyName);
  995. return true;
  996. }
  997. /// <summary>
  998. /// Raises this object's PropertyChanged event.
  999. /// </summary>
  1000. /// <param name="propertyName">Name of the property used to notify listeners. This
  1001. /// value is optional and can be provided automatically when invoked from compilers
  1002. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  1003. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  1004. {
  1005. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  1006. }
  1007. /// <summary>
  1008. /// Raises this object's PropertyChanged event.
  1009. /// </summary>
  1010. /// <param name="args">The PropertyChangedEventArgs</param>
  1011. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  1012. {
  1013. PropertyChanged?.Invoke(this, args);
  1014. }
  1015. #endregion
  1016. }
  1017. }