Pārlūkot izejas kodu

添加AI识别NCM

cxs 4 dienas atpakaļ
vecāks
revīzija
36dd9493a3

+ 38 - 0
OTS.sln

@@ -79,6 +79,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OxfordExtenderWrapper", "Ox
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpectrumSTDEditor", "SpectrumSTDEditor\SpectrumSTDEditor.csproj", "{A60440F1-FC94-4802-BFCB-E96457830D50}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OTSAlgrithm", "OTSAlgrithm\OTSAlgrithm.csproj", "{8FEF070D-879C-42E6-A3D4-57F137F09A47}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -773,6 +775,42 @@ Global
 		{A60440F1-FC94-4802-BFCB-E96457830D50}.Release_oxford62|x64.Build.0 = Release|x64
 		{A60440F1-FC94-4802-BFCB-E96457830D50}.Release_oxford62|x86.ActiveCfg = Release|Any CPU
 		{A60440F1-FC94-4802-BFCB-E96457830D50}.Release_oxford62|x86.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|x64.Build.0 = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Debug|x86.Build.0 = Debug|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|Any CPU.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|Any CPU.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|x64.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|x64.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|x86.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford50|x86.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|Any CPU.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|Any CPU.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|x64.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|x64.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|x86.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford60|x86.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|Any CPU.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|Any CPU.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|x64.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|x64.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|x86.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61|x86.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|Any CPU.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|Any CPU.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|x64.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|x64.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|x86.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford61sp1|x86.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|Any CPU.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|Any CPU.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|x64.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|x64.Build.0 = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|x86.ActiveCfg = Release|Any CPU
+		{8FEF070D-879C-42E6-A3D4-57F137F09A47}.Release_oxford62|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 31 - 0
OTSCPP/OTSImagePro/OTSImageProcess.cpp

@@ -121,6 +121,37 @@ namespace OTSIMGPROC
 			Mat labels = Mat::zeros(cvcopyImg.size(), CV_32S);
 			Mat  stats, centroids;
 			int number = connectedComponentsWithStats(cvcopyImg, labels, stats, centroids, 8, CV_32S);
+
+			
+			//// 创建一个空白的二值图像(全黑背景,值为0)
+			//Mat outputBinary = Mat::zeros(cvcopyImg.size(), CV_8UC1);
+
+			//// 遍历所有连通域(跳过背景组件,从索引1开始)
+			//for (int i = 1; i < number; i++) {
+			//	int x = stats.at<int>(i, CC_STAT_LEFT);
+			//	int y = stats.at<int>(i, CC_STAT_TOP);
+			//	int w = stats.at<int>(i, CC_STAT_WIDTH);
+			//	int h = stats.at<int>(i, CC_STAT_HEIGHT);
+			//	int area = stats.at<int>(i, CC_STAT_AREA);
+
+			//	// 可选:过滤小面积的连通域
+			//	// if (area < 最小面积阈值) continue;
+
+			//	// 在输出图像中标记连通域为白色(值为255)
+			//	for (int row = y; row < y + h; row++) {
+			//		for (int col = x; col < x + w; col++) {
+			//			if (labels.at<int>(row, col) == i) {
+			//				outputBinary.at<uchar>(row, col) = 255;
+			//			}
+			//		}
+			//	}
+			//}
+			//// 保存结果到指定路径
+			//cv::imwrite("C:\\Users\\yunyunyun\\Desktop\\9-9-1\\pic\\OTS.bmp", outputBinary);
+
+
+
+
 			
 			double rMin = m_imageProcessParam->GetIncArea().GetStart()/2.0;
 			double rMax = m_imageProcessParam->GetIncArea().GetEnd()/2.0;

+ 185 - 47
OTSIncAMeasureApp/1-OTSMeasure/Measure/3-MeasureFlow/CSmplMeasure.cs

@@ -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;
+        }
     }
 }

+ 12 - 5
OTSIncAMeasureApp/OTSIncAMeasureApp.csproj

@@ -223,10 +223,9 @@
       <EmbedInteropTypes>True</EmbedInteropTypes>
       <HintPath>..\OpenDll\WordApiDll\Microsoft.Office.Interop.Excel.dll</HintPath>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+    <Reference Include="Newtonsoft.Json, Version=13.0.1.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\OpenDll\Json\Newtonsoft.Json.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="NLog">
       <HintPath>..\OpenDll\Nlog\NLog.dll</HintPath>
@@ -238,8 +237,11 @@
       <HintPath>..\OpenDll\WordApiDll\office.dll</HintPath>
     </Reference>
     <Reference Include="OpenCvSharp">
-      <HintPath>..\OpenDll\OpenCvSharp\OpenCvSharp.dll</HintPath>
-      <Private>False</Private>
+      <HintPath>..\packages\OpenCvSharp4.4.13.0.20260330\lib\netstandard2.0\OpenCvSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="OpenCvSharp.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6adad1e807fea099, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\OpenCvSharp4.Extensions.4.13.0.20260330\lib\netstandard2.0\OpenCvSharp.Extensions.dll</HintPath>
     </Reference>
     <Reference Include="OTS.WinFormsUI.Docking, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -267,6 +269,7 @@
       <Private>False</Private>
     </Reference>
     <Reference Include="System.Design" />
+    <Reference Include="System.Drawing.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
     <Reference Include="System.Management" />
     <Reference Include="System.Numerics" />
     <Reference Include="System.Runtime.Remoting" />
@@ -1079,6 +1082,10 @@
     </BootstrapperPackage>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\OTSAlgrithm\OTSAlgrithm.csproj">
+      <Project>{8FEF070D-879C-42E6-A3D4-57F137F09A47}</Project>
+      <Name>OTSAlgrithm</Name>
+    </ProjectReference>
     <ProjectReference Include="..\OTSCommon\OTSCommon.csproj">
       <Project>{3b7695aa-8231-45ac-b493-84390a945d02}</Project>
       <Name>OTSCommon</Name>