Management.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. using Cognex.VisionPro;
  2. using Cognex.VisionPro.QuickBuild;
  3. using LampInspectionMachine.Cameralibs;
  4. using LampInspectionMachine.Model;
  5. using MvCamCtrl.NET;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using Prism.Mvvm;
  13. using LampInspectionMachine.Log4xml;
  14. using Cognex.VisionPro.ImageFile;
  15. using System.Drawing;
  16. using System.Windows.Forms;
  17. using System.Web;
  18. using System.ComponentModel;
  19. using System.Windows.Media.Media3D;
  20. using LampInspectionMachine.ViewModels;
  21. using System.Collections.Concurrent;
  22. using System.Threading;
  23. using System.Windows.Controls;
  24. using LampInspectionMachine.Views;
  25. using System.Windows.Media.Imaging;
  26. using System.Windows.Media;
  27. using System.Windows;
  28. using System.Runtime.InteropServices;
  29. using SqlSugar.DistributedSystem.Snowflake;
  30. using System.Windows.Threading;
  31. using System.Windows.Ink;
  32. using System.Data.SqlClient;
  33. using System.Xml.Linq;
  34. using System.Drawing.Imaging;
  35. using System.IO.Packaging;
  36. using Cognex.VisionPro.ToolBlock;
  37. using System.Windows.Markup;
  38. using System.Diagnostics;
  39. using LampInspectionMachine.Cameralibs.HKCamera;
  40. using Newtonsoft.Json.Linq;
  41. using OpenCvSharp.Dnn;
  42. using LampInspectionMachine.Interfaces;
  43. namespace LampInspectionMachine.Core
  44. {
  45. public class Management : BindableBase
  46. {
  47. private bool isConnected = false;
  48. private CogJobManager myJobManager;
  49. private List<CogJob> myJobs = new List<CogJob>();
  50. private List<CogJobIndependent> myIndependentJobs = new List<CogJobIndependent>();
  51. private CameraView cameraView;
  52. private ICogImage image = new CogImage8Grey();
  53. private WriteableBitmap writeable;
  54. public WriteableBitmap Writeable { get => writeable; set { SetProperty(ref writeable, value); } }
  55. public ICogImage Image
  56. {
  57. get => image;
  58. set
  59. {
  60. SetProperty(ref image, value);
  61. }
  62. }
  63. // 使用泛型委托
  64. public event EventHandler<ICogImage> PropertyChanged;
  65. // 或者自定义委托
  66. public delegate void ChangeEventHandler(ICogImage e);
  67. public event ChangeEventHandler OnChange;
  68. public CameraService CameraService { get; set; }
  69. public CogJobManager MyJobManager { get => myJobManager; set => myJobManager = value; }
  70. public List<CogJob> MyJobs { get => myJobs; set => myJobs = value; }
  71. public List<CogJobIndependent> MyIndependentJobs { get => myIndependentJobs; set => myIndependentJobs = value; }
  72. public CogJobManagerEdit MyJobManagerEdit { get => myJobManagerEdit; set => myJobManagerEdit = value; }
  73. /// <summary>
  74. /// 相机列表
  75. /// </summary>
  76. public ObservableCollection<string> CameraList { get => _CameraList; set { SetProperty(ref _CameraList, value); } }
  77. /// <summary>
  78. /// 当前相机配置
  79. /// </summary>
  80. public CameraInfo CurrCamConfig { get => _CurrCamConfig; set { SetProperty(ref _CurrCamConfig, value); } }
  81. /// <summary>
  82. /// 相机配置列表
  83. /// </summary>
  84. public ObservableCollection<CameraInfo> CamConfigs { get => _CamConfigs; set { SetProperty(ref _CamConfigs, value); } }
  85. public bool IsTriggerModel { get => _isTriggerModel; set { SetProperty(ref _isTriggerModel, value); } }
  86. public ICamera MyCamera { get => myCamera; set { SetProperty(ref myCamera, value); } }
  87. /// <summary>
  88. /// 相机对应模板工具
  89. /// </summary>
  90. public List<CogToolBlock> CamTemplateS { get => _CamTemplateS; set => _CamTemplateS = value; }
  91. public event Action<int> ToolBlockSwitched;
  92. /// <summary>
  93. /// 当前选中相机的SN
  94. /// </summary>
  95. public string CurrCameraSn { get => _CurrCameraSn; set { SetProperty(ref _CurrCameraSn, value); } }
  96. private ObservableCollection<CameraInfo> _CamConfigs = new ObservableCollection<CameraInfo>();
  97. private List<CogToolBlock> _CamTemplateS = new List<CogToolBlock>();
  98. private CogToolBlock cogToolBlock1;
  99. private CameraInfo _CurrCamConfig = null;
  100. private ICamera myCamera;
  101. private bool _isTriggerModel = false;
  102. /// <summary>
  103. /// 当前需要显示的工程文件
  104. /// </summary>
  105. private CogJobManagerEdit myJobManagerEdit;
  106. private ObservableCollection<string> _CameraList = new ObservableCollection<string>();
  107. private string _CurrCameraSn = "";
  108. public Stopwatch stopwatch = new Stopwatch();
  109. public Management()
  110. {
  111. }
  112. /// <summary>
  113. /// 获取相机列表
  114. /// </summary>
  115. public void LoadCameraDevice()
  116. {
  117. CameraService = new CameraService();
  118. CameraList = FindLoadCamera();
  119. if (CamConfigs.Count == 0)
  120. {
  121. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam1.vpp" });
  122. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam2.vpp" });
  123. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam3.vpp" });
  124. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam4.vpp" });
  125. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam5.vpp" });
  126. CamConfigs.Add(new CameraInfo() { VppFileName = "Cam6.vpp" });
  127. }
  128. }
  129. public void SaveCameraDevice()
  130. {
  131. }
  132. /// <summary>
  133. /// 初始化模板
  134. /// </summary>
  135. public void InitTemplates(TipService tipService)
  136. {
  137. tipService.ShowMsg("相机模板加载2%");
  138. CogToolBlock cogToolBlock = (CogToolBlock)CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam1.vpp");
  139. CamTemplateS.Add(cogToolBlock);
  140. //tipService.ShowMsg("相机模板加载10%");
  141. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam2.vpp");
  142. //CamTemplateS.Add(cogToolBlock);
  143. //tipService.ShowMsg("相机模板加载26%");
  144. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam3.vpp");
  145. //CamTemplateS.Add(cogToolBlock);
  146. //tipService.ShowMsg("相机模板加载39%");
  147. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam4.vpp");
  148. //CamTemplateS.Add(cogToolBlock);
  149. //tipService.ShowMsg("相机模板加载52%");
  150. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam5.vpp");
  151. //CamTemplateS.Add(cogToolBlock);
  152. //tipService.ShowMsg("相机模板加载65%");
  153. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam6.vpp");
  154. //CamTemplateS.Add(cogToolBlock);
  155. //tipService.ShowMsg("相机模板加载78%");
  156. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam7.vpp");
  157. //CamTemplateS.Add(cogToolBlock);
  158. //tipService.ShowMsg("相机模板加载91%");
  159. //cogToolBlock = ( CogToolBlock ) CogSerializer.LoadObjectFromFile(Environment.CurrentDirectory + "\\Vpp\\Cam8.vpp");
  160. //CamTemplateS.Add(cogToolBlock);
  161. //tipService.ShowMsg("相机模板加载99%");
  162. tipService.Tcolse();
  163. }
  164. /// <summary>
  165. /// 单张采集
  166. /// </summary>
  167. public void SoftTrigger()
  168. {
  169. if (isConnected)
  170. {
  171. MyCamera.StopGrabbing();
  172. LogHelper.Info($"软触发配置写入");
  173. //MyCamera.SetTriggerModeOff();
  174. //CurrCamConfig.TriggerMode = false;
  175. //MyCamera.SetTriggerSoftware();
  176. //if (!MyCamera.CheckImageCallbackEvent(CamCallBack))
  177. // MyCamera.ImageCallbackEvent -= CamCallBack;
  178. //if (MyCamera.CheckImageCallbackEvent(CamVisionProCallBack))
  179. // MyCamera.ImageCallbackEvent += CamVisionProCallBack;
  180. LogHelper.Info($"软触发取图");
  181. MyCamera.Grab();
  182. }
  183. }
  184. /// <summary>
  185. /// 连续采集写入
  186. /// </summary>
  187. public void SoftTrigger__Continue()
  188. {
  189. //MyCamera.SetTriggerModeOff();
  190. //CurrCamConfig.TriggerMode = false;
  191. //MyCamera.SetTriggerSoftware();
  192. //if (MyCamera.CheckImageCallbackEvent(CamCallBack))
  193. // MyCamera.ImageCallbackEvent += CamCallBack;
  194. //if (!MyCamera.CheckImageCallbackEvent(CamVisionProCallBack))
  195. // MyCamera.ImageCallbackEvent -= CamVisionProCallBack;
  196. LogHelper.Info($"连续采集启动");
  197. MyCamera.StartGrabbing();
  198. }
  199. public void SetHardTrigger_CallBack()
  200. {
  201. LogHelper.Info($"硬触发模式 启动");
  202. //MyCamera.SetTriggerModeOn();
  203. //CurrCamConfig.TriggerMode = true;
  204. //MyCamera.SetTriggerSoftware(0);
  205. //if (!MyCamera.CheckImageCallbackEvent(CamCallBack))
  206. // MyCamera.ImageCallbackEvent -= CamCallBack;
  207. //if (MyCamera.CheckImageCallbackEvent(CamVisionProCallBack))
  208. // MyCamera.ImageCallbackEvent += CamVisionProCallBack;
  209. MyCamera.StartGrabbing();
  210. }
  211. /// <summary>
  212. /// 查找相机
  213. /// </summary>
  214. public ObservableCollection<string> FindLoadCamera()
  215. {
  216. var listsn = MvCamera.GetDevices();
  217. if (listsn.Length > 0)
  218. {
  219. ObservableCollection<string> strings = new ObservableCollection<string>();
  220. for (int i = 0; i < listsn.Length; i++)
  221. {
  222. //strings.Add(listsn[i].);
  223. }
  224. return strings;
  225. }
  226. else
  227. {
  228. System.Windows.Forms.MessageBox.Show("未查询到设备!", "提示", MessageBoxButtons.OK);
  229. return null;
  230. }
  231. }
  232. public void InitCamera(string name)
  233. {
  234. // 初始化相机
  235. if (isConnected && myCamera != null)
  236. {
  237. myCamera.CloseDevice();
  238. myCamera = null;
  239. }
  240. Guid guid = new Guid();
  241. CameraService.CreateCamera(guid, new CameraInfo() { SerialNumber = name });
  242. myCamera = CameraService.GetCamera(guid);
  243. bool res = myCamera.OpenDevice();
  244. if (!res)
  245. {
  246. myCamera.CloseDevice();
  247. myCamera = null;
  248. isConnected = false;
  249. }
  250. else
  251. {
  252. isConnected = true;
  253. }
  254. }
  255. public void InitCameras()
  256. {
  257. CameraService = new CameraService();
  258. foreach (var item in CamConfigs)
  259. {
  260. try
  261. {
  262. CameraService.CreateCamera(item.Id, item);
  263. CameraService.GetCamera(item.Id).CameraConnectChangedEvent += Management_CameraConnectChangedEvent;
  264. if (CameraService.GetCamera(item.Id).OpenDevice())
  265. {
  266. }
  267. else
  268. {
  269. }
  270. }
  271. catch (Exception ex)
  272. {
  273. }
  274. }
  275. }
  276. public void CloseCamera()
  277. {
  278. myCamera?.StopGrabbing();
  279. myCamera?.CloseDevice();
  280. myCamera = null;
  281. isConnected = false;
  282. }
  283. /// <summary>
  284. ///图像显示
  285. /// </summary>
  286. /// <param name="img"></param>
  287. private void CamCallBack(ICogImage image, TimeSpan totaltime, string errormessage)
  288. {
  289. try
  290. {
  291. Image = image;
  292. }
  293. finally
  294. {
  295. }
  296. }
  297. /// <summary>
  298. ///图像显示
  299. /// </summary>
  300. /// <param name="img"></param>
  301. private void MainCamCallBack(ICogImage image, TimeSpan totaltime, string errormessage)
  302. {
  303. try
  304. {
  305. Image = image;
  306. }
  307. finally
  308. {
  309. }
  310. }
  311. // 将海康相机帧数据转换为CogImage8Grey灰度图像
  312. public static ICogImage ConvertToCogImage(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo)
  313. {
  314. // 验证像素格式(支持MONO8/RGB8转灰度)
  315. if (pFrameInfo.enPixelType != MvCamCtrl.NET.MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8 &&
  316. pFrameInfo.enPixelType != MvCamCtrl.NET.MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
  317. {
  318. throw new ArgumentException("Unsupported pixel format");
  319. }
  320. // 创建CogImage8Grey对象
  321. CogImage8Grey cogImage = new CogImage8Grey();
  322. int width = (int)pFrameInfo.nWidth;
  323. int height = (int)pFrameInfo.nHeight;
  324. // 分配内存并复制数据
  325. cogImage.Allocate(width, height);
  326. // 获取8位灰度图像像素内存区域
  327. ICogImage8PixelMemory pixelMemory = (cogImage).Get8GreyPixelMemory(
  328. CogImageDataModeConstants.ReadWrite,
  329. 0, 0,
  330. cogImage.Width, cogImage.Height);
  331. IntPtr destPtr = pixelMemory.Scan0; // 获取像素数据指针
  332. // IntPtr destPtr = cogImage.GetPixelData(CogImageDataModeConstants.ReadWrite);
  333. if (pFrameInfo.enPixelType == MvCamCtrl.NET.MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
  334. {
  335. // 直接拷贝MONO8数据
  336. SafeMemoryCopy(destPtr, pData, width * height);
  337. }
  338. else // RGB转灰度
  339. {
  340. byte[] rgbBuffer = new byte[width * height * 3];
  341. Marshal.Copy(pData, rgbBuffer, 0, rgbBuffer.Length);
  342. unsafe
  343. {
  344. byte* pDest = (byte*)destPtr.ToPointer();
  345. for (int i = 0; i < rgbBuffer.Length; i += 3)
  346. {
  347. // RGB转灰度公式:0.299*R + 0.587*G + 0.114*B
  348. *pDest++ = (byte)(0.299 * rgbBuffer[i] +
  349. 0.587 * rgbBuffer[i + 1] +
  350. 0.114 * rgbBuffer[i + 2]);
  351. }
  352. }
  353. }
  354. return cogImage;
  355. }
  356. // 将海康相机帧数据转换为CogImage24PlanarColor彩色图像
  357. public static ICogImage ConvertToColorCogImage(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo)
  358. {
  359. if (pFrameInfo.enPixelType != MvCamCtrl.NET.MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
  360. {
  361. throw new ArgumentException("Only RGB8 format supported for color conversion");
  362. }
  363. CogImage24PlanarColor cogColorImage = new CogImage24PlanarColor();
  364. int width = (int)pFrameInfo.nWidth;
  365. int height = (int)pFrameInfo.nHeight;
  366. // 分配内存
  367. cogColorImage.Allocate(width, height);
  368. // 获取三个颜色平面指针
  369. CogImage8Grey red = cogColorImage.GetPlane(CogImagePlaneConstants.Red);
  370. CogImage8Grey green = cogColorImage.GetPlane(CogImagePlaneConstants.Green);
  371. CogImage8Grey blue = cogColorImage.GetPlane(CogImagePlaneConstants.Blue);
  372. IntPtr redPtr = cogColorImage.GetPlane(CogImagePlaneConstants.Red).Get8GreyPixelMemory(
  373. CogImageDataModeConstants.ReadWrite,
  374. 0, 0,
  375. red.Width, red.Height).Scan0; // 获取像素数据指针
  376. IntPtr greenPtr = cogColorImage.GetPlane(CogImagePlaneConstants.Green).Get8GreyPixelMemory(
  377. CogImageDataModeConstants.ReadWrite,
  378. 0, 0,
  379. red.Width, red.Height).Scan0; ;
  380. IntPtr bluePtr = cogColorImage.GetPlane(CogImagePlaneConstants.Blue).Get8GreyPixelMemory(
  381. CogImageDataModeConstants.ReadWrite,
  382. 0, 0,
  383. red.Width, red.Height).Scan0; ;
  384. // 转换RGB数据到平面格式
  385. byte[] rgbBuffer = new byte[width * height * 3];
  386. Marshal.Copy(pData, rgbBuffer, 0, rgbBuffer.Length);
  387. unsafe
  388. {
  389. byte* pRed = (byte*)redPtr.ToPointer();
  390. byte* pGreen = (byte*)greenPtr.ToPointer();
  391. byte* pBlue = (byte*)bluePtr.ToPointer();
  392. for (int i = 0; i < rgbBuffer.Length; i += 3)
  393. {
  394. *pRed++ = rgbBuffer[i]; // R
  395. *pGreen++ = rgbBuffer[i + 1]; // G
  396. *pBlue++ = rgbBuffer[i + 2]; // B
  397. }
  398. }
  399. return cogColorImage;
  400. }
  401. // 使用示例(在回调函数中调用)
  402. private void ImageCallback(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
  403. {
  404. ICogImage resultImage;
  405. if (pFrameInfo.enPixelType == MvCamCtrl.NET.MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
  406. {
  407. resultImage = ConvertToCogImage(pData, ref pFrameInfo);
  408. }
  409. else
  410. {
  411. resultImage = ConvertToColorCogImage(pData, ref pFrameInfo);
  412. }
  413. Image = resultImage;
  414. }
  415. /// <summary>
  416. /// 视觉处理
  417. /// </summary>
  418. /// <param name="data"></param>
  419. private void CamVisionProCallBack(ICogImage image, TimeSpan totaltime, string errormessage)
  420. {
  421. try
  422. {
  423. cogToolBlock1.Inputs[0].Value = image;
  424. cogToolBlock1.Run();
  425. Image = (ICogImage)cogToolBlock1.Outputs[6].Value;
  426. }
  427. finally
  428. {
  429. }
  430. }
  431. /// <summary>
  432. /// WriteableBitmap转Bitmap图像
  433. /// </summary>
  434. /// <param name="wBitmap"></param>
  435. /// <returns></returns>
  436. public static Bitmap SafeConvert(WriteableBitmap wb)
  437. {
  438. Bitmap bmp = new Bitmap(wb.PixelWidth, wb.PixelHeight);
  439. using (var ms = new System.IO.MemoryStream())
  440. {
  441. var encoder = new PngBitmapEncoder();
  442. encoder.Frames.Add(BitmapFrame.Create(wb));
  443. encoder.Save(ms);
  444. bmp = (Bitmap)System.Drawing.Image.FromStream(ms);
  445. }
  446. return bmp;
  447. }
  448. // 使用Windows API实现内存拷贝(支持重叠内存区域)
  449. [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
  450. private static extern void RtlMoveMemory(IntPtr dest, IntPtr src, uint length);
  451. // 安全封装方法(带参数校验)
  452. public static void SafeMemoryCopy(IntPtr dest, IntPtr src, int byteCount)
  453. {
  454. if (dest == IntPtr.Zero || src == IntPtr.Zero)
  455. throw new ArgumentNullException("指针参数不能为null");
  456. if (byteCount <= 0)
  457. throw new ArgumentOutOfRangeException("字节数必须大于0");
  458. RtlMoveMemory(dest, src, (uint)byteCount);
  459. }
  460. /// <summary>
  461. /// 将WriteableBitmap转换为CogImage8Grey(自动处理彩色转灰度)
  462. /// </summary>
  463. public void OnSwitchToolBlock(int index)
  464. {
  465. cogToolBlock1 = CamTemplateS[index];
  466. ToolBlockSwitched?.Invoke(index); // 触发事件,传递索引参数。
  467. }
  468. /// <summary>
  469. /// 相机连接或者断开时
  470. /// </summary>
  471. /// <param name="id"></param>
  472. /// <param name="state"></param>
  473. private void Management_CameraConnectChangedEvent(Guid id, bool state)
  474. {
  475. // var sta = Status.FirstOrDefault(s => s.ID == id);
  476. // var camera = DeviceConfig.Cameras.FirstOrDefault(c => c.Id == id);
  477. //if ( sta != null && camera != null )
  478. //{
  479. // if ( state )
  480. // {
  481. // App.Current.Dispatcher.Invoke(new Action(() =>
  482. // {
  483. // sta.Message = $"{camera.CameraName}{connected}";
  484. // sta.Background = new SolidColorBrush(Colors.Green);
  485. // }));
  486. // }
  487. // else
  488. // {
  489. // App.Current.Dispatcher.Invoke(new Action(() =>
  490. // {
  491. // sta.Message = $"{camera.CameraName}{disconnected1}";
  492. // sta.Background = new SolidColorBrush(Colors.Red);
  493. // }));
  494. // }
  495. //}
  496. }
  497. }
  498. }