版博士V2.0程序
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. using CalTools;
  2. using MaiMuAOI.ImageProcessing;
  3. using Newtonsoft.Json;
  4. using OpenCvSharp;
  5. using ProductionControl.UIExtend;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Data;
  10. using System.Drawing;
  11. using System.Drawing.Imaging;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Windows.Forms;
  18. using static MaiMuAOI.ImageProcessing.DefectLib;
  19. namespace DefectInferTool
  20. {
  21. public partial class Form1 : Form
  22. {
  23. private string AIModelPath;
  24. private string _sizeItemsPath;
  25. private string _defectItemsPath;
  26. private string _defectOnnxName;
  27. private string _defectOnnxPath;
  28. private string _smallImagePath;
  29. private DefectLib defectLib;
  30. private int defectBmpNum;
  31. private int defectBmpNumResult;
  32. private List<QualifiedCriterion> QualifiedCriterionList;
  33. private bool OpenAsideDefect;
  34. private OpenCvSharp.Size CutSize = new OpenCvSharp.Size(592, 532);
  35. private OpenCvSharp.Size tResize = new OpenCvSharp.Size(224, 224);
  36. private float Thresholds = 0.4f;
  37. private int tHoleCount;
  38. private int AllDefectCount;
  39. private List<DefectCntInfo> DefectCntInfoList = new List<DefectCntInfo>();
  40. public Form1()
  41. {
  42. InitializeComponent();
  43. }
  44. private void Form1_Load(object sender, EventArgs e)
  45. {
  46. AIModelPath = Path.Combine(Directory.GetCurrentDirectory(), "ConfigFiles\\onnxFiles");
  47. numericUpDown1.Value = CutSize.Width;
  48. numericUpDown2.Value = CutSize.Height;
  49. numericUpDown4.Value = tResize.Width;
  50. numericUpDown3.Value = tResize.Height;
  51. numericUpDown6.Value = (decimal)Thresholds;
  52. GetModels();
  53. defectLib = new DefectLib();
  54. defectLib.WarningEvent = (warning, msg) =>
  55. {
  56. AddTextEvent("缺陷处理", msg, warning);
  57. };
  58. if (!defectLib.start())
  59. MessageBox.Show("外观检测核心初始化失败!");
  60. }
  61. #region 模型选择
  62. private void GetModels()
  63. {
  64. var dirs = Directory.GetDirectories(AIModelPath);
  65. string[] pname = new string[dirs.Length];
  66. int i = 0;
  67. foreach (var item in dirs)
  68. {
  69. pname[i++] = Path.GetFileNameWithoutExtension(item);
  70. }
  71. this.comboBox1.Items.Clear();
  72. this.comboBox1.Items.AddRange(pname);
  73. }
  74. #endregion
  75. #region 缺陷检测项
  76. #region 缺陷检测参数
  77. public class DefectItemParam
  78. {
  79. /// <summary>
  80. /// 名称
  81. /// </summary>
  82. public string Name { get; set; }
  83. /// <summary>
  84. /// 代码
  85. /// </summary>
  86. public string Code { get; set; }
  87. /// <summary>
  88. /// 序号
  89. /// </summary>
  90. public int Index { get; set; }
  91. /// <summary>
  92. /// 默认分值
  93. /// </summary>
  94. public double Threshold { get; set; }
  95. /// <summary>
  96. /// RGB颜色代码
  97. /// </summary>
  98. public int[] RGBcolor { get; set; }
  99. /// <summary>
  100. /// 对应类型
  101. /// </summary>
  102. public string Type { get; set; }
  103. /// <summary>
  104. /// 尺寸
  105. /// </summary>
  106. public float Size { get; set; }
  107. /// <summary>
  108. /// 最大允许缺陷数量
  109. /// </summary>
  110. public int MaxDefectCount { get; set; }
  111. /// <summary>
  112. /// 显示
  113. /// </summary>
  114. public int Show { get; set; }
  115. }
  116. #endregion
  117. public List<DefectItemParam> DefectItemParamsList = new List<DefectItemParam>();
  118. public void ReadDefectItems(string path)
  119. {
  120. string _rootPath = Path.Combine(Directory.GetCurrentDirectory(), "ConfigFiles\\onnxFiles\\" + path);
  121. //_sizeItemsPath = Path.Combine(_rootPath, "尺寸测试项.json");
  122. _defectItemsPath = Path.Combine(_rootPath, "缺陷测试项.json");
  123. _defectOnnxPath = Directory.GetFiles(_rootPath, "*.onnx", SearchOption.TopDirectoryOnly)[0];
  124. _defectOnnxName = Path.GetFileNameWithoutExtension(Directory.GetFiles(_rootPath, "*.onnx", SearchOption.TopDirectoryOnly )[0]);
  125. if(string.IsNullOrEmpty(_defectItemsPath))
  126. {
  127. MessageBox.Show("缺少 缺陷测试项.json!");
  128. return;
  129. }
  130. if (string.IsNullOrEmpty(_defectOnnxName))
  131. {
  132. MessageBox.Show("缺少 onnx模型!");
  133. return;
  134. }
  135. string str = File.ReadAllText(_defectItemsPath);
  136. DefectItemParamsList = JsonConvert.DeserializeObject<List<DefectItemParam>>(str);
  137. }
  138. #endregion
  139. #region 记录
  140. object AddTextLock = new object();
  141. private void AddTextEvent(string tag, string msg, WarningEnum level = WarningEnum.Normal)
  142. {
  143. this.Invoke(new Action(() =>
  144. {
  145. lock (AddTextLock)
  146. {
  147. if (tag != null && tag != "")
  148. tag = $" - [{tag}]";
  149. var now = DateTime.Now;
  150. msg = now.ToString("HH:mm:ss fff") + tag + " - " + msg;
  151. msg = (level == WarningEnum.Normal ? "B" : level == WarningEnum.Low ? "Y" : "R") + msg;
  152. if (this.lstLog.Items.Count > 1000)
  153. this.lstLog.Items.Clear();
  154. lstLog.Items.Insert(0, msg);
  155. }
  156. }));
  157. }
  158. #endregion
  159. #region 推理
  160. private void button1_Click(object sender, EventArgs e)
  161. {
  162. if (string.IsNullOrEmpty(_defectOnnxName))
  163. {
  164. MessageBox.Show($"没用模型", "警告");
  165. return;
  166. }
  167. string imgfilePath;
  168. FolderBrowserDialog dlg = new FolderBrowserDialog();
  169. dlg.Description = "选择处理图片路径";
  170. //dlg.SelectedPath = (defaultPath != "" ? defaultPath : Path.GetFullPath("."));
  171. if (dlg.ShowDialog() == DialogResult.OK)
  172. imgfilePath = dlg.SelectedPath;
  173. else
  174. return;
  175. textBox3.Text = imgfilePath;
  176. //string tp = radioButton1.Checked ? "*.bmp" : "*.jpg";
  177. string tp = "*.bmp";
  178. string[] files = Directory.GetFiles(imgfilePath, tp, SearchOption.TopDirectoryOnly);
  179. if (files == null || files.Length <= 0)
  180. {
  181. MessageBox.Show($"缺少推理的{tp}图片", "警告");
  182. return;
  183. }
  184. this.gboxDefectList.Tag = 0;
  185. AllDefectCount = 0;
  186. defectBmpNum = 0;
  187. defectBmpNumResult = 0;
  188. _smallImagePath = textBox4.Text;
  189. OpenAsideDefect = checkBox1.Checked;
  190. CutSize.Width = (int)numericUpDown1.Value;
  191. CutSize.Height = (int)numericUpDown2.Value;
  192. tResize.Width = (int)numericUpDown4.Value;
  193. tResize.Height = (int)numericUpDown3.Value;
  194. Thresholds = (float)numericUpDown6.Value;
  195. tHoleCount = (int)numericUpDown5.Value;
  196. if (DefectCntInfoList == null)
  197. DefectCntInfoList = new List<DefectCntInfo>();
  198. else
  199. DefectCntInfoList.Clear();
  200. if (QualifiedCriterionList == null)
  201. QualifiedCriterionList = new List<QualifiedCriterion>();
  202. else
  203. QualifiedCriterionList.Clear();
  204. foreach (DefectCountOfSizeControl defectControl in this.flpQualifiedPannel.Controls)
  205. {
  206. if (defectControl.Checked)
  207. {
  208. QualifiedCriterionList.Add(
  209. new QualifiedCriterion()
  210. {
  211. DefectCode = defectControl.Code,
  212. Size = (float)defectControl.SizeValue,
  213. MaxDefectCount = (int)defectControl.MaxDefectCount,
  214. Threshold = (double)defectControl.Threshold,
  215. });
  216. }
  217. }
  218. defectLib.loadModelFile(_defectOnnxPath, checkBox2.Checked);
  219. for (int i = 0; i < files.Count(); i++)
  220. {
  221. Mat mat = new Mat(files[i], ImreadModes.Color);
  222. AddInfer(mat, mat);
  223. AddTextEvent("加载图片", files[i]);
  224. }
  225. while(true)
  226. {
  227. if (defectBmpNum >0 && defectBmpNumResult == defectBmpNum)
  228. break;
  229. Thread.Sleep(100);
  230. Application.DoEvents();
  231. }
  232. MessageBox.Show("处理完成");
  233. }
  234. /// <summary>
  235. /// 获取种类阈值
  236. /// </summary>
  237. /// <param name="m"></param>
  238. /// <returns></returns>
  239. private string getProductThresholClass()
  240. {
  241. string thresStr = "";
  242. foreach (var item in DefectItemParamsList)
  243. {
  244. if ((item.Type.Split(',').Count(p => p == "-1") > 0) ||
  245. (item.Type.Split(',').Count(p => p == _defectOnnxName.Replace(".onnx", "")) > 0))
  246. {
  247. bool have = false;
  248. if (QualifiedCriterionList != null)
  249. {
  250. foreach (var queItem in QualifiedCriterionList)
  251. {
  252. if (queItem.DefectCode == item.Code)
  253. {
  254. have = true;
  255. if (queItem.Threshold != null || queItem.Threshold > 0)
  256. thresStr += queItem.Threshold.ToString() + ",";
  257. else
  258. thresStr += item.Threshold.ToString() + ",";
  259. break;
  260. }
  261. }
  262. }
  263. if (!have)
  264. {
  265. thresStr += item.Threshold.ToString() + ",";
  266. }
  267. }
  268. }
  269. //移除最后的,
  270. if (thresStr.Length > 0)
  271. {
  272. thresStr = thresStr.Remove(thresStr.Length - 1);
  273. }
  274. return thresStr;
  275. }
  276. /// <summary>
  277. /// 获取缺陷项阈值
  278. /// </summary>
  279. /// <param name="m"></param>
  280. /// <returns></returns>
  281. private Dictionary<string, float> getProductAreaThreshol(int HoleCount)
  282. {
  283. Dictionary<string, float> dic = new Dictionary<string, float>();
  284. if (!OpenAsideDefect)
  285. {
  286. foreach (var item in QualifiedCriterionList)
  287. dic.Add(item.DefectCode, (float)(item.Size * 25.4 * 25.4 / HoleCount / HoleCount));//网目 => mm^2
  288. }
  289. else
  290. {
  291. foreach (var item in QualifiedCriterionList)
  292. dic.Add(item.DefectCode, (float)(item.Size * 25.4 / HoleCount));//网目 => mm^2
  293. }
  294. //dic.Add(item.DefectCode, (float)(item.Size * 25.4 * 25.4 / m.HoleCount / m.HoleCount));//网目 => mm^2
  295. //全缺陷项
  296. foreach (var item in DefectItemParamsList)
  297. {
  298. string code = item.Code;
  299. if (!dic.ContainsKey(code))
  300. dic.Add(code, 0);
  301. }
  302. return dic;
  303. }
  304. public void countDefectClass(List<string>[] list)
  305. {
  306. string className;
  307. for (int i = 0; i < list.Length; i++)
  308. {
  309. var fd = DefectItemParamsList.Find(p => p.Code == list[i][4]);
  310. if (fd != null)
  311. {
  312. string name = fd.Name;
  313. //改变list中某个元素值
  314. var model = DefectCntInfoList.Where(c => c.Name == name).FirstOrDefault();
  315. if (model != null)
  316. {
  317. model.DefectCnt++;
  318. }
  319. else
  320. {
  321. DefectCntInfoList.Add(new DefectCntInfo()
  322. {
  323. Code = fd.Code,
  324. Name = fd.Name,
  325. DefectCnt = 1,
  326. });
  327. }
  328. }
  329. }
  330. }
  331. private void showDefectSmallBmps(Bitmap[] bmps, Mat[] bmps_cut, double Xmm, double Ymm, List<Dictionary<int, List<string>[]>> info)
  332. {
  333. this.Invoke(new Action(() =>
  334. {
  335. //加载缺陷小图
  336. //纵向显示
  337. int imgWidth = this.pnlBmpList.ClientSize.Width - 50;
  338. int imgHeight = (int)((bmps[0].Height * 1.0f / bmps[0].Width) * imgWidth + 0.5);
  339. int splitWidth = 20;
  340. int pnlWidth = this.pnlBmpList.ClientSize.Width;
  341. int index = (int)this.gboxDefectList.Tag;
  342. //横向显示
  343. //int imgHeight = this.pnlBmpList.Height - 50;
  344. //int imgWidth = (int)((e.Bitmaps[0].Width * 1.0f / e.Bitmaps[0].Height) * imgHeight + 0.5);
  345. //int splitWidth = 20;
  346. //int pnlWidth = this.pnlBmpList.Height;
  347. //int index = (int)this.gboxDefectList.Tag;
  348. int len = info.Count();
  349. int range = 100;
  350. int uselen = len > 100 ? 100 : len;
  351. for (int x = 0; x < uselen / range + 1; x++)
  352. {
  353. for (int i = 0; i < (x < (uselen / range) ? range : uselen % range); i++)
  354. {
  355. foreach (var item in info[(x * range + i)]) //单个info[x] = {"1":[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]}
  356. {
  357. //统计缺陷类型
  358. countDefectClass(item.Value);//[["92.7542","80.85799","99.54083","86.05363","dk","0.52"]]
  359. //
  360. PictureBox picbox = new PictureBox();
  361. picbox.Width = imgWidth;
  362. picbox.Height = imgHeight;
  363. picbox.Image = (Bitmap)bmps[(x * range + i)].Clone();
  364. picbox.Name = "imgDefect_" + index;
  365. picbox.Tag = item.Key + "," + Xmm + "," + Ymm;
  366. //picbox.Click += new EventHandler(defectBmpBox_Click);
  367. picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
  368. picbox.BorderStyle = BorderStyle.FixedSingle;
  369. //picbox.Margin = new Padding((pnlWidth - picbox.Height) / 2, splitWidth, 0, 0);
  370. picbox.Margin = new Padding((pnlWidth - picbox.Width) / 2, splitWidth, 0, 0);
  371. //picbox.MouseHover += simpleTip_MouseHover;
  372. picbox.Visible = true;
  373. //this.Invoke(new MethodInvoker(() =>
  374. // {
  375. this.pnlBmpList.Controls.Add(picbox);
  376. //this.Refresh();
  377. //this.dgvProcess.Refresh();
  378. //this.lstLog.Refresh();
  379. //this.statusStrip1.Refresh();
  380. // }));
  381. break;
  382. }
  383. //
  384. index++;
  385. //Thread.Sleep(10);
  386. //Application.DoEvents();
  387. }
  388. //Application.DoEvents();
  389. //this.Invoke(new MethodInvoker(() =>
  390. //{
  391. //this.Refresh();
  392. pnlBmpList.VerticalScroll.Value = pnlBmpList.VerticalScroll.Maximum;
  393. //}));
  394. //Thread.Sleep(10);
  395. }
  396. //this.Invoke(new MethodInvoker(() =>
  397. //{
  398. //this.gboxDefectList.Tag = len + (int)this.gboxDefectList.Tag;
  399. this.gboxDefectList.Tag = index;
  400. this.gboxDefectList.Text = $"缺陷图像:{index} 张";
  401. //return 0;
  402. }));
  403. }
  404. private void AddInfer(Mat bmpLoc, Mat toDefect)
  405. {
  406. string modeltp = "pt";
  407. if (_defectOnnxName.Replace(".onnx", "").IndexOf("rj") >= 0)
  408. modeltp = "rj";
  409. else
  410. modeltp = "pt";
  411. defectLib.add(new DefectTask()
  412. {
  413. stepIndex = 0,
  414. processName = "模拟测试",
  415. modelType = modeltp,
  416. drawingPagePath = "",
  417. //index = defectBmpNum++,
  418. index = defectBmpNum,
  419. srcbmp = bmpLoc.Clone(),
  420. bmp = toDefect.Clone(),
  421. //bmp = mats[0].Clone(),
  422. Xmm = 0,
  423. Ymm = 0,
  424. cut_size = new System.Drawing.Size(CutSize.Width, CutSize.Height),
  425. resize = new System.Drawing.Size(tResize.Width, tResize.Height),
  426. thresholds = Thresholds,
  427. thresholdsClass = getProductThresholClass(),
  428. recAreaThreshold = getProductAreaThreshol(tHoleCount), //qxName,面积; qxName,面积; qxName,面积;
  429. finishEvent = (res) =>
  430. {
  431. int err = 0;
  432. try
  433. {
  434. string path = "";
  435. if (res.isSucceed)
  436. {
  437. //OnAutoRuning(new RunEventArgs(liStatocStepIndex,
  438. // $"源图索引:{res.index},缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}"));
  439. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测完成(源图索引:{res.index}),缺陷数:{res.defectCount},处理时间(ms):{string.Join("->", res.stopwatch.Select(i => i.ToString()).ToArray())}");
  440. //string path = "";
  441. if (res.defectCount > 0)
  442. {
  443. err = 1;
  444. //UI显示小图 (含统计缺陷类型数量)
  445. AllDefectCount += res.informationList.Count;
  446. showDefectSmallBmps(res.bmps_tag, res.bmps_cut, res.Xmm, res.Ymm, res.informationList);
  447. err = 2;
  448. //保存小图
  449. if (_smallImagePath != "" && Directory.Exists(_smallImagePath))
  450. {
  451. err = 8;
  452. //2024-03-07 图片index计算
  453. List<string> indexList = new List<string>();
  454. if (res.defectInfor2RestorationDeskPage != null && res.defectInfor2RestorationDeskPage.Count > 0)
  455. foreach (var item in res.defectInfor2RestorationDeskPage)
  456. {
  457. if (indexList.Count == 0)
  458. indexList.Add(item[0]);
  459. else
  460. {
  461. if (!indexList.Contains(item[0]))
  462. indexList.Add(item[0]);
  463. }
  464. }
  465. path = _smallImagePath;
  466. path += $"\\Defect_I{res.index}_test";
  467. err = 9;
  468. for (int i = 0; i < res.bmps_tag.Count(); i++)
  469. {
  470. res.bmps_tag[i].Save(path + $"_i{i}.bmp", ImageFormat.Bmp);
  471. Thread.Sleep(10);
  472. }
  473. err = 10;
  474. }
  475. }
  476. else//没有缺陷
  477. {
  478. }
  479. }
  480. else
  481. {
  482. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测失败:{res.resultInfo}");
  483. }
  484. }
  485. catch (Exception ex)
  486. {
  487. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测回调处理异常-{err} index:{res.index},ex={ex.Message}");
  488. }
  489. defectBmpNumResult++;
  490. try
  491. {
  492. foreach (var item in res.bmps_cut)
  493. item.Dispose();
  494. res.bmp.Dispose();
  495. res.bmp = null;
  496. res.bmps_tag = null;
  497. if (res.bmpCompress != null)
  498. {
  499. res.bmpCompress.Dispose();
  500. res.bmpCompress = null;
  501. }
  502. if (res.srcbmp != null)
  503. {
  504. res.srcbmp.Dispose();
  505. res.srcbmp = null;
  506. }
  507. }
  508. catch (Exception ex)
  509. {
  510. AddTextEvent($"{res.stepIndex + 1}-{res.processName}", $"缺陷检测回调释放内存异常 index:{res.index},ex={ex.Message}");
  511. }
  512. System.GC.Collect();
  513. }
  514. });
  515. defectBmpNum++;
  516. }
  517. #endregion
  518. #region 模型选择
  519. private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
  520. {
  521. ReadDefectItems(this.comboBox1.Text);
  522. foreach (var item in DefectItemParamsList)
  523. {
  524. string mdname = _defectOnnxName;
  525. if ((item.Type.Split(',').Count(p => p == "-1") > 0) ||
  526. (item.Type.Split(',').Count(p => p == mdname.Replace(".onnx", "")) > 0))
  527. {
  528. DefectCountOfSizeControl userCon = new DefectCountOfSizeControl();
  529. userCon.Code = item.Code;
  530. userCon.Title = item.Name;
  531. userCon.Threshold = (decimal)item.Threshold;
  532. //不显示,是有默认值
  533. if (item.Show == 0)
  534. {
  535. userCon.Checked = true;
  536. userCon.Threshold = (decimal)item.Threshold;
  537. userCon.SizeValue = (decimal)item.Size;
  538. userCon.MaxDefectCount = item.MaxDefectCount;
  539. userCon.Visible = false;
  540. }
  541. else
  542. {
  543. userCon.Checked = true;
  544. userCon.Threshold = (decimal)item.Threshold;
  545. userCon.SizeValue = (decimal)item.Size;
  546. userCon.MaxDefectCount = item.MaxDefectCount;
  547. }
  548. this.flpQualifiedPannel.Controls.Add(userCon);
  549. }
  550. }
  551. }
  552. #endregion
  553. #region 小图存储
  554. private void button2_Click(object sender, EventArgs e)
  555. {
  556. FolderBrowserDialog dlg = new FolderBrowserDialog();
  557. //dlg.SelectedPath = (Application.StartupPath != "" ? Application.StartupPath : Path.GetFullPath("."));
  558. if (dlg.ShowDialog() == DialogResult.OK)
  559. {
  560. textBox4.Text = dlg.SelectedPath;
  561. }
  562. else
  563. return;
  564. }
  565. #endregion
  566. #region 标定
  567. /// <summary>
  568. /// 选择文件
  569. /// </summary>
  570. /// <param name="filter">如 图像文件|*.jpg|图像文件|*.png|所有文件|*.*</param>
  571. /// <returns></returns>
  572. public static string SelectFile(string filter = "所有文件|*.*", string defaultPath = "")
  573. {
  574. OpenFileDialog fie = new OpenFileDialog();
  575. fie.Title = "选择文件";
  576. //fie.InitialDirectory = (defaultPath != "" ? defaultPath : Path.GetFullPath("."));
  577. fie.Filter = filter; //设置文件类型
  578. if (fie.ShowDialog() == DialogResult.OK)
  579. return fie.FileName;
  580. return "";
  581. }
  582. private void tbTZPath_Click(object sender, EventArgs e)
  583. {
  584. TextBox tb = (TextBox)sender;
  585. string path = SelectFile("所有文件|*.*", Application.StartupPath);
  586. if (!string.IsNullOrWhiteSpace(path))
  587. {
  588. tb.Text = path.Remove(path.Length-4,4);
  589. }
  590. }
  591. /// <summary>
  592. /// 选择目录
  593. /// </summary>
  594. /// <returns></returns>
  595. public static string SelectFolder(string defaultPath = "")
  596. {
  597. FolderBrowserDialog dlg = new FolderBrowserDialog();
  598. dlg.SelectedPath = (defaultPath != "" ? defaultPath : Path.GetFullPath("."));
  599. if (dlg.ShowDialog() == DialogResult.OK)
  600. return dlg.SelectedPath;
  601. return "";
  602. }
  603. private void tbSFPath_Click(object sender, EventArgs e)
  604. {
  605. TextBox tb = (TextBox)sender;
  606. string path = SelectFolder(Application.StartupPath);
  607. if (!string.IsNullOrWhiteSpace(path))
  608. {
  609. tb.Text = path;
  610. }
  611. }
  612. private void btnMarkCal_Click(object sender, EventArgs e)
  613. {
  614. CalToolsClass calToolsClass = new CalToolsClass();
  615. double[] sizeX = new double[4];
  616. double[] sizeY = new double[4];
  617. double[] defectX = new double[4];
  618. double[] defectY = new double[4];
  619. double zpos = (double)ZPos.Value;
  620. sizeX[0] = (double)markX1.Value;
  621. sizeX[1] = (double)markX2.Value;
  622. sizeX[2] = (double)markX3.Value;
  623. sizeX[3] = (double)markX4.Value;
  624. sizeY[0] = (double)MarkY1.Value;
  625. sizeY[1] = (double)MarkY2.Value;
  626. sizeY[2] = (double)MarkY3.Value;
  627. sizeY[3] = (double)MarkY4.Value;
  628. defectX[0] = (double)qx_markX1.Value;
  629. defectX[1] = (double)qx_markX2.Value;
  630. defectX[2] = (double)qx_markX3.Value;
  631. defectX[3] = (double)qx_markX4.Value;
  632. defectY[0] = (double)qx_markY1.Value;
  633. defectY[1] = (double)qx_markY2.Value;
  634. defectY[2] = (double)qx_markY3.Value;
  635. defectY[3] = (double)qx_markY4.Value;
  636. HalconDotNet.HTuple GerBerPath = new HalconDotNet.HTuple(tbTZPath.Text);
  637. HalconDotNet.HTuple FilePath = new HalconDotNet.HTuple(tbSFPath.Text);
  638. HalconDotNet.HTuple hv_PoseMarkX_CCDSize = new HalconDotNet.HTuple(sizeX);
  639. HalconDotNet.HTuple hv_PoseMarkY_CCDSize = new HalconDotNet.HTuple(sizeY);
  640. HalconDotNet.HTuple hv_PoseMarkX_CCDDefect = new HalconDotNet.HTuple(defectX);
  641. HalconDotNet.HTuple hv_PoseMarkY_CCDDefect = new HalconDotNet.HTuple(defectY);
  642. HalconDotNet.HTuple hv_PoseZ_Size = new HalconDotNet.HTuple(zpos);
  643. var ret = (bool)calToolsClass.CCDPoseCal_Mark(GerBerPath, FilePath, sizeX, sizeY,
  644. defectX, defectY, zpos);
  645. if(ret)
  646. {
  647. MessageBox.Show("主机台标定成功!", "标定");
  648. }
  649. else
  650. {
  651. MessageBox.Show("主机台标定失败!", "标定", MessageBoxButtons.OK, MessageBoxIcon.Error);
  652. }
  653. }
  654. private void btnNoMarkCal_Click(object sender, EventArgs e)
  655. {
  656. CalToolsClass calToolsClass = new CalToolsClass();
  657. double[] sizeX = new double[4];
  658. double[] sizeY = new double[4];
  659. double[] defectX = new double[4];
  660. double[] defectY = new double[4];
  661. double zpos = (double)ZPos.Value;
  662. sizeX[0] = (double)markX1.Value;
  663. sizeX[1] = (double)markX2.Value;
  664. sizeX[2] = (double)markX3.Value;
  665. sizeX[3] = (double)markX4.Value;
  666. sizeY[0] = (double)MarkY1.Value;
  667. sizeY[1] = (double)MarkY2.Value;
  668. sizeY[2] = (double)MarkY3.Value;
  669. sizeY[3] = (double)MarkY4.Value;
  670. defectX[0] = (double)qx_markX1.Value;
  671. defectX[1] = (double)qx_markX2.Value;
  672. defectX[2] = (double)qx_markX3.Value;
  673. defectX[3] = (double)qx_markX4.Value;
  674. defectY[0] = (double)qx_markY1.Value;
  675. defectY[1] = (double)qx_markY2.Value;
  676. defectY[2] = (double)qx_markY3.Value;
  677. defectY[3] = (double)qx_markY4.Value;
  678. HalconDotNet.HTuple GerBerPath = new HalconDotNet.HTuple(tbTZPath.Text);
  679. HalconDotNet.HTuple FilePath = new HalconDotNet.HTuple(tbSFPath.Text);
  680. HalconDotNet.HTuple hv_PoseMarkX_CCDSize = new HalconDotNet.HTuple(sizeX);
  681. HalconDotNet.HTuple hv_PoseMarkY_CCDSize = new HalconDotNet.HTuple(sizeY);
  682. HalconDotNet.HTuple hv_PoseMarkX_CCDDefect = new HalconDotNet.HTuple(defectX);
  683. HalconDotNet.HTuple hv_PoseMarkY_CCDDefect = new HalconDotNet.HTuple(defectY);
  684. HalconDotNet.HTuple hv_PoseZ_Size = new HalconDotNet.HTuple(zpos);
  685. var ret = (bool)calToolsClass.CCDPoseCal_Corner(GerBerPath, FilePath, sizeX, sizeY,
  686. defectX, defectY, zpos);
  687. if (ret)
  688. {
  689. MessageBox.Show("主机台无Mark标定成功!", "标定");
  690. }
  691. else
  692. {
  693. MessageBox.Show("主机台无Mark标定失败!", "标定", MessageBoxButtons.OK, MessageBoxIcon.Error);
  694. }
  695. }
  696. private void btnCal_Click(object sender, EventArgs e)
  697. {
  698. CalToolsClass calToolsClass = new CalToolsClass();
  699. double BeforeX = (double)bX1.Value;
  700. double BeforeY = (double)bY1.Value;
  701. double AfterX = (double)aX1.Value;
  702. double AfterY = (double)aY1.Value;
  703. HalconDotNet.HTuple hv_BeforeX = new HalconDotNet.HTuple(BeforeX);
  704. HalconDotNet.HTuple hv_BeforeY = new HalconDotNet.HTuple(BeforeY);
  705. HalconDotNet.HTuple hv_AfterX = new HalconDotNet.HTuple(AfterX);
  706. HalconDotNet.HTuple hv_AfterY = new HalconDotNet.HTuple(AfterY);
  707. var ret = (bool)calToolsClass.RepairCal_2(BeforeX, BeforeY, AfterX, AfterY);
  708. if (ret)
  709. {
  710. MessageBox.Show("修复台标定成功!", "标定");
  711. }
  712. else
  713. {
  714. MessageBox.Show("修复台标定失败!", "标定", MessageBoxButtons.OK, MessageBoxIcon.Error);
  715. }
  716. }
  717. #endregion
  718. private void button3_Click(object sender, EventArgs e)
  719. {
  720. CalToolsClass calToolsClass = new CalToolsClass();
  721. var ret = (bool)calToolsClass.RepairCal_1();
  722. if (ret)
  723. {
  724. MessageBox.Show("修复台标定1成功!", "标定");
  725. }
  726. else
  727. {
  728. MessageBox.Show("修复台标定1失败!", "标定", MessageBoxButtons.OK, MessageBoxIcon.Error);
  729. }
  730. }
  731. private void tbSFPath_TextChanged(object sender, EventArgs e)
  732. {
  733. }
  734. }
  735. public class DefectCntInfo
  736. {
  737. public int Pid { get; set; }
  738. //测试项名称
  739. public string Name { get; set; }
  740. //测试项代码
  741. public string Code { get; set; }
  742. //个数
  743. public int DefectCnt { get; set; }
  744. }
  745. /// <summary>
  746. /// 合格标准
  747. /// </summary>
  748. public class QualifiedCriterion
  749. {
  750. public int Pid { get; set; }
  751. public string DefectCode { get; set; }//pp,sx,... EnumUtil.Convert2Enum
  752. /// <summary>
  753. /// 阈值 20240409
  754. /// </summary>
  755. public double Threshold { get; set; }
  756. /// <summary>
  757. /// 尺寸
  758. /// </summary>
  759. public float Size { get; set; }
  760. /// <summary>
  761. /// 最大允许缺陷数量
  762. /// </summary>
  763. public int MaxDefectCount { get; set; }
  764. }
  765. }