OTSImageDisHelp.cs 37 KB

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