OptCamera.cs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. using Cognex.VisionPro;
  2. using Microsoft.Win32;
  3. using netDxf.Entities;
  4. using NPOI.POIFS.Crypt.Dsig;
  5. using NPOI.SS.Formula;
  6. using NPOI.SS.Formula.Eval;
  7. using SciCamera.Net;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.ComponentModel;
  11. using System.Diagnostics;
  12. using System.Drawing;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Runtime.CompilerServices;
  16. using System.Runtime.InteropServices;
  17. using System.Text;
  18. using System.Threading;
  19. using System.Threading.Tasks;
  20. using System.Web.Configuration;
  21. using TeamAAS_VP.Enums;
  22. using TeamAAS_VP.Interfaces;
  23. using TeamAAS_VP.Models;
  24. namespace TeamAAS_VP.Core.Cameras
  25. {
  26. public class OptCamera : ICamera, INotifyPropertyChanged
  27. {
  28. #region 字段
  29. private Thread m_hReceiveThread;
  30. // 用于序列化对同一相机实例的操作,防止同一实例被并发操作
  31. //private readonly SemaphoreSlim _operationSemaphore = new SemaphoreSlim(1, 1);
  32. // 用于保护状态变量(例如 IsGrabbing)的并发访问
  33. private readonly object _stateLock = new object();
  34. private TaskCompletionSource<ICogImage> _tcs;
  35. #endregion
  36. #region 属性
  37. public CameraBrand CameraBrand { get => CameraBrand.Opt; }
  38. public string Name { get; private set; }
  39. public Guid ID { get; private set; }
  40. public int Index { get; set; }
  41. public string ManufacturerName { get; private set; }
  42. public bool IsFindByIp { get; private set; }
  43. public string ModelName { get; private set; }
  44. public string SerialNumber { get; private set; }
  45. public string CameraIp { get; private set; }
  46. public CameraType CameraType { get; private set; }
  47. SciCam mvCameraAcq;
  48. public SciCam.SCI_DEVICE_INFO CameraInfo { get; private set; }
  49. public UInt32 ImageWidth { get; private set; }
  50. public UInt32 ImageHeight { get; private set; }
  51. public SciCam.SciCamPixelType PixelType { get; private set; }
  52. private bool _IsGrabbing;
  53. /// <summary>
  54. /// 正在采集
  55. /// </summary>
  56. public bool IsGrabbing
  57. {
  58. get { return _IsGrabbing; }
  59. private set { SetProperty(ref _IsGrabbing, value); }
  60. }
  61. private ICogImage _Image;
  62. public ICogImage Image
  63. {
  64. get { return _Image; }
  65. private set { SetProperty(ref _Image, value); }
  66. }
  67. public bool IsConnected { get; private set; }
  68. private bool IsHaveCamera = false;
  69. /// <summary>
  70. /// 采集用时
  71. /// </summary>
  72. public TimeSpan TotalTime { get; private set; }
  73. /// <summary>
  74. /// 错误信息
  75. /// </summary>
  76. public string ErrorMessage { get; private set; }
  77. //当前的图像采集模式
  78. public SciCam.SciCamGrabStrategy CurrentGrabStrategy { get; private set; } = SciCam.SciCamGrabStrategy.SciCam_GrabStrategy_Latest;
  79. #endregion
  80. #region 事件
  81. public event Action<ICogImage, TimeSpan, string> ImageCallbackEvent;
  82. public event Action<Guid, bool> CameraConnectChangedEvent;
  83. #endregion
  84. public OptCamera(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. mvCameraAcq = new SciCam();
  93. SciCam.SCI_DEVICE_INFO_LIST stDeviceList = new SciCam.SCI_DEVICE_INFO_LIST(); //设备列表
  94. uint nReVal = SciCam.DiscoveryDevices(ref stDeviceList, (uint)(SciCam.SciCamTLType.SciCam_TLType_Gige));
  95. if (nReVal != SciCam.SCI_CAMERA_OK)
  96. {
  97. return;
  98. }
  99. for (int i = 0; i < stDeviceList.count; i++)
  100. {
  101. SciCam.SCI_DEVICE_INFO device = stDeviceList.pDevInfo[i];
  102. SciCam.SciCamTLType devTlType = device.tlType;
  103. if (devTlType == SciCam.SciCamTLType.SciCam_TLType_Gige)
  104. {
  105. SciCam.SCI_DEVICE_GIGE_INFO gigeDevInfo = (SciCam.SCI_DEVICE_GIGE_INFO)SciCam.ByteToStruct(device.info.gigeInfo, typeof(SciCam.SCI_DEVICE_GIGE_INFO));
  106. uint ip1 = gigeDevInfo.ip;
  107. int nIp1 = (int)(ip1 & 0x000000ff);
  108. int nIp2 = (int)((ip1 & 0x0000ff00) >> 8);
  109. int nIp3 = (int)((ip1 & 0x00ff0000) >> 16);
  110. int nIp4 = (int)((ip1 & 0xff000000) >> 24);
  111. string ip = string.Format("{0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
  112. if (IsFindByIp)
  113. {
  114. if (CameraIp == ip)
  115. {
  116. ManufacturerName = gigeDevInfo.manufactureName;
  117. ModelName = gigeDevInfo.modelName;
  118. SerialNumber = gigeDevInfo.serialNumber;
  119. CameraType = CameraType.GIGE;
  120. CameraInfo = device;
  121. IsHaveCamera = true;
  122. break;
  123. }
  124. }
  125. else
  126. {
  127. if (string.Equals(gigeDevInfo.serialNumber, serialNumber))
  128. {
  129. ManufacturerName = gigeDevInfo.manufactureName;
  130. ModelName = gigeDevInfo.modelName;
  131. SerialNumber = gigeDevInfo.serialNumber;
  132. CameraType = CameraType.GIGE;
  133. CameraInfo = device;
  134. IsHaveCamera = true;
  135. break;
  136. }
  137. }
  138. }
  139. }
  140. IsConnected = false;
  141. }
  142. #region 方法
  143. /// <summary>
  144. /// 获取设备
  145. /// </summary>
  146. /// <returns></returns>
  147. public static CameraInfo[] GetDevices()
  148. {
  149. List<CameraInfo> cameras = new List<CameraInfo>();
  150. try
  151. {
  152. if (!CheckSoftwareInstalled().isInstalled)
  153. {
  154. LogHelper.WriteLogInfo("未安装OPT");
  155. return cameras.ToArray();
  156. }
  157. SciCam.SCI_DEVICE_INFO_LIST stDeviceList = new SciCam.SCI_DEVICE_INFO_LIST(); //设备列表
  158. uint nReVal = SciCam.DiscoveryDevices(ref stDeviceList, (uint)(SciCam.SciCamTLType.SciCam_TLType_Gige));
  159. if (nReVal != SciCam.SCI_CAMERA_OK)
  160. {
  161. return cameras.ToArray();
  162. }
  163. for (int i = 0; i < stDeviceList.count; i++)
  164. {
  165. SciCam.SCI_DEVICE_INFO device = stDeviceList.pDevInfo[i];
  166. SciCam.SciCamTLType devTlType = device.tlType;
  167. if (devTlType == SciCam.SciCamTLType.SciCam_TLType_Gige)
  168. {
  169. SciCam.SCI_DEVICE_GIGE_INFO gigeDevInfo = (SciCam.SCI_DEVICE_GIGE_INFO)SciCam.ByteToStruct(device.info.gigeInfo, typeof(SciCam.SCI_DEVICE_GIGE_INFO));
  170. uint ip1 = gigeDevInfo.ip;
  171. int nIp1 = (int)(ip1 & 0x000000ff);
  172. int nIp2 = (int)((ip1 & 0x0000ff00) >> 8);
  173. int nIp3 = (int)((ip1 & 0x00ff0000) >> 16);
  174. int nIp4 = (int)((ip1 & 0xff000000) >> 24);
  175. string ip = string.Format("{0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
  176. cameras.Add(new CameraInfo()
  177. {
  178. CameraNo = i + 1,
  179. CameraName = gigeDevInfo.name,
  180. CameraBrand = CameraBrand.Opt,
  181. CameraType = CameraType.GIGE,
  182. ManufacturerName = gigeDevInfo.manufactureName,
  183. Model = gigeDevInfo.modelName,
  184. SerialNumber = gigeDevInfo.serialNumber,
  185. CameraIp = ip,
  186. IsFindByIp = true,
  187. });
  188. }
  189. }
  190. }
  191. catch (Exception ex)
  192. {
  193. LogHelper.WriteLogError("搜索OPT相机列表时出错!", ex);
  194. }
  195. return cameras.ToArray();
  196. }
  197. /// <summary>
  198. /// 检查相机软件是否安装
  199. /// </summary>
  200. /// <returns></returns>
  201. public static (bool isInstalled, string version) CheckSoftwareInstalled()
  202. {
  203. //string softwareName = "OPT Camera Viewer";
  204. //string softwareVersion = "4.0.0.3";
  205. //string[] registryPaths = new[]
  206. //{
  207. // @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
  208. // @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  209. //};
  210. //foreach (var path in registryPaths)
  211. //{
  212. // using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))
  213. // {
  214. // if (key == null) continue;
  215. // foreach (string subKeyName in key.GetSubKeyNames())
  216. // {
  217. // using (RegistryKey subKey = key.OpenSubKey(subKeyName))
  218. // {
  219. // string displayName = subKey.GetValue("DisplayName")?.ToString();
  220. // if (displayName != null && displayName.ToUpper().Trim() == softwareName.ToUpper())
  221. // {
  222. // string version = subKey.GetValue("DisplayVersion")?.ToString();
  223. // Version v1 = new Version(version);
  224. // Version v2 = new Version(softwareVersion);
  225. // if (v1 >= v2)
  226. // {
  227. // return (true, version);
  228. // }
  229. // else
  230. // {
  231. // return (false, version);
  232. // }
  233. // }
  234. // }
  235. // }
  236. // }
  237. //}
  238. //return (false, "");
  239. return (true, "4.0.0.3"); // TODO: Opt相机不检查软件安装
  240. }
  241. /// <summary>
  242. /// 打开相机
  243. /// </summary>
  244. /// <returns></returns>
  245. /// <exception cref="Exception"></exception>
  246. public bool OpenDevice()
  247. {
  248. //_operationSemaphore.Wait();
  249. uint nReVal = SciCam.SCI_CAMERA_OK;
  250. try
  251. {
  252. if (!IsHaveCamera)
  253. {
  254. mvCameraAcq = new SciCam();
  255. SciCam.SCI_DEVICE_INFO_LIST stDeviceList = new SciCam.SCI_DEVICE_INFO_LIST(); //设备列表
  256. nReVal = SciCam.DiscoveryDevices(ref stDeviceList, (uint)(SciCam.SciCamTLType.SciCam_TLType_Gige));
  257. if (nReVal != SciCam.SCI_CAMERA_OK)
  258. {
  259. return false;
  260. }
  261. for (int i = 0; i < stDeviceList.count; i++)
  262. {
  263. SciCam.SCI_DEVICE_INFO device = stDeviceList.pDevInfo[i];
  264. SciCam.SciCamTLType devTlType = device.tlType;
  265. if (devTlType == SciCam.SciCamTLType.SciCam_TLType_Gige)
  266. {
  267. SciCam.SCI_DEVICE_GIGE_INFO gigeDevInfo = (SciCam.SCI_DEVICE_GIGE_INFO)SciCam.ByteToStruct(device.info.gigeInfo, typeof(SciCam.SCI_DEVICE_GIGE_INFO));
  268. uint ip1 = gigeDevInfo.ip;
  269. int nIp1 = (int)(ip1 & 0x000000ff);
  270. int nIp2 = (int)((ip1 & 0x0000ff00) >> 8);
  271. int nIp3 = (int)((ip1 & 0x00ff0000) >> 16);
  272. int nIp4 = (int)((ip1 & 0xff000000) >> 24);
  273. string ip = string.Format("{0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
  274. if (IsFindByIp)
  275. {
  276. if (CameraIp == ip)
  277. {
  278. ManufacturerName = gigeDevInfo.manufactureName;
  279. ModelName = gigeDevInfo.modelName;
  280. SerialNumber = gigeDevInfo.serialNumber;
  281. CameraType = CameraType.GIGE;
  282. CameraInfo = device;
  283. IsHaveCamera = true;
  284. break;
  285. }
  286. }
  287. else
  288. {
  289. if (string.Equals(gigeDevInfo.serialNumber, SerialNumber))
  290. {
  291. ManufacturerName = gigeDevInfo.manufactureName;
  292. ModelName = gigeDevInfo.modelName;
  293. SerialNumber = gigeDevInfo.serialNumber;
  294. CameraType = CameraType.GIGE;
  295. CameraInfo = device;
  296. IsHaveCamera = true;
  297. break;
  298. }
  299. }
  300. }
  301. }
  302. if (!IsHaveCamera)
  303. {
  304. throw new Exception("没有发现相机");
  305. }
  306. }
  307. SciCam.SCI_DEVICE_INFO sCI_DEVICE_INFO = CameraInfo;
  308. nReVal = mvCameraAcq.CreateDevice(ref sCI_DEVICE_INFO);
  309. if (nReVal != SciCam.SCI_CAMERA_OK)
  310. {
  311. Console.WriteLine("Creat Device Fail! nRet:{0}", nReVal);
  312. throw new Exception("Creat Device Fail!");
  313. }
  314. // ch:打开设备 | en:Open device
  315. nReVal = mvCameraAcq.OpenDevice();
  316. // ch:设置触发模式为off | en:Set trigger mode as off
  317. nReVal = mvCameraAcq.SetEnumValueByStringEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, "TriggerMode", "On");
  318. nReVal = mvCameraAcq.SetEnumValueByString("TriggerSource", "Software");
  319. // ch:注册事件回调 | en:Register event callback
  320. //nReVal = mvCameraAcq.RegisterPayloadCallBack(new SciCam.fnOnPayloadDelegate(ImageCallBack), IntPtr.Zero, true);
  321. // ch:设置采集策略 | en:Set Grab Strategy
  322. nReVal = mvCameraAcq.SetGrabStrategy(CurrentGrabStrategy);
  323. if (nReVal != SciCam.SCI_CAMERA_OK)
  324. {
  325. Console.WriteLine("Register Event CallBack fail! nRet {0}", nReVal);
  326. }
  327. if (!IsConnected)
  328. {
  329. CameraConnectChangedEvent?.Invoke(ID, true);
  330. }
  331. mvCameraAcq.SetGrabTimeout(5000);
  332. IsConnected = mvCameraAcq.IsDeviceOpen();
  333. if (IsConnected)
  334. {
  335. mvCameraAcq.StartGrabbing();
  336. }
  337. return IsConnected;
  338. }
  339. finally
  340. {
  341. //_operationSemaphore.Release();
  342. }
  343. }
  344. /// <summary>
  345. /// 打开相机异步
  346. /// </summary>
  347. /// <returns></returns>
  348. public Task<bool> OpenDeviceAsync()
  349. {
  350. return Task.Run(() =>
  351. {
  352. return OpenDevice();
  353. });
  354. }
  355. /// <summary>
  356. /// 关闭相机
  357. /// </summary>
  358. public void CloseDevice()
  359. {
  360. // ch:关闭设备 | en:Close Device
  361. //_operationSemaphore.Wait();
  362. try
  363. {
  364. mvCameraAcq?.StopGrabbing();
  365. mvCameraAcq?.CloseDevice();
  366. mvCameraAcq?.DeleteDevice();
  367. }
  368. finally
  369. {
  370. //_operationSemaphore.Release();
  371. }
  372. }
  373. /// <summary>
  374. /// 采集单张图片
  375. /// </summary>
  376. /// <param name="lastImageOnly">true:采集一张新图像,false:返回最后一张图像</param>
  377. /// <returns></returns>
  378. public ICogImage Grab(bool lastImageOnly = true)
  379. {
  380. //_operationSemaphore.Wait();
  381. uint nReVal = SciCam.SCI_CAMERA_OK;
  382. IntPtr payload = IntPtr.Zero;
  383. try
  384. {
  385. Stopwatch sw = Stopwatch.StartNew();
  386. for (int i = 0; i < 5; i++)
  387. {
  388. try
  389. {
  390. if (!mvCameraAcq.IsDeviceOpen())
  391. {
  392. OpenDevice();
  393. }
  394. // 重置TaskCompletionSource
  395. //_tcs?.TrySetCanceled();
  396. //_tcs = new TaskCompletionSource<ICogImage>();
  397. // 注册取消令牌
  398. //CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(2000000); // 2秒超时
  399. //cancellationTokenSource.Token.Register(() => _tcs.TrySetCanceled());
  400. // 触发图像采集
  401. // ch:发送软触发命令 | en:Send Trigger Software command
  402. nReVal = mvCameraAcq.SetCommandValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, "TriggerSoftware");
  403. if (nReVal == SciCam.SCI_CAMERA_OK)
  404. {
  405. nReVal = mvCameraAcq.Grab(ref payload);
  406. if (nReVal == SciCam.SCI_CAMERA_OK)
  407. {
  408. Image = GetConvertedInfo(payload);
  409. mvCameraAcq.FreePayload(payload);
  410. //nReVal = mvCameraAcq.StopGrabbing();
  411. TotalTime = sw.Elapsed;
  412. ErrorMessage = $"{i + 1}";
  413. return Image;
  414. }
  415. else
  416. {
  417. //nReVal = mvCameraAcq.FreePayload(payload);
  418. //nReVal = mvCameraAcq.StopGrabbing();
  419. //_operationSemaphore.Release();
  420. CloseDevice();
  421. OpenDevice();
  422. ErrorMessage = "图像采集失败!";
  423. }
  424. }
  425. else
  426. {
  427. //nReVal = mvCameraAcq.FreePayload(payload);
  428. //nReVal = mvCameraAcq.StopGrabbing();
  429. //_operationSemaphore.Release();
  430. CloseDevice();
  431. OpenDevice();
  432. ErrorMessage = "软触发失败!";
  433. }
  434. }
  435. catch (Exception ex)
  436. {
  437. //_operationSemaphore.Release();
  438. CloseDevice();
  439. OpenDevice();
  440. ErrorMessage = ex.Message;
  441. }
  442. }
  443. if (IsConnected)
  444. {
  445. IsConnected = false;
  446. CameraConnectChangedEvent?.Invoke(ID, false);
  447. }
  448. return null;
  449. }
  450. finally
  451. {
  452. //_operationSemaphore.Release();
  453. }
  454. }
  455. // ch:采集回调接口 | en:Grab Callback interface
  456. void ImageCallBack(IntPtr payload, IntPtr tag)
  457. {
  458. try
  459. {
  460. if (payload == IntPtr.Zero) return;
  461. uint nReVal = SciCam.SCI_CAMERA_OK;
  462. SciCam.SCI_CAM_PAYLOAD_ATTRIBUTE attribute = new SciCam.SCI_CAM_PAYLOAD_ATTRIBUTE();
  463. nReVal = SciCam.PayloadGetAttribute(payload, ref attribute);
  464. if (nReVal != SciCam.SCI_CAMERA_OK || !attribute.isComplete)
  465. {
  466. Console.WriteLine("Failed to get image attributes or frame is incomplete! nRet:{0}", nReVal);
  467. _tcs?.TrySetException(new Exception($"Failed to get image attributes or frame is incomplete! nRet: {nReVal}"));
  468. }
  469. else
  470. {
  471. Image = GetConvertedInfo(payload);
  472. //ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  473. //Console.WriteLine("Get One Frame: Width[{0}], Height[{1}], nFrameNum[{2}]",
  474. //attribute.imgAttr.width, attribute.imgAttr.height, attribute.frameID);
  475. // 收到图像时完成任务
  476. _tcs?.TrySetResult(Image);
  477. }
  478. }
  479. catch (Exception ex)
  480. {
  481. _tcs?.TrySetException(new Exception($"相机采集错误: {ex.Message}"));
  482. }
  483. }
  484. /// <summary>
  485. /// 开始采集图像
  486. /// </summary>
  487. public void StartGrabbing()
  488. {
  489. lock (_stateLock)
  490. {
  491. if (IsGrabbing)
  492. return;
  493. IsGrabbing = true;
  494. }
  495. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  496. m_hReceiveThread.Start();
  497. }
  498. /// <summary>
  499. /// 停止采集图像
  500. /// </summary>
  501. public void StopGrabbing()
  502. {
  503. try
  504. {
  505. lock (_stateLock)
  506. {
  507. IsGrabbing = false;
  508. }
  509. if (m_hReceiveThread != null)
  510. {
  511. m_hReceiveThread.Abort();
  512. m_hReceiveThread = null;
  513. }
  514. }
  515. catch (Exception)
  516. {
  517. }
  518. }
  519. /// <summary>
  520. /// 设置曝光时间
  521. /// </summary>
  522. /// <param name="ExposureTime"></param>
  523. /// <returns></returns>
  524. public bool SetExposureTime(float ExposureTime)
  525. {
  526. try
  527. {
  528. if (!mvCameraAcq.IsDeviceOpen())
  529. return false;
  530. string[] nodeName = new string[]{
  531. "ExposureTime",
  532. "ExposureTimeAbs",
  533. "ExposureTimeRaw"};
  534. uint nReVal = SciCam.SCI_CAMERA_OK;
  535. for (int i = 0; i < nodeName.Count(); i++)
  536. {
  537. nReVal = mvCameraAcq.SetIntValue(nodeName[i], (int)ExposureTime);
  538. if (nReVal != SciCam.SCI_CAMERA_OK)
  539. {
  540. nReVal = mvCameraAcq.SetFloatValue(nodeName[i], ExposureTime);
  541. if (nReVal == SciCam.SCI_CAMERA_OK)
  542. {
  543. break;
  544. }
  545. }
  546. else
  547. {
  548. break;
  549. }
  550. }
  551. if (nReVal != SciCam.SCI_CAMERA_OK)
  552. {
  553. return false;
  554. }
  555. return true;
  556. }
  557. finally
  558. {
  559. //_operationSemaphore.Release();
  560. }
  561. }
  562. /// <summary>
  563. /// 获取曝光时间
  564. /// </summary>
  565. /// <returns></returns>
  566. public float GetExposureTime()
  567. {
  568. //_operationSemaphore.Wait();
  569. try
  570. {
  571. if (!mvCameraAcq.IsDeviceOpen())
  572. return 0;
  573. uint nReVal = SciCam.SCI_CAMERA_OK;
  574. string[] nodeName = new string[]
  575. {
  576. "ExposureTime",
  577. "ExposureTimeAbs",
  578. "ExposureTimeRaw"
  579. };
  580. for (int i = 0; i < nodeName.Count(); i++)
  581. {
  582. SciCam.SCI_NODE_VAL_INT iNodeVal = new SciCam.SCI_NODE_VAL_INT();
  583. nReVal = mvCameraAcq.GetIntValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], ref iNodeVal);
  584. if (nReVal != SciCam.SCI_CAMERA_OK)
  585. {
  586. SciCam.SCI_NODE_VAL_FLOAT fNodeVal = new SciCam.SCI_NODE_VAL_FLOAT();
  587. nReVal = mvCameraAcq.GetFloatValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], ref fNodeVal);
  588. if (nReVal == SciCam.SCI_CAMERA_OK)
  589. {
  590. return Convert.ToSingle(fNodeVal.dVal);
  591. }
  592. }
  593. else
  594. {
  595. return Convert.ToSingle(iNodeVal.nVal);
  596. }
  597. }
  598. return 0;
  599. }
  600. finally
  601. {
  602. //_operationSemaphore.Release();
  603. }
  604. }
  605. /// <summary>
  606. /// 设置增益
  607. /// </summary>
  608. /// <param name="Gain"></param>
  609. /// <returns></returns>
  610. public bool SetGain(float Gain)
  611. {
  612. //_operationSemaphore.Wait();
  613. try
  614. {
  615. if (!mvCameraAcq.IsDeviceOpen())
  616. return false;
  617. uint nReVal = SciCam.SCI_CAMERA_OK;
  618. string[] nodeName = new string[]
  619. {
  620. "Gain",
  621. "GainRaw"
  622. };
  623. for (int i = 0; i < nodeName.Count(); i++)
  624. {
  625. nReVal = mvCameraAcq.SetIntValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], (int)Gain);
  626. if (nReVal != SciCam.SCI_CAMERA_OK)
  627. {
  628. nReVal = mvCameraAcq.SetFloatValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], Gain);
  629. if (nReVal == SciCam.SCI_CAMERA_OK)
  630. {
  631. return true;
  632. }
  633. }
  634. else
  635. {
  636. return true;
  637. }
  638. }
  639. return false;
  640. }
  641. finally
  642. {
  643. //_operationSemaphore.Release();
  644. }
  645. }
  646. /// <summary>
  647. /// 获取增益
  648. /// </summary>
  649. /// <returns></returns>
  650. public float GetGain()
  651. {
  652. //_operationSemaphore.Wait();
  653. try
  654. {
  655. if (!mvCameraAcq.IsDeviceOpen())
  656. return 0;
  657. uint nReVal = SciCam.SCI_CAMERA_OK;
  658. string[] nodeName = new string[]
  659. {
  660. "Gain",
  661. "GainRaw"
  662. };
  663. for (int i = 0; i < nodeName.Count(); i++)
  664. {
  665. SciCam.SCI_NODE_VAL_INT iNodeVal = new SciCam.SCI_NODE_VAL_INT();
  666. nReVal = mvCameraAcq.GetIntValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], ref iNodeVal);
  667. if (nReVal != SciCam.SCI_CAMERA_OK)
  668. {
  669. SciCam.SCI_NODE_VAL_FLOAT fNodeVal = new SciCam.SCI_NODE_VAL_FLOAT();
  670. nReVal = mvCameraAcq.GetFloatValueEx(SciCam.SciCamDeviceXmlType.SciCam_DeviceXml_Camera, nodeName[i], ref fNodeVal);
  671. if (nReVal == SciCam.SCI_CAMERA_OK)
  672. {
  673. return Convert.ToSingle(fNodeVal.dVal);
  674. }
  675. }
  676. else
  677. {
  678. return Convert.ToSingle(iNodeVal.nVal);
  679. }
  680. }
  681. return 0;
  682. }
  683. finally
  684. {
  685. //_operationSemaphore.Release();
  686. }
  687. }
  688. private void GetStreamThreadProc()
  689. {
  690. while (IsGrabbing)
  691. {
  692. try
  693. {
  694. Grab(false);
  695. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  696. }
  697. catch (Exception)
  698. {
  699. }
  700. Thread.Sleep(10);
  701. }
  702. IsGrabbing = false;
  703. }
  704. private ICogImage GetConvertedInfo(IntPtr payload)
  705. {
  706. if (payload == IntPtr.Zero)
  707. {
  708. return null;
  709. }
  710. SciCam.SCI_CAM_PAYLOAD_ATTRIBUTE payloadAttribute = new SciCam.SCI_CAM_PAYLOAD_ATTRIBUTE();
  711. uint nReVal = SciCam.PayloadGetAttribute(payload, ref payloadAttribute);
  712. if (nReVal != SciCam.SCI_CAMERA_OK)
  713. {
  714. return null;
  715. }
  716. bool imgIsComplete = payloadAttribute.isComplete;
  717. SciCam.SciCamPayloadMode payloadMode = payloadAttribute.payloadMode;
  718. SciCam.SciCamPixelType imgPixelType = payloadAttribute.imgAttr.pixelType;
  719. ulong imgWidth = payloadAttribute.imgAttr.width;
  720. ulong imgHeight = payloadAttribute.imgAttr.height;
  721. ulong framID = payloadAttribute.frameID;
  722. if (!imgIsComplete || payloadMode != SciCam.SciCamPayloadMode.SciCam_PayloadMode_2D)
  723. {
  724. return null;
  725. }
  726. IntPtr imgData = IntPtr.Zero;
  727. nReVal = SciCam.PayloadGetImage(payload, ref imgData);
  728. if (nReVal != SciCam.SCI_CAMERA_OK)
  729. {
  730. return null;
  731. }
  732. long destImgSize = 0;
  733. if (imgPixelType == SciCam.SciCamPixelType.Mono1p ||
  734. imgPixelType == SciCam.SciCamPixelType.Mono2p ||
  735. imgPixelType == SciCam.SciCamPixelType.Mono4p ||
  736. imgPixelType == SciCam.SciCamPixelType.Mono8s ||
  737. imgPixelType == SciCam.SciCamPixelType.Mono8 ||
  738. imgPixelType == SciCam.SciCamPixelType.Mono10 ||
  739. imgPixelType == SciCam.SciCamPixelType.Mono10p ||
  740. imgPixelType == SciCam.SciCamPixelType.Mono12 ||
  741. imgPixelType == SciCam.SciCamPixelType.Mono12p ||
  742. imgPixelType == SciCam.SciCamPixelType.Mono14 ||
  743. imgPixelType == SciCam.SciCamPixelType.Mono16 ||
  744. imgPixelType == SciCam.SciCamPixelType.Mono10Packed ||
  745. imgPixelType == SciCam.SciCamPixelType.Mono12Packed ||
  746. imgPixelType == SciCam.SciCamPixelType.Mono14p)
  747. {
  748. nReVal = SciCam.PayloadConvertImage(ref payloadAttribute.imgAttr, imgData, SciCam.SciCamPixelType.Mono8, IntPtr.Zero, ref destImgSize, true);
  749. if (nReVal == SciCam.SCI_CAMERA_OK)
  750. {
  751. IntPtr destImg = Marshal.AllocHGlobal((int)destImgSize);
  752. try
  753. {
  754. nReVal = SciCam.PayloadConvertImage(ref payloadAttribute.imgAttr, imgData, SciCam.SciCamPixelType.Mono8, destImg, ref destImgSize, true);
  755. if (nReVal == SciCam.SCI_CAMERA_OK)
  756. {
  757. byte[] bBitmap = new byte[destImgSize];
  758. Marshal.Copy(destImg, bBitmap, 0, (int)destImgSize);
  759. Bitmap bitMap = new Bitmap((int)imgWidth, (int)imgHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
  760. System.Drawing.Imaging.BitmapData bitmapData = bitMap.LockBits(new Rectangle(0, 0, (int)imgWidth, (int)imgHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
  761. Marshal.Copy(bBitmap, 0, bitmapData.Scan0, (int)destImgSize);
  762. bitMap.UnlockBits(bitmapData);
  763. //设置调色板
  764. System.Drawing.Imaging.ColorPalette palette = bitMap.Palette;
  765. for (int i = 0; i < 256; i++)
  766. {
  767. palette.Entries[i] = Color.FromArgb(i, i, i);
  768. }
  769. bitMap.Palette = palette;
  770. //显示图片
  771. return TransformICogImage((uint)imgHeight, (uint)imgWidth, destImg, SciCam.SciCamPixelType.Mono8);
  772. }
  773. }
  774. catch (Exception ex)
  775. {
  776. }
  777. finally
  778. {
  779. Marshal.FreeHGlobal(destImg);
  780. }
  781. }
  782. }
  783. else
  784. {
  785. nReVal = SciCam.PayloadConvertImage(ref payloadAttribute.imgAttr, imgData, SciCam.SciCamPixelType.RGB8, IntPtr.Zero, ref destImgSize, true);
  786. if (nReVal == SciCam.SCI_CAMERA_OK)
  787. {
  788. IntPtr destImg = Marshal.AllocHGlobal((int)destImgSize);
  789. try
  790. {
  791. nReVal = SciCam.PayloadConvertImage(ref payloadAttribute.imgAttr, imgData, SciCam.SciCamPixelType.RGB8, destImg, ref destImgSize, true);
  792. if (nReVal == SciCam.SCI_CAMERA_OK)
  793. {
  794. IntPtr pTemp = IntPtr.Zero;
  795. Byte[] byteArrImageData = new Byte[imgWidth * imgHeight * 3];
  796. unsafe
  797. {
  798. byte* pBufForSaveImage = (byte*)destImg;
  799. UInt32 nSupWidth = ((UInt32)imgWidth + (UInt32)3) & 0xfffffffc;
  800. for (int nRow = 0; nRow < (int)imgHeight; nRow++)
  801. {
  802. for (int col = 0; col < (int)imgWidth; col++)
  803. {
  804. byteArrImageData[nRow * nSupWidth + col] = pBufForSaveImage[nRow * (int)imgWidth * 3 + (3 * col)];
  805. byteArrImageData[(int)imgWidth * (int)imgHeight + nRow * nSupWidth + col] = pBufForSaveImage[nRow * (int)imgWidth * 3 + (3 * col + 1)];
  806. byteArrImageData[(int)imgWidth * (int)imgHeight * 2 + nRow * nSupWidth + col] = pBufForSaveImage[nRow * (int)imgWidth * 3 + (3 * col + 2)];
  807. }
  808. }
  809. pTemp = Marshal.UnsafeAddrOfPinnedArrayElement(byteArrImageData, 0);
  810. }
  811. //显示图片
  812. return TransformICogImage((uint)imgHeight, (uint)imgWidth, pTemp, SciCam.SciCamPixelType.RGB8);
  813. }
  814. }
  815. catch (Exception ex)
  816. {
  817. }
  818. finally
  819. {
  820. Marshal.FreeHGlobal(destImg);
  821. }
  822. }
  823. }
  824. return null;
  825. }
  826. private ICogImage TransformICogImage(UInt32 nHeight, UInt32 nWidth, IntPtr pImageBuf, SciCam.SciCamPixelType enPixelType)
  827. {
  828. try
  829. {
  830. ICogImage image;
  831. if (enPixelType == SciCam.SciCamPixelType.Mono8)
  832. {
  833. CogImage8Root cogImage8Root = new CogImage8Root();
  834. cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null);
  835. CogImage8Grey cogImage8Grey = new CogImage8Grey();
  836. cogImage8Grey.SetRoot(cogImage8Root);
  837. image = cogImage8Grey.ScaleImage((int)nWidth, (int)nHeight);
  838. System.GC.Collect();
  839. return image;
  840. }
  841. else
  842. {
  843. CogImage8Root image0 = new CogImage8Root();
  844. IntPtr ptr0 = new IntPtr(pImageBuf.ToInt64());
  845. image0.Initialize((int)nWidth, (int)nHeight, ptr0, (int)nWidth, null);
  846. CogImage8Root image1 = new CogImage8Root();
  847. IntPtr ptr1 = new IntPtr(pImageBuf.ToInt64() + nWidth * nHeight);
  848. image1.Initialize((int)nWidth, (int)nHeight, ptr1, (int)nWidth, null);
  849. CogImage8Root image2 = new CogImage8Root();
  850. IntPtr ptr2 = new IntPtr(pImageBuf.ToInt64() + nWidth * nHeight * 2);
  851. image2.Initialize((int)nWidth, (int)nHeight, ptr2, (int)nWidth, null);
  852. CogImage24PlanarColor colorImage = new CogImage24PlanarColor();
  853. //colorImage.SetRoots(image0, image1, image2);
  854. colorImage.SetRoots(image2, image1, image0);
  855. image = colorImage.ScaleImage((int)nWidth, (int)nHeight);
  856. System.GC.Collect();
  857. return image;
  858. }
  859. }
  860. catch (System.Exception)
  861. {
  862. return null;
  863. }
  864. }
  865. #endregion
  866. #region 属性通知
  867. /// <summary>
  868. /// Occurs when a property value changes.
  869. /// </summary>
  870. public event PropertyChangedEventHandler PropertyChanged;
  871. /// <summary>
  872. /// Checks if a property already matches a desired value. Sets the property and
  873. /// notifies listeners only when necessary.
  874. /// </summary>
  875. /// <typeparam name="T">Type of the property.</typeparam>
  876. /// <param name="storage">Reference to a property with both getter and setter.</param>
  877. /// <param name="value">Desired value for the property.</param>
  878. /// <param name="propertyName">Name of the property used to notify listeners. This
  879. /// value is optional and can be provided automatically when invoked from compilers that
  880. /// support CallerMemberName.</param>
  881. /// <returns>True if the value was changed, false if the existing value matched the
  882. /// desired value.</returns>
  883. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  884. {
  885. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  886. storage = value;
  887. RaisePropertyChanged(propertyName);
  888. return true;
  889. }
  890. /// <summary>
  891. /// Checks if a property already matches a desired value. Sets the property and
  892. /// notifies listeners only when necessary.
  893. /// </summary>
  894. /// <typeparam name="T">Type of the property.</typeparam>
  895. /// <param name="storage">Reference to a property with both getter and setter.</param>
  896. /// <param name="value">Desired value for the property.</param>
  897. /// <param name="propertyName">Name of the property used to notify listeners. This
  898. /// value is optional and can be provided automatically when invoked from compilers that
  899. /// support CallerMemberName.</param>
  900. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  901. /// <returns>True if the value was changed, false if the existing value matched the
  902. /// desired value.</returns>
  903. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  904. {
  905. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  906. storage = value;
  907. onChanged?.Invoke();
  908. RaisePropertyChanged(propertyName);
  909. return true;
  910. }
  911. /// <summary>
  912. /// Raises this object's PropertyChanged event.
  913. /// </summary>
  914. /// <param name="propertyName">Name of the property used to notify listeners. This
  915. /// value is optional and can be provided automatically when invoked from compilers
  916. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  917. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  918. {
  919. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  920. }
  921. /// <summary>
  922. /// Raises this object's PropertyChanged event.
  923. /// </summary>
  924. /// <param name="args">The PropertyChangedEventArgs</param>
  925. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  926. {
  927. PropertyChanged?.Invoke(this, args);
  928. }
  929. #endregion
  930. }
  931. }