OTSImageDisHelp.cs 41 KB

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