BaslerCamera.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Runtime.CompilerServices;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using TeamAAS_VP.Enums;
  11. using TeamAAS_VP.Interfaces;
  12. using Cognex.VisionPro;
  13. using Basler.Pylon;
  14. using System.IO;
  15. using System.Drawing.Imaging;
  16. using System.Drawing;
  17. using System.Diagnostics;
  18. using ControlzEx.Standard;
  19. using System.Windows.Media.Media3D;
  20. using MvCamCtrl.NET;
  21. using TeamAAS_VP.Models;
  22. using Microsoft.Win32;
  23. //using System.Drawing;
  24. //using System.Drawing.Imaging;
  25. namespace TeamAAS_VP.Core.Cameras
  26. {
  27. public class BaslerCamera : Interfaces.ICamera, INotifyPropertyChanged
  28. {
  29. #region 字段
  30. private Basler.Pylon.Camera m_MyCamera;
  31. private Thread m_hReceiveThread;
  32. UInt32 m_nRowStep = 0;
  33. // The pixel data converter is used for converting grabbed images to a pixel format that can be displayed.
  34. private PixelDataConverter converter = new PixelDataConverter();
  35. #endregion
  36. #region 属性
  37. public CameraBrand CameraBrand { get => CameraBrand.Basler_Pylon; }
  38. public string Name { get; private set; }
  39. public Guid ID { get; private set; }
  40. public string ManufacturerName { get; private set; }
  41. public string ModelName { get; private set; }
  42. public string SerialNumber { get; private set; }
  43. public CameraType CameraType { get; private set; }
  44. public UInt32 ImageWidth { get; private set; }
  45. public UInt32 ImageHeight { get; private set; }
  46. private bool _IsGrabbing;
  47. /// <summary>
  48. /// 正在采集
  49. /// </summary>
  50. public bool IsGrabbing
  51. {
  52. get { return _IsGrabbing; }
  53. private set { SetProperty(ref _IsGrabbing, value); }
  54. }
  55. private ICogImage _Image;
  56. public ICogImage Image
  57. {
  58. get { return _Image; }
  59. private set { SetProperty(ref _Image, value); }
  60. }
  61. public bool IsConnected { get; private set; }
  62. public ICameraInfo CameraInfo { get; private set; }
  63. /// <summary>
  64. /// 采集用时
  65. /// </summary>
  66. public TimeSpan TotalTime { get; private set; }
  67. /// <summary>
  68. /// 错误信息
  69. /// </summary>
  70. public string ErrorMessage { get; private set; }
  71. #endregion
  72. #region 事件
  73. public event Action<ICogImage, TimeSpan, string> ImageCallbackEvent;
  74. public event Action<Guid, bool> CameraConnectChangedEvent;
  75. #endregion
  76. public BaslerCamera(Guid _ID, string _Name, string _SerialNumber)
  77. {
  78. ID = _ID;
  79. Name = _Name;
  80. SerialNumber = _SerialNumber;
  81. List<Basler.Pylon.ICameraInfo> allCameraInfos = Basler.Pylon.CameraFinder.Enumerate();
  82. foreach (ICameraInfo cameraInfo in allCameraInfos)
  83. {
  84. if (cameraInfo[CameraInfoKey.SerialNumber] == SerialNumber)
  85. {
  86. CameraInfo = cameraInfo;
  87. m_MyCamera = new Basler.Pylon.Camera(cameraInfo);
  88. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo];
  89. ModelName = cameraInfo[CameraInfoKey.ModelName];
  90. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber];
  91. if (cameraInfo[CameraInfoKey.DeviceType].ToLower().Contains("gige"))
  92. {
  93. CameraType = CameraType.GIGE;
  94. }
  95. else
  96. {
  97. CameraType = CameraType.USB;
  98. }
  99. m_MyCamera.Parameters[PLCameraInstance.GrabCameraEvents].SetValue(true); // 激活相机事件
  100. m_MyCamera.CameraOpened += Configuration.AcquireContinuous; // 软触发打开
  101. m_MyCamera.CameraOpened += M_MyCamera_CameraOpened;
  102. m_MyCamera.CameraClosed += M_MyCamera_CameraClosed;
  103. //m_MyCamera.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed;
  104. break;
  105. }
  106. }
  107. IsConnected = false;
  108. }
  109. private void StreamGrabber_ImageGrabbed(object sender, ImageGrabbedEventArgs e)
  110. {
  111. Stopwatch sw = Stopwatch.StartNew();
  112. // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
  113. IGrabResult grabResult = e.GrabResult;
  114. using (grabResult)
  115. {
  116. // Image grabbed successfully?
  117. if (grabResult != null && grabResult.GrabSucceeded)
  118. {
  119. ErrorMessage = "";
  120. byte[] pixelData = grabResult.PixelData as byte[];
  121. IntPtr pixelPointer = Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0);
  122. IntPtr pTemp = IntPtr.Zero;
  123. Basler.Pylon.PixelType enDstPixelType = Basler.Pylon.PixelType.Undefined;
  124. UInt32 nSaveImageNeedSize = 0;
  125. if (IsColorPixelFormat(grabResult.PixelTypeValue))
  126. {
  127. Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
  128. // Lock the bits of the bitmap.
  129. BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  130. converter.OutputPixelFormat = PixelType.BGRA8packed;
  131. // Place the pointer to the buffer of the bitmap.
  132. IntPtr ptrBmp = bmpData.Scan0;
  133. converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
  134. bitmap.UnlockBits(bmpData);
  135. CogImage24PlanarColor colorImage = new CogImage24PlanarColor(bitmap);
  136. Image = colorImage.ScaleImage((int)bitmap.Width, (int)bitmap.Height);
  137. }
  138. else if (IsMonoPixelFormat(grabResult.PixelTypeValue))
  139. {
  140. enDstPixelType = Basler.Pylon.PixelType.Mono8;
  141. nSaveImageNeedSize = (uint)grabResult.Width * (uint)grabResult.Height * 3;
  142. if (grabResult.PixelTypeValue == Basler.Pylon.PixelType.Mono8)
  143. {
  144. pTemp = pixelPointer;
  145. }
  146. else
  147. {
  148. // 其他格式Mono转为Mono8
  149. Basler.Pylon.PixelDataConverter converter = new PixelDataConverter();
  150. converter.OutputPixelFormat = Basler.Pylon.PixelType.RGB8packed;
  151. converter.Convert(pTemp, nSaveImageNeedSize, grabResult);
  152. }
  153. Image = ConvertToICogImage((uint)grabResult.Height, (uint)grabResult.Width, pTemp, enDstPixelType);
  154. }
  155. TotalTime = sw.Elapsed;
  156. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  157. }
  158. else
  159. {
  160. TotalTime = sw.Elapsed;
  161. ErrorMessage = grabResult.ErrorDescription;
  162. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  163. }
  164. }
  165. }
  166. #region 方法
  167. /// <summary>
  168. /// 获取设备
  169. /// </summary>
  170. /// <returns></returns>
  171. public static CameraInfo[] GetDevices()
  172. {
  173. List<CameraInfo> cameras = new List<CameraInfo>();
  174. try
  175. {
  176. if (!CheckSoftwareInstalled().isInstalled)
  177. {
  178. LogHelper.WriteLogInfo("未安装pylon 7");
  179. return cameras.ToArray();
  180. }
  181. List<Basler.Pylon.ICameraInfo> allCameraInfos = Basler.Pylon.CameraFinder.Enumerate();
  182. foreach (ICameraInfo cameraInfo in allCameraInfos)
  183. {
  184. if (cameraInfo[CameraInfoKey.DeviceType].ToLower().Contains("gige"))
  185. {
  186. cameras.Add(new Models.CameraInfo()
  187. {
  188. CameraName = "",
  189. CameraBrand = CameraBrand.Basler_Pylon,
  190. CameraType = CameraType.GIGE,
  191. Id = Guid.NewGuid(),
  192. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo],
  193. Model = cameraInfo[CameraInfoKey.ModelName],
  194. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber],
  195. CameraIp = "",
  196. });
  197. }
  198. else if (cameraInfo[CameraInfoKey.DeviceType].ToLower().Contains("usb"))
  199. {
  200. cameras.Add(new Models.CameraInfo()
  201. {
  202. CameraName = "",
  203. CameraBrand = CameraBrand.Basler_Pylon,
  204. CameraType = CameraType.USB,
  205. Id = Guid.NewGuid(),
  206. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo],
  207. Model = cameraInfo[CameraInfoKey.ModelName],
  208. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber],
  209. CameraIp = "",
  210. });
  211. }
  212. else if (cameraInfo[CameraInfoKey.DeviceType].ToLower().Contains("link"))
  213. {
  214. cameras.Add(new Models.CameraInfo()
  215. {
  216. CameraName = "",
  217. CameraBrand = CameraBrand.Basler_Pylon,
  218. CameraType = CameraType.Link,
  219. Id = Guid.NewGuid(),
  220. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo],
  221. Model = cameraInfo[CameraInfoKey.ModelName],
  222. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber],
  223. CameraIp = "",
  224. });
  225. }
  226. else
  227. {
  228. cameras.Add(new Models.CameraInfo()
  229. {
  230. CameraName = "",
  231. CameraBrand = CameraBrand.Basler_Pylon,
  232. CameraType = CameraType.Unknown,
  233. Id = Guid.NewGuid(),
  234. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo],
  235. Model = cameraInfo[CameraInfoKey.ModelName],
  236. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber],
  237. CameraIp = "",
  238. });
  239. }
  240. }
  241. }
  242. catch (Exception ex)
  243. {
  244. LogHelper.WriteLogError("搜索巴斯勒相机列表时出错!", ex);
  245. }
  246. return cameras.ToArray();
  247. }
  248. /// <summary>
  249. /// 检查相机软件是否安装
  250. /// </summary>
  251. /// <returns></returns>
  252. public static (bool isInstalled, string version) CheckSoftwareInstalled()
  253. {
  254. string softwareName = "pylon 7 Camera Software";
  255. string softwareVersion = "7.5.0.15658";
  256. string[] registryPaths = new[]
  257. {
  258. @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
  259. @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  260. };
  261. foreach (var path in registryPaths)
  262. {
  263. using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))
  264. {
  265. if (key == null) continue;
  266. foreach (string subKeyName in key.GetSubKeyNames())
  267. {
  268. using (RegistryKey subKey = key.OpenSubKey(subKeyName))
  269. {
  270. string displayName = subKey.GetValue("DisplayName")?.ToString();
  271. if (displayName != null && displayName.Contains(softwareName))
  272. {
  273. string version = subKey.GetValue("DisplayVersion")?.ToString();
  274. Version v1 = new Version(version);
  275. Version v2 = new Version(softwareVersion);
  276. if (v1 >= v2)
  277. {
  278. return (true, version);
  279. }
  280. else
  281. {
  282. return (false, version);
  283. }
  284. }
  285. }
  286. }
  287. }
  288. }
  289. return (false, "");
  290. }
  291. /// <summary>
  292. /// 打开相机
  293. /// </summary>
  294. /// <returns></returns>
  295. /// <exception cref="Exception"></exception>
  296. public bool OpenDevice()
  297. {
  298. if (m_MyCamera == null)
  299. {
  300. List<Basler.Pylon.ICameraInfo> allCameraInfos = Basler.Pylon.CameraFinder.Enumerate();
  301. foreach (ICameraInfo cameraInfo in allCameraInfos)
  302. {
  303. if (cameraInfo[CameraInfoKey.SerialNumber] == SerialNumber)
  304. {
  305. CameraInfo = cameraInfo;
  306. m_MyCamera = new Basler.Pylon.Camera(CameraInfo);
  307. ManufacturerName = cameraInfo[CameraInfoKey.ManufacturerInfo];
  308. ModelName = cameraInfo[CameraInfoKey.ModelName];
  309. SerialNumber = cameraInfo[CameraInfoKey.SerialNumber];
  310. if (cameraInfo[CameraInfoKey.DeviceType].ToLower().Contains("gige"))
  311. {
  312. CameraType = CameraType.GIGE;
  313. }
  314. else
  315. {
  316. CameraType = CameraType.USB;
  317. }
  318. m_MyCamera.Parameters[PLCameraInstance.GrabCameraEvents].SetValue(true); // 激活相机事件
  319. m_MyCamera.CameraOpened += M_MyCamera_CameraOpened;
  320. m_MyCamera.CameraClosed += M_MyCamera_CameraClosed;
  321. m_MyCamera.CameraOpened += Configuration.AcquireContinuous; // 软触发打开
  322. break;
  323. }
  324. }
  325. if (m_MyCamera == null)
  326. {
  327. throw new Exception("没有识别到相机");
  328. }
  329. }
  330. if (!m_MyCamera.IsOpen)
  331. {
  332. m_MyCamera.Open();
  333. m_MyCamera.Parameters[PLCamera.TriggerSource].SetValue(PLCamera.TriggerSource.Software);
  334. m_MyCamera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
  335. m_MyCamera.Parameters[PLCamera.TriggerMode].SetValue(PLCamera.TriggerMode.On);
  336. }
  337. IsConnected = m_MyCamera.IsConnected;
  338. return IsConnected;
  339. }
  340. private void M_MyCamera_CameraClosed(object sender, EventArgs e)
  341. {
  342. CameraConnectChangedEvent?.Invoke(ID, false);
  343. }
  344. private void M_MyCamera_CameraOpened(object sender, EventArgs e)
  345. {
  346. CameraConnectChangedEvent?.Invoke(ID, true);
  347. }
  348. /// <summary>
  349. /// 关闭相机
  350. /// </summary>
  351. public void CloseDevice()
  352. {
  353. if (m_MyCamera != null)
  354. {
  355. if (m_MyCamera.IsOpen)
  356. {
  357. m_MyCamera.Close();
  358. m_MyCamera.CameraOpened -= Configuration.AcquireContinuous; // 软触发打开
  359. m_MyCamera.CameraOpened -= M_MyCamera_CameraOpened;
  360. m_MyCamera.CameraClosed -= M_MyCamera_CameraClosed;
  361. IsConnected = m_MyCamera.IsConnected;
  362. m_MyCamera.Dispose();
  363. }
  364. }
  365. }
  366. /// <summary>
  367. /// 采集图像
  368. /// </summary>
  369. /// <returns></returns>
  370. public ICogImage Grab()
  371. {
  372. Stopwatch sw = Stopwatch.StartNew();
  373. if (m_MyCamera == null)
  374. {
  375. throw new Exception("相机未连接");
  376. }
  377. if (!m_MyCamera.IsOpen)
  378. {
  379. m_MyCamera.Open();
  380. m_MyCamera.Parameters[PLCamera.TriggerSource].SetValue(PLCamera.TriggerSource.Software);
  381. m_MyCamera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
  382. m_MyCamera.Parameters[PLCamera.TriggerMode].SetValue(PLCamera.TriggerMode.On);
  383. }
  384. if (!m_MyCamera.StreamGrabber.IsGrabbing)
  385. {
  386. // Start grabbing.
  387. m_MyCamera.StreamGrabber.Start();
  388. }
  389. bool Succeed = false;
  390. IGrabResult grabResult = null;
  391. for (int i = 0; i < 5; i++)
  392. {
  393. try
  394. {
  395. m_MyCamera.ExecuteSoftwareTrigger();
  396. // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
  397. grabResult = m_MyCamera.StreamGrabber.RetrieveResult(1000, TimeoutHandling.ThrowException);
  398. if (grabResult != null && grabResult.GrabSucceeded)
  399. {
  400. ErrorMessage = "";
  401. Succeed = true;
  402. break;
  403. }
  404. else
  405. {
  406. ErrorMessage = grabResult.ErrorDescription;
  407. }
  408. }
  409. catch (Exception ex)
  410. {
  411. ErrorMessage = ex.Message;
  412. m_MyCamera.Close();
  413. m_MyCamera.CameraOpened -= M_MyCamera_CameraOpened;
  414. m_MyCamera.CameraClosed -= M_MyCamera_CameraClosed;
  415. m_MyCamera.Open();
  416. m_MyCamera.Parameters[PLCamera.TriggerSource].SetValue(PLCamera.TriggerSource.Software);
  417. m_MyCamera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
  418. m_MyCamera.Parameters[PLCamera.TriggerMode].SetValue(PLCamera.TriggerMode.On);
  419. IsConnected = m_MyCamera.IsConnected;
  420. }
  421. finally
  422. {
  423. //m_MyCamera.StreamGrabber.Stop();
  424. }
  425. }
  426. if (!Succeed)
  427. {
  428. if (IsConnected)
  429. {
  430. IsConnected = false;
  431. CameraConnectChangedEvent?.Invoke(ID, false);
  432. }
  433. return null;
  434. }
  435. //m_MyCamera.StreamGrabber.Stop();
  436. if (IsColorPixelFormat(grabResult.PixelTypeValue))
  437. {
  438. Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
  439. // Lock the bits of the bitmap.
  440. BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  441. converter.OutputPixelFormat = PixelType.BGRA8packed;
  442. // Place the pointer to the buffer of the bitmap.
  443. IntPtr ptrBmp = bmpData.Scan0;
  444. converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
  445. bitmap.UnlockBits(bmpData);
  446. CogImage24PlanarColor colorImage = new CogImage24PlanarColor(bitmap);
  447. Image = colorImage.ScaleImage((int)bitmap.Width, (int)bitmap.Height);
  448. }
  449. else if (IsMonoPixelFormat(grabResult.PixelTypeValue))
  450. {
  451. byte[] pixelData = grabResult.PixelData as byte[];
  452. IntPtr pixelPointer = Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0);
  453. IntPtr pTemp = IntPtr.Zero;
  454. Basler.Pylon.PixelType enDstPixelType = Basler.Pylon.PixelType.Undefined;
  455. UInt32 nSaveImageNeedSize = 0;
  456. enDstPixelType = Basler.Pylon.PixelType.Mono8;
  457. nSaveImageNeedSize = (uint)grabResult.Width * (uint)grabResult.Height * 3;
  458. if (grabResult.PixelTypeValue == Basler.Pylon.PixelType.Mono8)
  459. {
  460. pTemp = pixelPointer;
  461. }
  462. else
  463. {
  464. // 其他格式Mono转为Mono8
  465. Basler.Pylon.PixelDataConverter converter = new PixelDataConverter();
  466. converter.OutputPixelFormat = Basler.Pylon.PixelType.RGB8packed;
  467. converter.Convert(pTemp, nSaveImageNeedSize, grabResult);
  468. }
  469. Image = ConvertToICogImage((uint)grabResult.Height, (uint)grabResult.Width, pTemp, enDstPixelType);
  470. }
  471. GC.Collect();
  472. grabResult.Dispose();
  473. TotalTime = sw.Elapsed;
  474. return Image;
  475. }
  476. private void InvertColors(IGrabResult result)
  477. {
  478. byte pixelSize = 255;
  479. byte[] data = (byte[])result.PixelData;
  480. for (long i = 0; i < data.Length; i++)
  481. {
  482. data[i] = (byte)((int)pixelSize - (int)data[i]);
  483. }
  484. }
  485. /// <summary>
  486. /// 转换成ICogImage图像
  487. /// </summary>
  488. /// <param name="nHeight"></param>
  489. /// <param name="nWidth"></param>
  490. /// <param name="pImageBuf"></param>
  491. /// <param name="enPixelType"></param>
  492. /// <returns></returns>
  493. public ICogImage ConvertToICogImage(UInt32 nHeight, UInt32 nWidth, IntPtr pImageBuf, Basler.Pylon.PixelType enPixelType)
  494. {
  495. // ch: 显示 || display
  496. try
  497. {
  498. if (enPixelType == Basler.Pylon.PixelType.Mono8)
  499. {
  500. CogImage8Root cogImage8Root = new CogImage8Root();
  501. cogImage8Root.Initialize((Int32)nWidth, (Int32)nHeight, pImageBuf, (Int32)nWidth, null);
  502. CogImage8Grey cogImage8Grey = new CogImage8Grey();
  503. cogImage8Grey.SetRoot(cogImage8Root);
  504. return cogImage8Grey.ScaleImage((int)nWidth, (int)nHeight);
  505. }
  506. else
  507. {
  508. CogImage8Root image0 = new CogImage8Root();
  509. IntPtr ptr0 = new IntPtr(pImageBuf.ToInt64());
  510. image0.Initialize((int)nWidth, (int)nHeight, ptr0, (int)nWidth, null);
  511. CogImage8Root image1 = new CogImage8Root();
  512. IntPtr ptr1 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep);
  513. image1.Initialize((int)nWidth, (int)nHeight, ptr1, (int)nWidth, null);
  514. CogImage8Root image2 = new CogImage8Root();
  515. IntPtr ptr2 = new IntPtr(pImageBuf.ToInt64() + m_nRowStep * 2);
  516. image2.Initialize((int)nWidth, (int)nHeight, ptr2, (int)nWidth, null);
  517. CogImage24PlanarColor colorImage = new CogImage24PlanarColor();
  518. colorImage.SetRoots(image0, image1, image2);
  519. return colorImage.ScaleImage((int)nWidth, (int)nHeight);
  520. }
  521. }
  522. catch (System.Exception)
  523. {
  524. return null;
  525. }
  526. }
  527. /// <summary>
  528. /// 开始采集图像
  529. /// </summary>
  530. public void StartGrabbing()
  531. {
  532. if (m_MyCamera == null)
  533. {
  534. throw new Exception("相机未连接");
  535. }
  536. if (!m_MyCamera.IsOpen)
  537. {
  538. throw new Exception("相机未打开");
  539. }
  540. m_MyCamera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous);
  541. //m_MyCamera.StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);
  542. if (IsGrabbing)
  543. return;
  544. if (!m_MyCamera.StreamGrabber.IsGrabbing)
  545. {
  546. // Start grabbing.
  547. m_MyCamera.StreamGrabber.Start();
  548. }
  549. IsGrabbing = true;
  550. m_hReceiveThread = new Thread(GetStreamThreadProc) { IsBackground = true };
  551. m_hReceiveThread.Start();
  552. }
  553. /// <summary>
  554. /// 停止采集图像
  555. /// </summary>
  556. public void StopGrabbing()
  557. {
  558. try
  559. {
  560. //m_MyCamera.StreamGrabber.Stop();
  561. IsGrabbing = false;
  562. Thread.Sleep(1000);
  563. if (m_hReceiveThread != null)
  564. {
  565. m_hReceiveThread.Abort();
  566. m_hReceiveThread = null;
  567. }
  568. if (m_MyCamera != null && m_MyCamera.StreamGrabber.IsGrabbing)
  569. {
  570. m_MyCamera.StreamGrabber.Stop();
  571. }
  572. }
  573. catch (Exception)
  574. {
  575. }
  576. }
  577. /// <summary>
  578. /// 设置曝光时间
  579. /// </summary>
  580. /// <param name="ExposureTime"></param>
  581. /// <returns></returns>
  582. public bool SetExposureTime(float ExposureTime)
  583. {
  584. if (m_MyCamera == null)
  585. {
  586. return false;
  587. }
  588. if (m_MyCamera.Parameters.Contains(PLCamera.ExposureTimeAbs))
  589. {
  590. m_MyCamera.Parameters[PLCamera.ExposureTimeAbs].SetValue(ExposureTime);
  591. }
  592. else
  593. m_MyCamera.Parameters[PLCamera.ExposureTime].SetValue(ExposureTime);
  594. return true;
  595. }
  596. /// <summary>
  597. /// 获取曝光时间
  598. /// </summary>
  599. /// <returns></returns>
  600. public float GetExposureTime()
  601. {
  602. if (m_MyCamera == null)
  603. {
  604. return 0;
  605. }
  606. if (m_MyCamera.Parameters.Contains(PLCamera.ExposureTimeAbs))
  607. {
  608. return (float)m_MyCamera.Parameters[PLCamera.ExposureTimeAbs].GetValue();
  609. }
  610. else
  611. return (float)m_MyCamera.Parameters[PLCamera.ExposureTime].GetValue();
  612. }
  613. /// <summary>
  614. /// 设置增益
  615. /// </summary>
  616. /// <param name="Gain"></param>
  617. /// <returns></returns>
  618. public bool SetGain(float Gain)
  619. {
  620. if (m_MyCamera == null)
  621. {
  622. return false;
  623. }
  624. if (m_MyCamera.Parameters.Contains(PLCamera.Gain))
  625. {
  626. m_MyCamera.Parameters[PLCamera.Gain].SetValue(Gain);
  627. }
  628. else if (m_MyCamera.Parameters.Contains(PLCamera.GainRaw))
  629. {
  630. m_MyCamera.Parameters[PLCamera.GainRaw].SetValue((int)Gain);
  631. }
  632. else if (m_MyCamera.Parameters.Contains(PLCamera.GainAbs))
  633. {
  634. m_MyCamera.Parameters[PLCamera.GainAbs].SetValue(Gain);
  635. }
  636. return true;
  637. }
  638. /// <summary>
  639. /// 获取增益
  640. /// </summary>
  641. /// <returns></returns>
  642. public float GetGain()
  643. {
  644. if (m_MyCamera.Parameters.Contains(PLCamera.Gain))
  645. {
  646. return (float)m_MyCamera.Parameters[PLCamera.Gain].GetValue();
  647. }
  648. else
  649. return (float)m_MyCamera.Parameters[PLCamera.GainAbs].GetValue();
  650. }
  651. private void GetStreamThreadProc()
  652. {
  653. while (IsGrabbing)
  654. {
  655. Stopwatch sw = Stopwatch.StartNew();
  656. try
  657. {
  658. if (!m_MyCamera.IsConnected)
  659. {
  660. m_MyCamera.Close();
  661. m_MyCamera.CameraOpened -= M_MyCamera_CameraOpened;
  662. m_MyCamera.CameraClosed -= M_MyCamera_CameraClosed;
  663. m_MyCamera = new Basler.Pylon.Camera(CameraInfo);
  664. m_MyCamera.CameraOpened += M_MyCamera_CameraOpened;
  665. m_MyCamera.CameraClosed += M_MyCamera_CameraClosed;
  666. }
  667. if (!m_MyCamera.IsOpen)
  668. {
  669. m_MyCamera.Open();
  670. IsConnected = m_MyCamera.IsConnected;
  671. }
  672. m_MyCamera.ExecuteSoftwareTrigger();
  673. // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
  674. IGrabResult grabResult = m_MyCamera.StreamGrabber.RetrieveResult(1000, TimeoutHandling.ThrowException);
  675. using (grabResult)
  676. {
  677. // Image grabbed successfully?
  678. if (grabResult != null && grabResult.GrabSucceeded)
  679. {
  680. ErrorMessage = "";
  681. byte[] pixelData = grabResult.PixelData as byte[];
  682. IntPtr pixelPointer = Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0);
  683. IntPtr pTemp = IntPtr.Zero;
  684. Basler.Pylon.PixelType enDstPixelType = Basler.Pylon.PixelType.Undefined;
  685. UInt32 nSaveImageNeedSize = 0;
  686. if (IsColorPixelFormat(grabResult.PixelTypeValue))
  687. {
  688. Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
  689. // Lock the bits of the bitmap.
  690. BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  691. converter.OutputPixelFormat = PixelType.BGRA8packed;
  692. // Place the pointer to the buffer of the bitmap.
  693. IntPtr ptrBmp = bmpData.Scan0;
  694. converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
  695. bitmap.UnlockBits(bmpData);
  696. CogImage24PlanarColor colorImage = new CogImage24PlanarColor(bitmap);
  697. Image = colorImage.ScaleImage((int)bitmap.Width, (int)bitmap.Height);
  698. }
  699. else if (IsMonoPixelFormat(grabResult.PixelTypeValue))
  700. {
  701. enDstPixelType = Basler.Pylon.PixelType.Mono8;
  702. nSaveImageNeedSize = (uint)grabResult.Width * (uint)grabResult.Height * 3;
  703. if (grabResult.PixelTypeValue == Basler.Pylon.PixelType.Mono8)
  704. {
  705. pTemp = pixelPointer;
  706. }
  707. else
  708. {
  709. // 其他格式Mono转为Mono8
  710. Basler.Pylon.PixelDataConverter converter = new PixelDataConverter();
  711. converter.OutputPixelFormat = Basler.Pylon.PixelType.RGB8packed;
  712. converter.Convert(pTemp, nSaveImageNeedSize, grabResult);
  713. }
  714. Image = ConvertToICogImage((uint)grabResult.Height, (uint)grabResult.Width, pTemp, enDstPixelType);
  715. }
  716. TotalTime = sw.Elapsed;
  717. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  718. }
  719. else
  720. {
  721. TotalTime = sw.Elapsed;
  722. ErrorMessage = grabResult.ErrorDescription;
  723. ImageCallbackEvent?.Invoke(Image, TotalTime, ErrorMessage);
  724. }
  725. }
  726. }
  727. catch (Exception ex)
  728. {
  729. TotalTime = sw.Elapsed;
  730. ImageCallbackEvent?.Invoke(Image, TotalTime, ex.Message);
  731. }
  732. Thread.Sleep(10);
  733. GC.Collect();
  734. }
  735. IsGrabbing = false;
  736. }
  737. /// <summary>
  738. /// 图像是否为彩色
  739. /// </summary>
  740. /// <param name="enType"></param>
  741. /// <returns></returns>
  742. private bool IsColorPixelFormat(Basler.Pylon.PixelType enType)
  743. {
  744. switch (enType)
  745. {
  746. case Basler.Pylon.PixelType.RGB8packed:
  747. case Basler.Pylon.PixelType.BGR8packed:
  748. case Basler.Pylon.PixelType.RGBA8packed:
  749. case Basler.Pylon.PixelType.BGRA8packed:
  750. case Basler.Pylon.PixelType.YUV422packed:
  751. case Basler.Pylon.PixelType.YUV422_YUYV_Packed:
  752. case Basler.Pylon.PixelType.BayerGR8:
  753. case Basler.Pylon.PixelType.BayerRG8:
  754. case Basler.Pylon.PixelType.BayerGB8:
  755. case Basler.Pylon.PixelType.BayerBG8:
  756. case Basler.Pylon.PixelType.BayerGB10:
  757. case Basler.Pylon.PixelType.BayerGB10pp:
  758. case Basler.Pylon.PixelType.BayerBG10:
  759. case Basler.Pylon.PixelType.BayerBG10pp:
  760. case Basler.Pylon.PixelType.BayerRG10:
  761. case Basler.Pylon.PixelType.BayerRG10pp:
  762. case Basler.Pylon.PixelType.BayerGR10:
  763. case Basler.Pylon.PixelType.BayerGR10pp:
  764. case Basler.Pylon.PixelType.BayerGB12:
  765. case Basler.Pylon.PixelType.BayerGB12p:
  766. case Basler.Pylon.PixelType.BayerBG12:
  767. case Basler.Pylon.PixelType.BayerBG12Packed:
  768. case Basler.Pylon.PixelType.BayerRG12:
  769. case Basler.Pylon.PixelType.BayerRG12Packed:
  770. case Basler.Pylon.PixelType.BayerGR12:
  771. case Basler.Pylon.PixelType.BayerGR12Packed:
  772. return true;
  773. default:
  774. return false;
  775. }
  776. }
  777. /// <summary>
  778. /// 图像是否为Mono格式
  779. /// </summary>
  780. /// <param name="enType"></param>
  781. /// <returns></returns>
  782. private bool IsMonoPixelFormat(Basler.Pylon.PixelType enType)
  783. {
  784. switch (enType)
  785. {
  786. case Basler.Pylon.PixelType.Mono8:
  787. case Basler.Pylon.PixelType.Mono10:
  788. case Basler.Pylon.PixelType.Mono10packed:
  789. case Basler.Pylon.PixelType.Mono12:
  790. case Basler.Pylon.PixelType.Mono12packed:
  791. return true;
  792. default:
  793. return false;
  794. }
  795. }
  796. /// <summary>
  797. /// 将相机抓取到的图像转换成Bitmap位图
  798. /// </summary>
  799. /// <param name="grabResult"></param>
  800. /// <returns></returns>
  801. //Bitmap GrabResult2Bmp(IGrabResult grabResult)
  802. //{
  803. // Bitmap bitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb); // 转bit图
  804. // BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
  805. // PixelDataConverter converter = new PixelDataConverter();
  806. // converter.OutputPixelFormat = PixelType.BGRA8packed;
  807. // IntPtr ptrBmp = bmpData.Scan0;
  808. // converter.Convert(ptrBmp, bmpData.Stride * bitmap.Height, grabResult);
  809. // bitmap.UnlockBits(bmpData);
  810. // return (Bitmap)bitmap.Clone();
  811. //}
  812. #endregion
  813. #region 属性通知
  814. /// <summary>
  815. /// Occurs when a property value changes.
  816. /// </summary>
  817. public event PropertyChangedEventHandler PropertyChanged;
  818. /// <summary>
  819. /// Checks if a property already matches a desired value. Sets the property and
  820. /// notifies listeners only when necessary.
  821. /// </summary>
  822. /// <typeparam name="T">Type of the property.</typeparam>
  823. /// <param name="storage">Reference to a property with both getter and setter.</param>
  824. /// <param name="value">Desired value for the property.</param>
  825. /// <param name="propertyName">Name of the property used to notify listeners. This
  826. /// value is optional and can be provided automatically when invoked from compilers that
  827. /// support CallerMemberName.</param>
  828. /// <returns>True if the value was changed, false if the existing value matched the
  829. /// desired value.</returns>
  830. protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
  831. {
  832. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  833. storage = value;
  834. RaisePropertyChanged(propertyName);
  835. return true;
  836. }
  837. /// <summary>
  838. /// Checks if a property already matches a desired value. Sets the property and
  839. /// notifies listeners only when necessary.
  840. /// </summary>
  841. /// <typeparam name="T">Type of the property.</typeparam>
  842. /// <param name="storage">Reference to a property with both getter and setter.</param>
  843. /// <param name="value">Desired value for the property.</param>
  844. /// <param name="propertyName">Name of the property used to notify listeners. This
  845. /// value is optional and can be provided automatically when invoked from compilers that
  846. /// support CallerMemberName.</param>
  847. /// <param name="onChanged">Action that is called after the property value has been changed.</param>
  848. /// <returns>True if the value was changed, false if the existing value matched the
  849. /// desired value.</returns>
  850. protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
  851. {
  852. if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
  853. storage = value;
  854. onChanged?.Invoke();
  855. RaisePropertyChanged(propertyName);
  856. return true;
  857. }
  858. /// <summary>
  859. /// Raises this object's PropertyChanged event.
  860. /// </summary>
  861. /// <param name="propertyName">Name of the property used to notify listeners. This
  862. /// value is optional and can be provided automatically when invoked from compilers
  863. /// that support <see cref="CallerMemberNameAttribute"/>.</param>
  864. protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  865. {
  866. OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  867. }
  868. /// <summary>
  869. /// Raises this object's PropertyChanged event.
  870. /// </summary>
  871. /// <param name="args">The PropertyChangedEventArgs</param>
  872. protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
  873. {
  874. PropertyChanged?.Invoke(this, args);
  875. }
  876. #endregion
  877. }
  878. }