GalaxyCamera.cs 45 KB

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