OTSImageDisHelp.cs 41 KB

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