OTSImageDisHelp.cs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. using OpenCvSharp;
  2. using OTSCLRINTERFACE;
  3. using OTSCommon.Model;
  4. using OTSIncAReportApp.DataOperation.DataAccess;
  5. using OTSIncAReportGraph.Controls;
  6. using OTSModelSharp.DTLBase;
  7. using OTSModelSharp.ServiceCenter;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Drawing;
  11. using System.Drawing.Drawing2D;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Runtime.Serialization.Formatters.Binary;
  15. using Point = System.Drawing.Point;
  16. namespace OTSIncAReportGraph.OTSIncAReportGraphFuncation
  17. {
  18. public class OTSImageDisHelp
  19. {
  20. #region 枚举定义
  21. /// <summary>
  22. /// 样品台X轴方向
  23. /// </summary>
  24. enum OTS_X_AXIS_DIRECTION
  25. {
  26. LEFT_TOWARD = 0,
  27. RIGHT_TOWARD = 1
  28. }
  29. /// <summary>
  30. /// 样品台Y轴方向
  31. /// </summary>
  32. enum OTS_Y_AXIS_DIRECTION
  33. {
  34. UP_TOWARD = 0,
  35. DOWN_TOWARD = 1
  36. }
  37. #endregion
  38. #region 定义变量
  39. public ResultFile resultFile = null;
  40. public ParticleSegmentation m_ParticleSegmentation;
  41. public Point OTSLeftBottomPoint;
  42. public Point OTSRightUpPoint;
  43. public RectangleF m_originalBackRect;
  44. public double m_pixelSize;
  45. private List<Point> fieldCenterList;
  46. NLog.Logger log;
  47. //电镜设置对象
  48. public ServiceInterface.HardwareController m_cfun = null;
  49. #endregion
  50. #region 构造函数
  51. public OTSImageDisHelp( ResultFile result)
  52. {
  53. resultFile = result;
  54. m_cfun = ServiceInterface.HardwareController.GetSemController();
  55. List<Field> fieldlist = resultFile.List_OTSField;
  56. int fieldwidth;
  57. SizeF s = GetFieldImageSize();
  58. fieldwidth = (int)s.Width;
  59. fieldCenterList = new List<Point>();
  60. for (int i = 0; i < fieldlist.Count(); i++)
  61. {
  62. Point ls_point = new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY };
  63. fieldCenterList.Add(ls_point);
  64. }
  65. SizeF physicalfiledsize = GetPhysicalFieldWidthAndHeight();
  66. m_pixelSize = Convert.ToDouble(physicalfiledsize.Width) / Convert.ToDouble(fieldwidth);
  67. OTSLeftBottomPoint = GetOTSCoordLeftBottomPoint(fieldCenterList, (int)physicalfiledsize.Width, (int)physicalfiledsize.Height);
  68. OTSRightUpPoint = GetOTSCoordRightUpPoint(fieldCenterList, (int)physicalfiledsize.Width, (int)physicalfiledsize.Height);
  69. m_originalBackRect = new RectangleF(0, 0, (float)((OTSRightUpPoint.X - OTSLeftBottomPoint.X)/m_pixelSize), (float)((OTSRightUpPoint.Y - OTSLeftBottomPoint.Y)/m_pixelSize));
  70. log = NLog.LogManager.GetCurrentClassLogger();
  71. }
  72. #endregion
  73. #region 封装自定义方法
  74. private Point GetOTSCoordLeftBottomPoint(List<Point> allFldPos,int fieldwidth,int fieldheight)
  75. {
  76. //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the smallest point.
  77. //找出最小的x,y用来做偏移运算
  78. int i_offset_x = 1000000000;
  79. int i_offset_y = 1000000000;
  80. //先取出最小的x,y
  81. for (int i = 0; i < allFldPos.Count; i++)
  82. {
  83. if (i_offset_x > allFldPos[i].X)
  84. {
  85. i_offset_x = allFldPos[i].X;
  86. }
  87. if (i_offset_y > allFldPos[i].Y)
  88. {
  89. i_offset_y = allFldPos[i].Y;
  90. }
  91. }
  92. return new Point(i_offset_x-fieldwidth/2, i_offset_y-fieldheight/2);//the field pos is the center point position.
  93. }
  94. private Point GetOTSCoordRightUpPoint(List<Point> allFldPos, int fieldwidth, int fieldheight)
  95. {
  96. //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the biggest point.
  97. //找出最小的x,y用来做偏移运算
  98. int i_offset_x = -1000000000;
  99. int i_offset_y = -1000000000;
  100. //先取出最小的x,y
  101. for (int i = 0; i < allFldPos.Count; i++)
  102. {
  103. if (i_offset_x < allFldPos[i].X)
  104. {
  105. i_offset_x = allFldPos[i].X;
  106. }
  107. if (i_offset_y < allFldPos[i].Y)
  108. {
  109. i_offset_y = allFldPos[i].Y;
  110. }
  111. }
  112. return new Point(i_offset_x + fieldwidth / 2, i_offset_y + fieldheight / 2);//the field pos is the center point position.
  113. }
  114. public Point ConvertOTSCoordToScreenCoord( Point currenFldOTSPos)//
  115. {
  116. var OTSPoint=new Point(currenFldOTSPos.X - OTSLeftBottomPoint.X, currenFldOTSPos.Y - OTSLeftBottomPoint.Y);
  117. int screenHeight = (int)m_originalBackRect.Height + (0 - (int)(Convert.ToDouble(OTSPoint.Y) / m_pixelSize));//because the screen coordinate is downward rightward positive,so we need to translate the Y coordinate of the OTS system which is upward rightward positive.
  118. var screenPoint = new Point((int)(Convert.ToDouble(OTSPoint.X)/m_pixelSize), (int)(screenHeight));
  119. //var curP = new Point((int)(screenPoint.X + m_wholeBackRect.X), (int)(screenPoint.Y + m_wholeBackRect.Y));
  120. var curP = new Point((int)(screenPoint.X + m_originalBackRect.X), (int)(screenPoint.Y + m_originalBackRect.Y));
  121. return curP;
  122. }
  123. public SizeF GetPhysicalFieldWidthAndHeight()
  124. {
  125. SizeF ret_rect = new SizeF(0, 0);
  126. Dictionary<string, object> sampleMembers = ((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["Sample"])["Members"]);
  127. Dictionary<string, object> SEMDataMsr = (Dictionary<string, object>)sampleMembers["SEMDataMsr"];
  128. Dictionary<string, object> msrParams = (Dictionary<string, object>)sampleMembers["MsrParams"];
  129. Dictionary<string, object> imgParam = (Dictionary<string, object>)msrParams["Members"];
  130. Dictionary<string, object> scanParam = (Dictionary<string, object>)imgParam["ImageScanParam"];
  131. string resolution = scanParam["ImageResolution"].ToString();
  132. int width = Convert.ToInt32(resolution.Split('_')[1].ToString());
  133. int height = Convert.ToInt32(resolution.Split('_')[2].ToString());
  134. double retioOfHeightWidth =(double) height;
  135. retioOfHeightWidth /= width;
  136. string scanfeldsize = SEMDataMsr["ScanFieldSize"].ToString();
  137. double d_scanFieldSize_width = Convert.ToDouble(scanfeldsize);
  138. double d_scanFieldSize_height = 0;
  139. if (d_scanFieldSize_width != 0)
  140. d_scanFieldSize_height = d_scanFieldSize_width * retioOfHeightWidth;
  141. ret_rect.Width = (int)d_scanFieldSize_width;
  142. ret_rect.Height = (int)d_scanFieldSize_height;
  143. return ret_rect;
  144. }
  145. public SizeF GetFieldImageSize()
  146. {
  147. SizeF s = new SizeF();
  148. Dictionary<string, object> sampleMembers = ((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["Sample"])["Members"]);
  149. //Dictionary<string, object> SEMDataMsr = (Dictionary<string, object>)sampleMembers["SEMDataMsr"];
  150. Dictionary<string, object> msrParams= (Dictionary<string, object>)sampleMembers["MsrParams"];
  151. Dictionary<string, object> imgParam = (Dictionary<string, object>)msrParams["Members"];
  152. Dictionary<string, object> scanParam = (Dictionary<string, object>)imgParam["ImageScanParam"];
  153. string resolution = scanParam["ImageResolution"].ToString();
  154. int width = Convert.ToInt32(resolution.Split('_')[1].ToString());
  155. int height = Convert.ToInt32(resolution.Split('_')[2].ToString());
  156. s.Width = width;
  157. s.Height = height;
  158. return s;
  159. }
  160. #endregion
  161. #region 电镜操作相关方法
  162. /// <summary>
  163. /// 连接电镜,分布图使用
  164. /// </summary>
  165. public bool ConnectToIpcSvr()
  166. {
  167. //和电镜建立通讯连接
  168. return m_cfun.ConnectToIpcSvr();
  169. }
  170. /// <summary>
  171. /// 移动电镜到指定的X,Y坐标上,R坐标使用原先的值进行移动
  172. /// </summary>
  173. /// <param name="PositionX"></param>
  174. /// <param name="PositionY"></param>
  175. public void MoveSemToPointXY(double in_PositionX, double in_PositionY)
  176. {
  177. log.Trace("Begin MoveSemToPointXY:(" +in_PositionX.ToString()+","+in_PositionY.ToString()+")");
  178. //首先获取电镜当前的位置,并记录原R值
  179. double ls_PositionX = 0;
  180. double ls_PositionY = 0;
  181. double ls_PositionR = 0;
  182. if (m_cfun.ConnectToIpcSvr())
  183. {
  184. m_cfun.GetSemPositionXY(ref ls_PositionX, ref ls_PositionY, ref ls_PositionR);
  185. }
  186. else
  187. {
  188. log.Error("Failed to GetSemPositionXY");
  189. return;
  190. }
  191. if (m_cfun.ConnectToIpcSvr())
  192. {
  193. m_cfun.MoveSEMToPoint(new Point((int)in_PositionX, (int)in_PositionY), ls_PositionR);
  194. }
  195. }
  196. #endregion
  197. #region //--------------------------------------颗粒分布图相关部份---------------------------------------------------------------------
  198. /// <summary>
  199. /// 传入颗粒的tagid和fieldid,来获取该颗粒下对应的xray数据
  200. /// </summary>
  201. /// <param name="in_clr_tagid"></param>
  202. /// <param name="in_clr_fieldid"></param>
  203. /// <param name="Search_xray"></param>
  204. /// <param name="Analysis_xray"></param>
  205. public void GetXrayByParticleTagIDAndFieldID_ForDrawDistrbutionImageAndBSE(int in_clr_tagid, int in_clr_fieldid, out uint[] Search_xray, out uint[] Analysis_xray, out int xray_id, out List<Element> list_celementchemistryclr)
  206. {
  207. Search_xray = new uint[2000];
  208. Analysis_xray = new uint[2000];
  209. xray_id = 0;
  210. list_celementchemistryclr = new List<Element>();
  211. //防止为空校验判断
  212. if (resultFile.List_OTSField == null)
  213. return;
  214. Particle particle = resultFile.List_OTSField.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid);
  215. var tmpPart = new ParticleData(resultFile.FilePath).GetParticleXrayDataByFidAndPid(Convert.ToString(particle.FieldId), Convert.ToString(particle.XrayId));
  216. if (tmpPart != null)
  217. {
  218. particle.XRayData = tmpPart.XRayData;
  219. if (particle.XrayId > -1)
  220. {
  221. for (int i = 0; i < 2000; i++)
  222. {
  223. Analysis_xray[i] = BitConverter.ToUInt32(particle.XRayData, i * 4);
  224. }
  225. Search_xray = Analysis_xray;
  226. xray_id = particle.XrayId;
  227. list_celementchemistryclr = particle.ElementList;
  228. }
  229. }
  230. }
  231. /// <summary>
  232. /// 传入所有的物理field坐标点,和单个物理field的宽高,返回所有field的左上角位置,和整个field组成的rect大小
  233. /// </summary>
  234. /// <param name="in_list_point"></param>
  235. /// <param name="in_width"></param>
  236. /// <param name="in_height"></param>
  237. /// <returns></returns>
  238. public Rectangle GetWlRectTopLeftAndRect(List<Point> in_list_point, int in_width, int in_height)
  239. {
  240. //分别获取整个rect的xy最小值和最大值
  241. int i_rect_x_min = 100000000;
  242. int i_rect_y_min = 100000000;
  243. int i_rect_x_max = -100000000;
  244. int i_rect_y_max = -100000000;
  245. for (int i = 0; i < in_list_point.Count; i++)
  246. {
  247. if (i_rect_x_min > in_list_point[i].X)
  248. i_rect_x_min = in_list_point[i].X;
  249. if (i_rect_y_min > in_list_point[i].Y)
  250. i_rect_y_min = in_list_point[i].Y;
  251. if (i_rect_x_max < in_list_point[i].X)
  252. i_rect_x_max = in_list_point[i].X;
  253. if (i_rect_y_max < in_list_point[i].Y)
  254. i_rect_y_max = in_list_point[i].Y;
  255. }
  256. Rectangle ret_rect = new Rectangle(i_rect_x_min, i_rect_y_min,
  257. i_rect_x_max - i_rect_x_min, i_rect_y_max - i_rect_y_min);
  258. return ret_rect;
  259. }
  260. /// <summary>
  261. /// 根据Field的ID,来获取Field列表中对应FIeld的OTS 坐标
  262. /// </summary>
  263. /// <param name="in_fieldid"></param>
  264. /// <returns></returns>
  265. public Point GetOTSPointByFieldID(List<DisplayField> in_list_dfield, int in_fieldid)
  266. {
  267. Point ret_point = new Point(0, 0);
  268. for (int i = 0; i < in_list_dfield.Count; i++)
  269. {
  270. //这里TagID先代表的是底层返回的ID
  271. if (in_list_dfield[i].FieldID == in_fieldid.ToString())
  272. {
  273. ret_point = new Point(Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.X), Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.Y));
  274. }
  275. }
  276. return ret_point;
  277. }
  278. /// <summary>
  279. /// 将OTS坐标转换为Sem 坐标
  280. /// </summary>
  281. /// <param name="POTSCoord"></param>
  282. /// <returns></returns>
  283. public Point ChangeOTSToSemCoord(Point POTSCoord)
  284. {
  285. //first if m_semstagedata is null to get stage inforation
  286. Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  287. //after obtaining stage info,calc stage point data
  288. Point ret_SEM_point = new Point();
  289. // get center point, um
  290. long xStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["start"]);
  291. long xEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["end"]);
  292. long xCenter = (xStart + xEnd) / 2;
  293. long yStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["start"]);
  294. long yEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["end"]);
  295. long yCenter = (yStart + yEnd) / 2;
  296. // delte = SEM - OTSa
  297. long deltex = xCenter - 0;
  298. long deltey = yCenter - 0;
  299. int xdir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["xAxisDir"]);
  300. int ydir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["yAxisDir"]);
  301. if (xdir == (int)OTS_X_AXIS_DIRECTION.LEFT_TOWARD)
  302. {
  303. ret_SEM_point.X = -1 * (POTSCoord.X - Convert.ToInt32(deltex));
  304. }
  305. else if (xdir == (int)OTS_X_AXIS_DIRECTION.RIGHT_TOWARD)
  306. {
  307. ret_SEM_point.X = POTSCoord.X + Convert.ToInt32(deltex);
  308. }
  309. if (ydir == (int)OTS_Y_AXIS_DIRECTION.UP_TOWARD)
  310. {
  311. ret_SEM_point.Y = POTSCoord.Y + Convert.ToInt32(deltey);
  312. }
  313. else if (ydir == (int)OTS_Y_AXIS_DIRECTION.DOWN_TOWARD)
  314. {
  315. ret_SEM_point.Y = -1 * (POTSCoord.Y - Convert.ToInt32(deltey));
  316. }
  317. return ret_SEM_point;
  318. }
  319. #endregion
  320. /// <summary>
  321. /// 判断该点是否在多边形的范围内
  322. /// </summary>
  323. /// <param name="inPoints"></param>
  324. /// <param name="WhetherPoint"></param>
  325. /// <returns></returns>
  326. public bool WhetherInRange(DisplayParticle Part, Point WhetherPoint)
  327. {
  328. var rect = Part.GetShowRect();
  329. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  330. {
  331. var itm = Part;
  332. PointF[] inPoints = itm.GetGPath().PathPoints;
  333. bool b_inrange;
  334. GraphicsPath myGraphicsPath = new GraphicsPath();
  335. Region myRegion = new Region();
  336. myGraphicsPath.Reset();
  337. myGraphicsPath.AddPolygon(inPoints);
  338. myRegion.MakeEmpty();
  339. myRegion.Union(myGraphicsPath);
  340. //返回判断点是否在多边形里
  341. b_inrange = myRegion.IsVisible(WhetherPoint);
  342. return b_inrange;
  343. }
  344. else
  345. {
  346. return false;
  347. }
  348. }
  349. public bool WhetherInRange(RectangleF rec,PointF[] inPoints, Point WhetherPoint)
  350. {
  351. var rect = rec;
  352. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  353. {
  354. bool b_inrange;
  355. GraphicsPath myGraphicsPath = new GraphicsPath();
  356. Region myRegion = new Region();
  357. myGraphicsPath.Reset();
  358. myGraphicsPath.AddPolygon(inPoints);
  359. myRegion.MakeEmpty();
  360. myRegion.Union(myGraphicsPath);
  361. //返回判断点是否在多边形里
  362. b_inrange = myRegion.IsVisible(WhetherPoint);
  363. return b_inrange;
  364. }
  365. else
  366. {
  367. return false;
  368. }
  369. }
  370. /// <summary>
  371. /// 判断该点是否在多边形的范围内的float版本重载
  372. /// </summary>
  373. /// <param name="inPoints"></param>
  374. /// <param name="WhetherPoint"></param>
  375. /// <returns></returns>
  376. public bool WhetherInRange(DisplayParticle Part,PointF WhetherPoint)
  377. {
  378. var rect = Part.GetShowRect();
  379. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  380. {
  381. var itm = Part;
  382. PointF[] inPoints = itm.GetGPath().PathPoints;
  383. bool b_inrange ;
  384. GraphicsPath myGraphicsPath = new GraphicsPath();
  385. Region myRegion = new Region();
  386. myGraphicsPath.Reset();
  387. myGraphicsPath.AddPolygon(inPoints);
  388. myRegion.MakeEmpty();
  389. myRegion.Union(myGraphicsPath);
  390. //返回判断点是否在多边形里
  391. b_inrange = myRegion.IsVisible(WhetherPoint);
  392. return b_inrange;
  393. }
  394. else
  395. {
  396. return false;
  397. }
  398. }
  399. #region 颗粒分割功能方法
  400. /// <summary>
  401. /// 获取线段与矩形的两个交点
  402. /// </summary>
  403. /// <param name="line1S"></param>
  404. /// <param name="line1E"></param>
  405. /// <param name="rectangle"></param>
  406. /// <param name="pointList"></param>
  407. /// <returns></returns>
  408. public bool GetInterBetweenLinesAndRect(Point line1S, Point line1E, RectangleF rectangle, ref List<Point> pointList)
  409. {
  410. try
  411. {
  412. PointF pointF = new PointF(-1, -1);
  413. Rect rect = new Rect();
  414. rect.X = m_ParticleSegmentation.ParticleData.RectLeft;
  415. rect.Y = m_ParticleSegmentation.ParticleData.RectTop;
  416. rect.Width = m_ParticleSegmentation.ParticleData.RectWidth;
  417. rect.Height = m_ParticleSegmentation.ParticleData.RectHeight;
  418. float border = 0;
  419. if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Right, rectangle.Top), ref pointF))
  420. {
  421. border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left);
  422. pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y));
  423. }
  424. if (GetInterBetweenTwoLines(line1S, line1E,
  425. new PointF(rectangle.Left, rectangle.Bottom), new PointF(rectangle.Right, rectangle.Bottom), ref pointF))
  426. {
  427. border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left);
  428. pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y + rect.Height));
  429. }
  430. if (GetInterBetweenTwoLines(line1S, line1E,
  431. new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Left, rectangle.Bottom), ref pointF))
  432. {
  433. border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top);
  434. pointList.Add(new Point(rect.X, (int)(rect.Y + rect.Height * border)));
  435. }
  436. if (GetInterBetweenTwoLines(line1S, line1E,
  437. new PointF(rectangle.Right, rectangle.Top), new PointF(rectangle.Right, rectangle.Bottom), ref pointF))
  438. {
  439. border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top);
  440. pointList.Add(new Point(rect.X + rect.Width, (int)(rect.Y + rect.Height * border)));
  441. }
  442. if (pointList.Count == 2)
  443. {
  444. return true;
  445. }
  446. else
  447. {
  448. return false;
  449. }
  450. }
  451. catch (Exception ex)
  452. {
  453. log.Trace("(GetSplitPartFun)" + ex);
  454. return false;
  455. }
  456. }
  457. /// <summary>
  458. /// 获取分离颗粒方法
  459. /// </summary>
  460. /// <param name="startPoint"></param>
  461. /// <param name="endPoint"></param>
  462. /// <returns></returns>
  463. public bool GetSplitPartFun(Point startPoint, Point endPoint)
  464. {
  465. try
  466. {
  467. CImageHandler m_ImagePro = new CImageHandler();
  468. Particle particle1 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData);
  469. Particle particle2 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData);
  470. Dictionary<string, object> sampleMembers = ((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["Sample"])["Members"]);
  471. Dictionary<string, object> imageScanParam = (Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)sampleMembers["MsrParams"])["Members"])["ImageScanParam"];
  472. double d_scanFieldSize_width = Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  473. string ImageResolution = imageScanParam["ImageResolution"].ToString();
  474. int width = int.Parse(ImageResolution.Split('_')[1]);
  475. int height = int.Parse(ImageResolution.Split('_')[2]);
  476. double dPixelSize = d_scanFieldSize_width / width;
  477. using (Mat mat = new Mat(height, width, MatType.CV_8UC1, Scalar.Black))//黑色底图
  478. using (Mat labelMat = new Mat())
  479. using (Mat stats = new Mat())
  480. using (Mat centroids = new Mat())
  481. using (Mat matBse = new Mat(resultFile.List_OTSField[particle1.FieldId].FieldImage, ImreadModes.Grayscale))
  482. {
  483. foreach (Segment segment in m_ParticleSegmentation.ParticleData.SegmentList)
  484. {
  485. Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias);
  486. }
  487. //寻找坐标点
  488. List<Point> points1 = new List<Point>();
  489. List<Point> points2 = new List<Point>();
  490. List<int> aveGray1 = new List<int>();
  491. List<int> aveGray2 = new List<int>();
  492. for (int k = 0; k < mat.Height; k++)
  493. {
  494. for (int j = 0; j < mat.Width; j++)
  495. {
  496. if (mat.Get<int>(k, j) != 0)
  497. {
  498. int side = (startPoint.X - j) * (endPoint.Y - k) - (startPoint.Y - k) * (endPoint.X - j);
  499. if (side >= 0)//区分像素位置
  500. {
  501. points1.Add(new Point(j, k));
  502. aveGray1.Add(matBse.Get<byte>(k, j));
  503. }
  504. else
  505. {
  506. points2.Add(new Point(j, k));
  507. aveGray2.Add(matBse.Get<byte>(k, j));
  508. }
  509. }
  510. }
  511. }
  512. //处理Segment
  513. List<COTSSegmentClr> SegmentClrList1 = new List<COTSSegmentClr>();
  514. List<COTSSegmentClr> SegmentClrList2 = new List<COTSSegmentClr>();
  515. List<Segment> SegmentList1 = new List<Segment>();
  516. List<Segment> SegmentList2 = new List<Segment>();
  517. GetSegment(points1, SegmentClrList1, ref SegmentList1);
  518. GetSegment(points2, SegmentClrList2, ref SegmentList2);
  519. //颗粒一
  520. Cv2.Threshold(mat, mat, 0, 0, ThresholdTypes.Binary);
  521. foreach (Segment segment in SegmentList1)
  522. {
  523. Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias);
  524. }
  525. Cv2.ConnectedComponentsWithStats(mat, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
  526. CopyToPart(particle1, SegmentList1, SegmentClrList1, aveGray1, stats, centroids, dPixelSize);
  527. //颗粒二
  528. Cv2.Threshold(mat, mat, 0, 0, ThresholdTypes.Binary);
  529. foreach (Segment segment in SegmentList2)
  530. {
  531. Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias);
  532. }
  533. Cv2.ConnectedComponentsWithStats(mat, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
  534. CopyToPart(particle2, SegmentList2, SegmentClrList2, aveGray2, stats, centroids, dPixelSize);
  535. if (!SaveToDb(particle1, particle2))
  536. {
  537. log.Trace("(GetSplitPartFun) SaveToDb Faild");
  538. return false;
  539. }
  540. }
  541. return true;
  542. }
  543. catch (Exception ex)
  544. {
  545. log.Trace("(GetSplitPartFun)" + ex);
  546. return false;
  547. }
  548. }
  549. /// <summary>
  550. /// 拷贝颗粒数据
  551. /// </summary>
  552. /// <param name="particle"></param>
  553. /// <param name="segments"></param>
  554. /// <param name="SegmentClrList"></param>
  555. /// <param name="aveGray"></param>
  556. /// <param name="stats"></param>
  557. /// <param name="centroids"></param>
  558. /// <param name="dPixelSize"></param>
  559. private void CopyToPart(Particle particle, List<Segment> segments, List<COTSSegmentClr> SegmentClrList, List<int> aveGray, Mat stats, Mat centroids, double dPixelSize)
  560. {
  561. CImageHandler m_ImagePro = new CImageHandler();
  562. COTSParticleClr part = new COTSParticleClr();
  563. part.SetActualArea(stats.At<int>(1, 4) * dPixelSize * dPixelSize);
  564. part.SetParticleRect(new Rectangle(stats.At<int>(1, 0), stats.At<int>(1, 1), stats.At<int>(1, 2), stats.At<int>(1, 3)));
  565. part.GetFeature().SetSegmentsList(SegmentClrList, false);
  566. m_ImagePro.CalParticleImageProp(part, dPixelSize);
  567. particle.SegmentList = segments;
  568. particle.SegmentNum = segments.Count;
  569. particle.AveGray = (int)aveGray.Average();
  570. particle.RectLeft = stats.At<int>(1, 0);
  571. particle.RectTop = stats.At<int>(1, 1);
  572. particle.RectWidth = stats.At<int>(1, 2);
  573. particle.RectHeight = stats.At<int>(1, 3);
  574. particle.Area = stats.At<int>(1, 4) * dPixelSize * dPixelSize;
  575. particle.PosX = (int)centroids.At<double>(1, 0);
  576. particle.PosY = (int)centroids.At<double>(1, 1);
  577. particle.DFERET = part.GetFeretDiameter();
  578. particle.DMAX = part.GetDMAX();
  579. particle.DMIN = part.GetDMIN();
  580. particle.DPERP = part.GetDMPERP();
  581. particle.PERIMETER = part.GetDPRIMETER();
  582. particle.ORIENTATION = part.GetORIENTATION();
  583. particle.DINSCR = part.GetDINSCR();
  584. particle.DMEAN = part.GetDMEAN();
  585. particle.DELONG = part.GetDELONG();
  586. }
  587. /// <summary>
  588. /// 保存数据库
  589. /// </summary>
  590. /// <param name="particle1"></param>
  591. /// <param name="particle2"></param>
  592. /// <returns></returns>
  593. public bool SaveToDb(Particle particle1, Particle particle2)
  594. {
  595. //初始化
  596. SQLiteHelper sQLiteHelper = new SQLiteHelper(resultFile.FilePath + "\\FIELD_FILES\\Inclusion.db");
  597. sQLiteHelper.GetDBConnection();
  598. sQLiteHelper.BeginTransaction();
  599. //修改Segment表
  600. if (particle1.SegmentList.Count == 0 || particle2.SegmentList.Count == 0)
  601. {
  602. return false;
  603. }
  604. int SegmentCount = sQLiteHelper.ExecuteNewPartIdForTransaction() + 1;
  605. if (!sQLiteHelper.ExecuteSegmentForTransaction(particle1, particle2, SegmentCount))//修改Segment表
  606. {
  607. return false;
  608. }
  609. if (!sQLiteHelper.ExecuteXrayForTransaction(particle1, particle2, SegmentCount))//修改XRayData和PoxXrayInfo表
  610. {
  611. return false;
  612. }
  613. if (!sQLiteHelper.ExecuteIncAForTransaction(particle1, particle2, SegmentCount))//修改IncAData表
  614. {
  615. return false;
  616. }
  617. sQLiteHelper.CommitTransaction();
  618. return true;
  619. }
  620. /// <summary>
  621. /// 线段与矩形是否相交
  622. /// </summary>
  623. /// <param name="linePointX1"></param>
  624. /// <param name="linePointY1"></param>
  625. /// <param name="linePointX2"></param>
  626. /// <param name="linePointY2"></param>
  627. /// <param name="rectangleLeftTopX"></param>
  628. /// <param name="rectangleLeftTopY"></param>
  629. /// <param name="rectangleRightBottomX"></param>
  630. /// <param name="rectangleRightBottomY"></param>
  631. /// <returns></returns>
  632. public bool isLineIntersectRectangle(float linePointX1,
  633. float linePointY1,
  634. float linePointX2,
  635. float linePointY2,
  636. float rectangleLeftTopX,
  637. float rectangleLeftTopY,
  638. float rectangleRightBottomX,
  639. float rectangleRightBottomY)
  640. {
  641. float lineHeight = linePointY1 - linePointY2;
  642. float lineWidth = linePointX2 - linePointX1; // 计算叉乘
  643. float c = linePointX1 * linePointY2 - linePointX2 * linePointY1;
  644. if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0)
  645. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0)
  646. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0)
  647. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0))
  648. {
  649. if (rectangleLeftTopX > rectangleRightBottomX)
  650. {
  651. float temp = rectangleLeftTopX;
  652. rectangleLeftTopX = rectangleRightBottomX;
  653. rectangleRightBottomX = temp;
  654. }
  655. if (rectangleLeftTopY < rectangleRightBottomY)
  656. {
  657. float temp1 = rectangleLeftTopY;
  658. rectangleLeftTopY = rectangleRightBottomY;
  659. rectangleRightBottomY = temp1;
  660. }
  661. if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX)
  662. || (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX)
  663. || (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY)
  664. || (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY))
  665. {
  666. return false;
  667. }
  668. else
  669. {
  670. return true;
  671. }
  672. }
  673. else
  674. {
  675. return false;
  676. }
  677. }
  678. /// <summary>
  679. /// 求一个线段与另一个线段的交点
  680. /// </summary>
  681. /// <param name="line1S"></param>
  682. /// <param name="line1E"></param>
  683. /// <param name="line2S"></param>
  684. /// <param name="line2E"></param>
  685. /// <param name="interPoint"></param>
  686. /// <returns>-1:不存在交点;1:存在一个交点;2:存在无穷多个交点(重合或部分重合)</returns>
  687. public bool GetInterBetweenTwoLines(PointF line1S, PointF line1E,
  688. PointF line2S, PointF line2E, ref PointF interPoint)
  689. {
  690. int status = -1;
  691. // 判断两条直线各自的矩形包围盒的X与Y的值范围
  692. float line1Xmin = line1S.X < line1E.X ? line1S.X : line1E.X,
  693. line1Xmax = line1S.X > line1E.X ? line1S.X : line1E.X,
  694. line1Ymin = line1S.Y < line1E.Y ? line1S.Y : line1E.Y,
  695. line1Ymax = line1S.Y > line1E.Y ? line1S.Y : line1E.Y,
  696. line2Xmin = line2S.X < line2E.X ? line2S.X : line2E.X,
  697. line2Xmax = line2S.X > line2E.X ? line2S.X : line2E.X,
  698. line2Ymin = line2S.Y < line2E.Y ? line2S.Y : line2E.Y,
  699. line2Ymax = line2S.Y > line2E.Y ? line2S.Y : line2E.Y;
  700. if (line1S.X - line1E.X == 0)
  701. {
  702. // 两条线都垂直于X轴
  703. if (line2S.X - line2E.X == 0)
  704. {
  705. if (line1S.X != line2S.X) status = -1;
  706. else if ((line1Ymin > line2Ymax) || (line1Ymax < line2Ymin)) status = -1;
  707. else if (line1Ymin == line2Ymax)
  708. {
  709. interPoint = new PointF(line1S.X, line1Ymin); status = 1;
  710. }
  711. else if (line1Ymax == line2Ymin)
  712. {
  713. interPoint = new PointF(line1S.X, line1Ymax); status = 1;
  714. }
  715. else status = 2;
  716. }
  717. // line1垂直于X轴,line2不垂直于X轴
  718. else
  719. {
  720. float slope = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
  721. float offset = line2S.Y - slope * line2S.X;
  722. float newX = line1S.X, newY = slope * newX + offset;
  723. if (newX >= line2Xmin && newX <= line2Xmax && newY >= line1Ymin && newY <= line1Ymax
  724. && newY >= line2Ymin && newY <= line2Ymax)
  725. {
  726. interPoint = new PointF(newX, newY); status = 1;
  727. }
  728. }
  729. }
  730. else
  731. {
  732. // line1不垂直于X轴,line2垂直于X轴
  733. if (line2S.X - line2E.X == 0)
  734. {
  735. float slope = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
  736. float offset = line1S.Y - slope * line1S.X;
  737. float newX = line2S.X, newY = slope * newX + offset;
  738. if (newX >= line1Xmin && newX <= line1Xmax && newY >= line1Ymin && newY <= line1Ymax
  739. && newY >= line2Ymin && newY <= line2Ymax)
  740. {
  741. interPoint = new PointF(newX, newY); status = 1;
  742. }
  743. }
  744. // line1和line2都不垂直于X轴
  745. else
  746. {
  747. float slope1 = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
  748. float offset1 = line1S.Y - slope1 * line1S.X;
  749. float slope2 = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
  750. float offset2 = line2S.Y - slope2 * line2S.X;
  751. // 如果两条直线平行
  752. if (slope1 == slope2)
  753. {
  754. if (offset1 != offset2) status = -1;
  755. else if (line1Xmax == line2Xmin)
  756. {
  757. interPoint = new PointF(line1Xmax, line1Xmax * slope1 + offset1); status = 1;
  758. }
  759. else if (line1Xmin == line2Xmax)
  760. {
  761. interPoint = new PointF(line1Xmin, line1Xmin * slope1 + offset1); status = 1;
  762. }
  763. else if (line1Xmax < line2Xmin || line1Xmin > line2Xmax) status = -1;
  764. else status = 2;
  765. }
  766. else
  767. {
  768. float newX = (offset2 - offset1) / (slope1 - slope2), newY = newX * slope1 + offset1;
  769. if (newX >= line1Xmin && newX <= line1Xmax && newX >= line2Xmin && newX <= line2Xmax)
  770. {
  771. interPoint = new PointF(newX, newY); status = 1;
  772. }
  773. }
  774. }
  775. }
  776. if (status == 1)
  777. {
  778. return true;
  779. }
  780. else
  781. {
  782. return false;
  783. }
  784. }
  785. /// <summary>
  786. /// 获取Segment信息
  787. /// </summary>
  788. /// <param name="points"></param>
  789. /// <param name="SegmentClrList"></param>
  790. /// <param name="SegmentList"></param>
  791. public void GetSegment(List<Point> points, List<COTSSegmentClr> SegmentClrList, ref List<Segment> SegmentList)
  792. {
  793. List<int> segmentStart = new List<int>();
  794. List<int> segmentHeight = new List<int>();
  795. List<int> segmentLength = new List<int>();
  796. FindSegment(points, ref segmentStart, ref segmentHeight, ref segmentLength);
  797. for (int i = 0; i < segmentLength.Count; i++)
  798. {
  799. COTSSegmentClr seg = new COTSSegmentClr();
  800. seg.SetStart(segmentStart[i]);
  801. seg.SetHeight(segmentHeight[i]);
  802. seg.SetLength(segmentLength[i]);
  803. SegmentClrList.Add(seg);
  804. Segment segment = new Segment();
  805. segment.Start = segmentStart[i];
  806. segment.Height = segmentHeight[i];
  807. segment.Length = segmentLength[i];
  808. segment.SegmentNum = segmentLength.Count;
  809. segment.SegmentId = i;
  810. segment.FieldId = m_ParticleSegmentation.ParticleData.FieldId;
  811. segment.XRayId = m_ParticleSegmentation.ParticleData.XrayId;
  812. segment.ParticleId = m_ParticleSegmentation.ParticleData.ParticleId;
  813. SegmentList.Add(segment);
  814. }
  815. }
  816. /// <summary>
  817. /// 寻找segment方法
  818. /// </summary>
  819. public void FindSegment(List<Point> point_list_final, ref List<int> segmentStart, ref List<int> segmentHeight, ref List<int> segmentLength)
  820. {
  821. int flag = 0;
  822. point_list_final.Sort(my_sort);//排序
  823. for (int k = 0; k < point_list_final.Count(); k++)
  824. {
  825. if (k == 0 && k != point_list_final.Count() - 1)//第一个颗粒
  826. {
  827. flag++;
  828. segmentStart.Add(point_list_final[k].X);
  829. segmentHeight.Add(point_list_final[k].Y);
  830. }
  831. else if (k == 0 && k == point_list_final.Count() - 1)//只有一个颗粒
  832. {
  833. segmentStart.Add(point_list_final[k].X);
  834. segmentHeight.Add(point_list_final[k].Y);
  835. segmentLength.Add(1);
  836. }
  837. else if (k == point_list_final.Count() - 1)//最后一个颗粒
  838. {
  839. flag++;
  840. segmentLength.Add(flag);
  841. }
  842. else if (point_list_final[k].Y == point_list_final[k - 1].Y && point_list_final[k].X == point_list_final[k - 1].X + 1)//同行连续
  843. {
  844. flag++;
  845. }
  846. else if (point_list_final[k].Y == point_list_final[k - 1].Y && point_list_final[k].X != point_list_final[k - 1].X + 1)//同行隔断
  847. {
  848. segmentLength.Add(flag);
  849. flag = 1;
  850. segmentStart.Add(point_list_final[k].X);
  851. segmentHeight.Add(point_list_final[k].Y);
  852. }
  853. else if (point_list_final[k].Y != point_list_final[k - 1].Y)//不同行
  854. {
  855. segmentLength.Add(flag);
  856. flag = 1;
  857. segmentStart.Add(point_list_final[k].X);
  858. segmentHeight.Add(point_list_final[k].Y);
  859. }
  860. }
  861. }
  862. /// <summary>
  863. /// 排序方法
  864. /// </summary>
  865. /// <param name="p1"></param>
  866. /// <param name="p2"></param>
  867. /// <returns></returns>
  868. private int my_sort(Point p1, Point p2)
  869. {
  870. return p1.Y == p2.Y ? p1.X.CompareTo(p2.X) : p1.Y.CompareTo(p2.Y); //升序排序
  871. }
  872. public object CloneObject(object obj)
  873. {
  874. using (MemoryStream stream = new MemoryStream())
  875. {
  876. BinaryFormatter formatter = new BinaryFormatter();
  877. stream.Position = 0;
  878. formatter.Serialize(stream, obj);
  879. stream.Position = 0;
  880. return formatter.Deserialize(stream);
  881. }
  882. }
  883. #endregion
  884. }
  885. }