OTSImageDisHelp.cs 38 KB

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