|
|
@@ -1,19 +1,24 @@
|
|
|
-using System;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.Linq;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-using OTSModelSharp.ServiceCenter;
|
|
|
-using static OTSDataType.otsdataconst;
|
|
|
+using Microsoft.Office.Interop.Excel;
|
|
|
+using OpenCvSharp;
|
|
|
+using OpenCvSharp.Extensions;
|
|
|
+using OTSAlgrithm;
|
|
|
+using OTSAlgrithm.AI;
|
|
|
+using OTSCLRINTERFACE;
|
|
|
+using OTSCommon.DBOperate.Model;
|
|
|
using OTSDataType;
|
|
|
-
|
|
|
+using OTSMeasureApp._0_OTSModel.OTSDataType;
|
|
|
+using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow;
|
|
|
+using OTSModelSharp.ServiceCenter;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Data;
|
|
|
using System.Drawing;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
|
-using OTSCLRINTERFACE;
|
|
|
-
|
|
|
-using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow;
|
|
|
-using OTSMeasureApp._0_OTSModel.OTSDataType;
|
|
|
+using static OTSDataType.otsdataconst;
|
|
|
+using Point = System.Drawing.Point;
|
|
|
|
|
|
namespace OTSModelSharp
|
|
|
{
|
|
|
@@ -150,7 +155,7 @@ namespace OTSModelSharp
|
|
|
// get image size
|
|
|
var nImageSizeId = pImgScanParam.GetImageResulotion();
|
|
|
int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId;
|
|
|
- Size sizePixelImage = RESOLUTION_VALUE[nResulotionId];
|
|
|
+ System.Drawing.Size sizePixelImage = RESOLUTION_VALUE[nResulotionId];
|
|
|
|
|
|
|
|
|
|
|
|
@@ -327,7 +332,7 @@ namespace OTSModelSharp
|
|
|
|
|
|
|
|
|
|
|
|
- PointF a_SEMpt = new Point();
|
|
|
+ PointF a_SEMpt = new System.Drawing.Point();
|
|
|
|
|
|
CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
|
|
|
int hardWareDelay = a_pCSEMStageData.GetHardWareDelay();
|
|
|
@@ -616,9 +621,82 @@ namespace OTSModelSharp
|
|
|
|
|
|
log.Info("Acquire BSE image success! Processing image...");
|
|
|
|
|
|
+
|
|
|
+ string path = @"C:\Users\yunyunyun\Desktop\9-9-1\pic\";
|
|
|
+
|
|
|
+ //byte[] bytes = curFld.GetBSEImage().GetImageDataPtr();
|
|
|
+ //if (bytes == null)
|
|
|
+ //{
|
|
|
+ // log.Error("BSE image data is null.");
|
|
|
+ //}
|
|
|
+ //Mat fieldMat = null;
|
|
|
+ int width = curFld.GetBSEImage().GetWidth();
|
|
|
+ int height = curFld.GetBSEImage().GetHeight();
|
|
|
+ //long expected = (long)width * height;
|
|
|
+ //if (bytes.Length < expected)
|
|
|
+ //{
|
|
|
+ // log.Error($"BSE image byte length ({bytes.Length}) < expected ({expected}).");
|
|
|
+ //}
|
|
|
+ //fieldMat = new Mat(height, width, MatType.CV_8UC1);
|
|
|
+ //Marshal.Copy(bytes, 0, fieldMat.Data, (int)expected);
|
|
|
+ //Cv2.ImWrite(path + "Org.bmp", fieldMat);
|
|
|
+
|
|
|
+
|
|
|
+ //Mat aifield = fieldMat.Clone();
|
|
|
+ //NCMDetector nCMDetector = new NCMDetector();
|
|
|
+ //List<AIShapeResult> aIShapeResults = nCMDetector.Detect(aifield);
|
|
|
+ //Mat binaryAifield = new Mat(fieldMat.Rows, fieldMat.Cols, MatType.CV_8UC1, new Scalar(255));
|
|
|
+ //foreach (var shp in aIShapeResults)
|
|
|
+ //{
|
|
|
+ // //Cv2.DrawContours(colorAifield, new List<List<OpenCvSharp.Point>> { shp.Points2List() }, -1, new Scalar(255, 0, 0), 3);
|
|
|
+ // Cv2.FillPoly(binaryAifield, new List<List<OpenCvSharp.Point>> { shp.Points2List() }, new Scalar(0, 0, 0));
|
|
|
+ //}
|
|
|
+
|
|
|
+ //Cv2.ImWrite(path + "Ai.bmp", binaryAifield);
|
|
|
+
|
|
|
+ ////Mat grayAifield = colorAifield.CvtColor(ColorConversionCodes.BGR2GRAY);
|
|
|
+ ////Mat binaryAifield = new Mat();
|
|
|
+ ////Cv2.Threshold(grayAifield, binaryAifield, 127, 255, ThresholdTypes.Binary);
|
|
|
+ //Mat invertedAifield = new Mat();
|
|
|
+ //Cv2.BitwiseNot(binaryAifield, invertedAifield);
|
|
|
+ //Cv2.ImWrite(path + "Ai_Not.bmp", invertedAifield);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// image process
|
|
|
|
|
|
FieldImageProcess(curFld);
|
|
|
+ Mat invertedAifield = Cv2.ImRead(path + "Ai.bmp", ImreadModes.Grayscale);
|
|
|
+ Mat binaryAifield = new Mat();
|
|
|
+ Cv2.Threshold(invertedAifield, binaryAifield, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
|
|
|
+
|
|
|
+ Mat OTSPic = Cv2.ImRead(path + "OTS.bmp", ImreadModes.Grayscale);
|
|
|
+ Mat binaryOTSPic = new Mat();
|
|
|
+ Cv2.Threshold(OTSPic, binaryOTSPic, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
|
|
|
+
|
|
|
+ //// 确保两个矩阵尺寸相同,才能进行与运算
|
|
|
+ //if (binaryOTSPic.Size() != binaryAifield.Size())
|
|
|
+ //{
|
|
|
+ // // 如果尺寸不同,则调整到相同的大小
|
|
|
+ // Mat resizedAifield = new Mat();
|
|
|
+ // Cv2.Resize(binaryAifield, resizedAifield, binaryOTSPic.Size());
|
|
|
+
|
|
|
+ // // 执行与运算
|
|
|
+ // Mat result = new Mat();
|
|
|
+ // Cv2.BitwiseAnd(binaryOTSPic, resizedAifield, result);
|
|
|
+ // // 保存结果
|
|
|
+ // Cv2.ImWrite(path + "OTS_Ai_And_Result.bmp", result);
|
|
|
+ //}
|
|
|
+ //else
|
|
|
+ //{
|
|
|
+ // // 执行与运算
|
|
|
+ // Mat result = new Mat();
|
|
|
+ // Cv2.BitwiseAnd(binaryOTSPic, invertedAifield, result);
|
|
|
+
|
|
|
+ // // 保存结果
|
|
|
+ // Cv2.ImWrite(path + "OTS_Ai_And_Result.bmp", result);
|
|
|
+ //}
|
|
|
|
|
|
MsgFieldBSE.InitFieldBSEAnalysisPartsDataMsg();
|
|
|
|
|
|
@@ -629,7 +707,7 @@ namespace OTSModelSharp
|
|
|
var listAnalysisParts = curFld.GetListAnalysisParticles();
|
|
|
foreach (var p in listAnalysisParts)
|
|
|
{
|
|
|
- Rectangle r = (Rectangle)p.GetParticleRect();
|
|
|
+ System.Drawing.Rectangle r = (System.Drawing.Rectangle)p.GetParticleRect();
|
|
|
var img = m_ScanHardwareMgr.AcquireRectangleBSEImage(r);
|
|
|
if (img != null)
|
|
|
{
|
|
|
@@ -638,20 +716,37 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
|
|
|
-
|
|
|
+ List<COTSParticleClr> AiAnalysisParts = new List<COTSParticleClr>();
|
|
|
if (pXRayParam.GetUsingXray() == true)
|
|
|
{
|
|
|
- foreach (var p in curFld.GetListAnalysisParticles())
|
|
|
+ log.Info("Begin to classify particles By AI!");
|
|
|
+ foreach (COTSParticleClr p in curFld.GetListAnalysisParticles())
|
|
|
{
|
|
|
- p.SetIsXrayParticle(true);
|
|
|
+ OpenCvSharp.Rect rect = new Rect();
|
|
|
+ Mat OtsPart = OTSParticlePic(width, height, p,ref rect);
|
|
|
+ Mat AiPart = binaryAifield[rect].Clone();
|
|
|
+ double area = p.GetPixelArea();
|
|
|
+ bool flag = IsNCMByAI(AiPart, OtsPart, (int)area);
|
|
|
+ if (!flag)
|
|
|
+ {
|
|
|
+ p.SetIsXrayParticle(true);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ p.SetBasicClassifyId(40004);
|
|
|
+ p.SetTypeId(40004);
|
|
|
+ p.SetTypeName("NCM");
|
|
|
+ p.SetTypeColor("#80FF80");
|
|
|
+ AiAnalysisParts.Add(p);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+ binaryAifield.Dispose();
|
|
|
+ log.Info("The ai classification is completed ;Number of identified particles:" + AiAnalysisParts.Count);
|
|
|
try
|
|
|
{
|
|
|
CollectParticlesXrayData(curFld);
|
|
|
+
|
|
|
//collect another time by double dwell time if it is lowcounts particle
|
|
|
var xrayparts = curFld.GetListXrayParticles();
|
|
|
var lowcountparts = new List<COTSParticleClr>();
|
|
|
@@ -670,7 +765,7 @@ namespace OTSModelSharp
|
|
|
|
|
|
}
|
|
|
var enoughcountparts = new List<COTSParticleClr>();
|
|
|
- foreach (var p in curFld.GetListAnalysisParticles())
|
|
|
+ foreach (var p in curFld.GetListXrayParticles())
|
|
|
{
|
|
|
if (!IsLowCounts(p))
|
|
|
{
|
|
|
@@ -683,16 +778,14 @@ namespace OTSModelSharp
|
|
|
{
|
|
|
log.Error(e.Message);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
|
|
|
+ }
|
|
|
+ curFld.SetIsMeasureComplete(true);
|
|
|
|
|
|
-
|
|
|
- curFld.SetIsMeasureComplete(true);
|
|
|
-
|
|
|
- log.Info("Begin to classify particles! particle num:" + curFld.GetListAnalysisParticles().Count);
|
|
|
+ log.Info("Begin to classify other particles! particle num:" + curFld.GetListAnalysisParticles().Count);
|
|
|
try
|
|
|
{
|
|
|
ClassifyFieldParticles(curFld);
|
|
|
@@ -700,20 +793,17 @@ namespace OTSModelSharp
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
log.Error(e.Message);
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+ List<COTSParticleClr> finalparts = new List<COTSParticleClr>();
|
|
|
+ finalparts.AddRange(curFld.GetListAnalysisParticles());
|
|
|
+ finalparts.AddRange(AiAnalysisParts);
|
|
|
+ curFld.SetListAnalysisParticles(finalparts);
|
|
|
MsgFieldBSE.InitFieldSTDColoredPartsDataMsg();
|
|
|
-
|
|
|
m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
|
|
|
//start db save
|
|
|
StartSaveFileThread(ref curFld);
|
|
|
-
|
|
|
// record
|
|
|
pStatus.AddCompletedFieldCenter(curFld.GetOTSPosition());
|
|
|
-
|
|
|
-
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.END);
|
|
|
|
|
|
SendFieldParticlesInfoToGUI(curFld, m_Sample.GetMsrStatus());
|
|
|
@@ -721,11 +811,12 @@ namespace OTSModelSharp
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
log.Error(e.Message);
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
while (bSaveThreadWorking)//wait untill all the field data has been saved.
|
|
|
{
|
|
|
Thread.Sleep(1000);
|
|
|
@@ -775,7 +866,7 @@ namespace OTSModelSharp
|
|
|
|
|
|
|
|
|
CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
|
|
|
- PointF semPos = new Point();
|
|
|
+ PointF semPos = new System.Drawing.Point();
|
|
|
a_pCSEMStageData.ConvertOTSToSEMCoord(fldCenter, ref semPos);
|
|
|
|
|
|
curFldData.SetSemPos(semPos);
|
|
|
@@ -784,6 +875,7 @@ namespace OTSModelSharp
|
|
|
CSampleParam pMsrParam = m_Sample.GetMsrParams();
|
|
|
COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam();
|
|
|
log.Info("Begin to process image and get all particles!");
|
|
|
+
|
|
|
//according to the ECD scope,filter out the effective particles,remove the noise.
|
|
|
curFldData.GetOriginalParticles(m_Sample.GetMsrParams(), m_Sample.CalculatePixelSize());
|
|
|
if (curFldData.Sample.GetMsrParams().GetImageProcessParam().GetBGRemoveType() == OTS_BGREMOVE_TYPE.MATRIX)
|
|
|
@@ -821,7 +913,7 @@ namespace OTSModelSharp
|
|
|
curFldData.FilterParticles(m_Sample.GetMsrParams().GetXRayParam());//filter according to the xraylimit
|
|
|
|
|
|
log.Info("Begin to Calculate the image property of every particle!");
|
|
|
- var analysisparts = curFldData.GetListAnalysisParticles();
|
|
|
+ List<COTSParticleClr> analysisparts = curFldData.GetListAnalysisParticles();
|
|
|
curFldData.CalParticleImageProp(analysisparts);//calculate particle image property such as feret diameter, DMAX etc.
|
|
|
|
|
|
curFldData.SelectParticlesAccordingImgProp(pImgProcessParam);
|
|
|
@@ -1175,16 +1267,11 @@ namespace OTSModelSharp
|
|
|
|
|
|
m_pMsrThread.SendMessageToMeasureGUI(MsgFieldEnd);
|
|
|
|
|
|
-
|
|
|
}
|
|
|
|
|
|
protected void StartSaveFileThread(ref COTSField a_pFieldMgr)
|
|
|
{
|
|
|
-
|
|
|
-
|
|
|
fieldQueue.Enqueue(a_pFieldMgr);
|
|
|
-
|
|
|
-
|
|
|
if (fieldQueue.Count() > 0) //if there's data in the queue and the previous thread has finished then start a new thread.
|
|
|
{
|
|
|
if (bSaveThreadWorking == false)
|
|
|
@@ -1197,8 +1284,59 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+ public Mat OTSParticlePic(int width, int height, COTSParticleClr oTSParticleClr, ref OpenCvSharp.Rect cvRect)
|
|
|
+ {
|
|
|
+ if (oTSParticleClr == null) return new Mat();
|
|
|
+ var feature = oTSParticleClr.GetFeature();
|
|
|
+ if (feature == null) return new Mat();
|
|
|
+
|
|
|
+ List<COTSSegmentClr> segsData = feature.GetSegmentsList();
|
|
|
+ if (segsData == null || segsData.Count == 0) return new Mat();
|
|
|
+ System.Drawing.Rectangle rectangle = (System.Drawing.Rectangle)oTSParticleClr.GetParticleRect();
|
|
|
+ cvRect = new OpenCvSharp.Rect(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
|
|
|
|
|
+ using (var fieldMat = new Mat(height, width, MatType.CV_8UC1, Scalar.All(0)))
|
|
|
+ {
|
|
|
+ Cv2.Threshold(fieldMat, fieldMat, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
|
|
|
+ var indexer = fieldMat.GetGenericIndexer<byte>();
|
|
|
+ foreach (var seg in segsData)
|
|
|
+ {
|
|
|
+ if (seg == null) continue;
|
|
|
+ int startX = seg.GetStart();
|
|
|
+ int y = seg.GetHeight();
|
|
|
+ int len = seg.GetLength();
|
|
|
+ if (y < 0 || y >= height) continue;
|
|
|
+ int x0 = Math.Max(0, startX);
|
|
|
+ int x1 = Math.Min(width, startX + len);
|
|
|
+ for (int x = x0; x < x1; x++)
|
|
|
+ {
|
|
|
+ indexer[y, x] = 255;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fieldMat[cvRect].Clone();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public bool IsNCMByAI(Mat aiSelPic, Mat oTSParticlePic, int area)
|
|
|
+ {
|
|
|
+ if (aiSelPic == null || oTSParticlePic == null) return false;
|
|
|
+ Cv2.BitwiseNot(aiSelPic, aiSelPic);
|
|
|
+ Mat labels = new Mat();
|
|
|
+ Mat stats = new Mat();
|
|
|
+ Mat centroids = new Mat();
|
|
|
+ using (Mat overlap = new Mat())
|
|
|
+ {
|
|
|
+ Cv2.BitwiseAnd(aiSelPic, oTSParticlePic, overlap);
|
|
|
+ int overlapCount = Cv2.CountNonZero(overlap);
|
|
|
+ double coverRatio = (double)overlapCount / (double)area;
|
|
|
+ if (coverRatio + 1e-9 < 0.9) // 未满足覆盖阈值
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ labels.Dispose();
|
|
|
+ stats.Dispose();
|
|
|
+ centroids.Dispose();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|