using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using OTSModelSharp.ImageProcess; using OTSModelSharp.ServiceCenter; using OTSDataType; using OTSCLRINTERFACE; using System.Xml; using OTSMeasureApp._0_OTSModel.OTSDataType; using OTSModelSharp; namespace OTSDataType { using COTSFieldDataList = List; public class COTSField:ISlo { public COTSField leftField=null; public COTSField upField=null; public COTSField downField=null; public COTSField rightField=null; protected NLog.Logger log ; // ID int m_nID; int measureSequence; // position (from field center manager) protected System.Drawing.PointF m_otsPos ; protected CBSEImgClr m_pBSEImg; protected double m_pixelSize; protected CImageHandler m_ImagePro; protected List m_listAllParticles = new List();//hold up all the particles abstracted from bse image; protected List m_listAnalysisParticles = new List();// according to xraylimit constraint,pick out the first big particles. protected List m_listXrayParticles = new List();//hold up all the particles that needing the xray data. private int imgheight; private int imgwidth; private COTSRect m_otsRect; private COTSSample m_sample; public COTSField() { log = NLog.LogManager.GetCurrentClassLogger(); Init(); }//only using in xmlserialization public int ImgHeight { get => imgheight; set => imgheight = value; } public int ImgWidth { get => imgwidth; set => imgwidth = value; } public COTSSample Sample { get => m_sample; set => m_sample = value; } internal COTSRect GetOTSRect() { return m_otsRect; } internal void SetOTSRect(COTSRect value) { m_otsRect = value; } public int GetMeasureSequence() { return measureSequence; } public void SetMeasureSequence(int value) { measureSequence = value; } public List strKeyName; public bool GetIsMeasureComplete() { return isMeasureComplete; } public void SetIsMeasureComplete(bool value) { isMeasureComplete = value; } private bool isMeasureComplete; public PointF GetSemPos() { return m_semPos; } public void SetSemPos(PointF value) { m_semPos = value; } private PointF m_semPos; public List GetAllParticles() { return m_listAllParticles; } public List GetListAnalysisParticles() { return m_listAnalysisParticles; } public List GetListXrayParticles() { m_listXrayParticles.Clear(); foreach (var p in m_listAnalysisParticles) { if (p.IsXrayParticle()) { m_listXrayParticles.Add(p); } } return m_listXrayParticles; } public void SetListAnalysisParticles(List value) { m_listAnalysisParticles = value; } public COTSField(PointF centerPoint, double a_dPixelSize) { log = NLog.LogManager.GetCurrentClassLogger(); Init(); //m_pBSEImg = a_pBSEImg; m_otsPos = centerPoint; m_pixelSize = a_dPixelSize; } public double GetPixelSize() { return m_pixelSize; } public void SetPixelSize(double size) { m_pixelSize = size; } // initialization void Init() { // initialization m_nID = -1; m_otsPos =new System.Drawing.Point(0, 0); m_listAllParticles.Clear(); } public COTSField(COTSField a_poSource) { // can't copy itself if (a_poSource == this) { return; } Duplicate(a_poSource); } public CBSEImgClr GetBSEImage() { return m_pBSEImg; } public void SetBSEImage(CBSEImgClr a_pBSEImg) { if (a_pBSEImg == null) { // invalid BSE image. log.Error("SetBSEImage: invalid BSE image."); return; } m_pBSEImg = a_pBSEImg; imgwidth = a_pBSEImg.GetWidth(); imgheight = a_pBSEImg.GetHeight(); } public void RemoveImgBGAndGetParticles(COTSImageProcParam a_pImageProcessParam,double a_pixelSize,bool ifXray) { if (m_pBSEImg == null) return; CImageHandler imghandler = new CImageHandler(); List allParts = new List(); imghandler.RemoveBGAndGetParts(this, a_pImageProcessParam, ref allParts); foreach (var p in allParts) { p.SetIsXrayParticle(ifXray); m_listAllParticles.Add(p); } return ; } public void RemoveDuplicateOverlapParticles(int overlap) { List finalparts = new List(); if (leftField != null && leftField.measureSequence < this.measureSequence) { var leftparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); log.Info("left side particles num:" + leftparts.Count.ToString()); foreach (var p in leftparts ) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); bool findsimilar = false; var rightsideparts = leftField.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); foreach (var p1 in rightsideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if ( sim> 0.95) { log.Warn("remove left side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); findsimilar = true; break; } } } if (findsimilar == false) { if (!finalparts.Contains(p))//particles in the four corner are processed more than one time { finalparts.Add(p); } } } } else { foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap)) { finalparts.Add(p); } } if (upField != null && upField.measureSequence < this.measureSequence) { var upparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.UP, overlap); log.Info("up side particles num:" + upparts.Count.ToString()); foreach (var p in upparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); bool findsimilar = false; var othersideparts = upField.GetSideParticlesByOverlap(SORTING_DIRECTION.DOWN, overlap); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove upside duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); findsimilar = true; break; } } } if (findsimilar == false) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } } else { foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.UP, overlap)) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } if (rightField != null && rightField.measureSequence < this.measureSequence) { var rightparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); log.Info("right side particles num:" + rightparts.Count.ToString()); foreach (var p in rightparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); bool findsimilar = false; var othersideparts = rightField.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove right side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); findsimilar = true; break; } } } if (findsimilar == false) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } } else { foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap)) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } if (downField != null && downField.measureSequence < this.measureSequence) { var downparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.DOWN, overlap); log.Info("down side particles num:" + downparts.Count.ToString()); foreach (var p in downparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); bool findsimilar = false; var othersideparts = downField.GetSideParticlesByOverlap(SORTING_DIRECTION.UP, overlap); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove down side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); findsimilar = true; break; } } } if (findsimilar == false) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } } else { foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.DOWN, overlap)) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } } foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.CENTER, overlap)) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } this.SetListAnalysisParticles(finalparts); log.Info("removing duplicate particles result:" + finalparts.Count); } private List GetSideParticlesByOverlap(SORTING_DIRECTION direction,int overlap) { List sideparts = new List(); if (direction == SORTING_DIRECTION.LEFT) { var leftborderParts = this.GetLeftBorderedParticles(); foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if ((right - this.GetOTSRect().GetTopLeft().X) < 2 * overlap) { if (!leftborderParts.Contains(p) || Math.Abs(left-right)>2*overlap )//not on the border or it's a big particle { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.RIGHT) { var rightborderParts = this.GetRightBorderedParticles(); foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if ((this.GetOTSRect().GetBottomRight().X-left) < 2 * overlap) { if (!rightborderParts.Contains(p)|| Math.Abs(left - right) > 2 * overlap)//not on the border or is a big part { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.UP) { var upborderParts = this.GetTopBorderedParticles(); foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if ((this.GetOTSRect().GetTopLeft().Y - bottom) < 2 * overlap) { if (!upborderParts.Contains(p) || Math.Abs(top - bottom) > 2 * overlap)//not on the border { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.DOWN) { var downborderParts = this.GetBottomBorderedParticles(); foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if ((top-this.GetOTSRect().GetBottomRight().Y ) < 2 * overlap) { if (!downborderParts.Contains(p)|| Math.Abs(top - bottom) > 2 * overlap)//not on the border { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.CENTER) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); var fldrec = this.GetOTSRect(); int fldleft = (int)fldrec.GetTopLeft().X; int fldright = (int)fldrec.GetBottomRight().X; int fldtop = (int)fldrec.GetTopLeft().Y; int fldbottom = (int)fldrec.GetBottomRight().Y; if ((Math.Abs(top - fldtop) > 2 * overlap) && (Math.Abs(fldbottom-bottom)>2*overlap) && (Math.Abs(left-fldleft)>2*overlap) && (Math.Abs(fldright-right)>2*overlap)) { sideparts.Add(p); } } } return sideparts; } public void GetPartsBySpecialGray(CIntRangeClr grayRange, CDoubleRangeClr diameterRange,double pixelSize, bool ifXray) { if (m_pBSEImg == null) return; CImageHandler imghandler = new CImageHandler(); List specialParts = new List(); imghandler.GetParticlesBySpecialGray(m_pBSEImg, grayRange,diameterRange,pixelSize, ref specialParts); foreach (var p in specialParts) { p.SetIsXrayParticle(ifXray); m_listAllParticles.Add(p); } return; } public bool CalParticleImageProp(List particles) { m_ImagePro = new CImageHandler(); foreach (COTSParticleClr part in particles) { m_ImagePro.CalParticleImageProp( part, m_pixelSize); } return true; } public void InitParticles(COTSImageProcParam a_pImageProcessParam) { // get area range CDoubleRange oAreaRange = a_pImageProcessParam.GetIncAreaRange(); double rMin = oAreaRange.GetStart() / 2.0; double rMax = oAreaRange.GetEnd() / 2.0; int nTagId = 0; foreach (COTSParticleClr pParticle in m_listAnalysisParticles)//m_listAllParticles memorize all the particles . { pParticle.SetParticleId(nTagId);//give all the conforming particles a unified sequence no. pParticle.SetFieldId(GetId()); pParticle.SetType((int)otsdataconst.OTS_PARTICLE_TYPE.NO_ANALYSIS_X_RAY); pParticle.SetTypeName("Not Identified"); pParticle.SetAnalysisId(nTagId); // the same as the tagId no use now. nTagId++; } log.Info("Total analysis Particles: (>" + rMin.ToString("f2") + "): "+ "<" + rMax.ToString("f2") + "): " + m_listAnalysisParticles.Count); } public bool CreateXrayList(List a_listParticles) { foreach (COTSParticleClr pPart in a_listParticles) { System.Drawing.Point poi = (System.Drawing.Point)pPart.GetXRayPos(); CPosXrayClr pPosXray = new CPosXrayClr(); pPosXray.SetPosition(poi); pPosXray.SetPartTagId(pPart.GetParticleId()); pPosXray.SetIndex(pPart.GetAnalysisId()); pPosXray.SetScanFieldId(pPart.GetFieldId()); pPart.SetXray(pPosXray); } return true; } public bool NoParticle() { if (m_listAllParticles.Count == 0) { return true; } else { return false; } } public bool NoAnalysisParticle() { if (m_listAllParticles.Count == 0) { return true; } else { return false; } } public bool PositionEquals(COTSField a_oSource) { if (a_oSource.m_otsPos == this.m_otsPos) { return true; } else { return false; } } // ID public int GetId() { return m_nID; } public void SetId(int a_nID) { m_nID = a_nID; } // position (from field center manager) public System.Drawing.PointF GetOTSPosition() { return m_otsPos; } public void SetOTSPosition(System.Drawing.PointF a_poiPos) { m_otsPos = a_poiPos; } public List GetTopBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList();//COTSSegment foreach (var seg in segs) { if (seg.GetHeight() == 0) { parts.Add(p); break; } } } return parts; } public List< COTSParticleClr > GetBottomBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetHeight() == this.ImgHeight - 1)//the lowest height is 767(height-1),cause starting from 0. { parts.Add(p); break; } } } return parts; } public List GetLeftBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetStart() == 0) { parts.Add(p); break; } } } return parts; } public List GetRightBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetStart() + seg.GetLength() == this.ImgWidth) { parts.Add(p); break; } } } return parts; } // is empty public bool IsEmpty() { return m_listAllParticles.Count == 0; } void Duplicate( COTSField a_oSource) { m_nID = a_oSource.m_nID; m_otsPos = a_oSource.m_otsPos; // copy data over foreach(var pParticle in a_oSource.m_listAllParticles) { m_listAllParticles.Add(pParticle); } } public override void Serialize(bool isStoring, XmlDocument classDoc, XmlNode rootNode) { xPoint xPos = new xPoint(); Slo slo = new Slo(); slo.Register("OTSPosition", xPos); if (isStoring) { xPos.AssignValue(new System.Drawing.Point((int)m_otsPos.X,(int)m_otsPos.Y)); slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_otsPos = xPos.value(); } } } }