Browse Source

增加Ai图像处理功能

zym198098 1 year ago
parent
commit
08ac39e09d

+ 12 - 0
OTSIncAMeasureApp/0-OTSModel/OTSDataType/COTSImageProcParam.cs

@@ -26,6 +26,18 @@ namespace OTSDataType
 
         private CSpecialGrayRangeParam m_specialGreyRangeParam;
         private string particleSelectCondition = "";
+        private string AIServer;
+
+        public string GetAIServer()
+        {
+            AIServer = "36.129.163.148:8080";
+            return AIServer;
+        }
+
+        public void SetAIServer(string value)
+        {
+            AIServer = value;
+        }
 
         public string GetParticleSelectCondition()
         {

+ 57 - 2
OTSIncAMeasureApp/1-OTSMeasure/Measure/3-MeasureFlow/CSmplMeasure.cs

@@ -16,6 +16,9 @@ using System.Windows.Forms;
 using System.Data;
 using System.IO;
 using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow;
+using OpenCvSharp.Extensions;
+using OTSMeasureApp;
+using System.Diagnostics;
 
 namespace OTSModelSharp
 {
@@ -561,6 +564,57 @@ namespace OTSModelSharp
             SemDataGnr.SetValue(kv, brightness, contrast);
             return true;
         }
+        private void AiProcess(ref CBSEImgClr pBSEImg)
+        {
+            var procParam = m_Sample.GetMsrParams().GetImageProcessParam();
+            var aiserver = procParam.GetAIServer();
+            var originalBseData = pBSEImg.GetImageDataPtr();//获取bse 图像
+            pBSEImg.GetWidth();
+            int m_iWidth = pBSEImg.GetWidth();
+            int m_iHeight = pBSEImg.GetHeight();
+            OpenCvSharp.Mat input = new OpenCvSharp.Mat();
+            Bitmap bitmap = CImageHandler.ToGrayBitmap(originalBseData, m_iWidth, m_iHeight);
+            input = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
+            //OpenCvSharp.Cv2.ImShow("img", input);
+            //OpenCvSharp.Cv2.WaitKey(0);
+            //OpenCvSharp.Cv2.DestroyAllWindows();
+            string baseurl = "http://" + aiserver;
+            //test server 
+            bool test = false;
+            if (test)
+            {
+                if (!AI_HttpClient.AI_Test(baseurl))
+                {
+                    log.Info("server erro!");
+                    MessageBox.Show("server erro!");
+                    input.Dispose();
+                    return;
+                }
+            }
+            if (!input.Empty())
+            {
+                OpenCvSharp.Mat output = new OpenCvSharp.Mat();
+                AI_HttpClient.AI_SegformerImage_cxx(baseurl, input, ref output, 1007, 1);
+                if (output.Empty())
+                {
+                    log.Info("aiserver out erro!");
+                    MessageBox.Show("aiserver  erro!");
+                    input.Dispose();
+                    output.Dispose();
+                    return;
+                }
+                output = ~output;  //
+                                   //将二值图复制到pBSEImg
+                var bitData = CImageHandler.BitmapToGrayByte(output.ToBitmap());
+                pBSEImg.SetImageData(bitData, output.Width, output.Height);
+                //OpenCvSharp.Cv2.ImShow("out", output);
+                //OpenCvSharp.Cv2.WaitKey(0);
+                //OpenCvSharp.Cv2.DestroyAllWindows();
+                input.Dispose();
+                output.Dispose();
+            }
+        }
+
         public void DoMeasureForOneSample()
         {
             using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this)) //when this method exit ,the SetSEMExternalOff and ResetScan will be called automatically.
@@ -731,9 +785,10 @@ namespace OTSModelSharp
                         pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
                         return;
                     }
-                    curFld.SetBSEImage(pBSEImg);
-
+                    //ai 提取二值图
+                    AiProcess(ref pBSEImg);
 
+                    curFld.SetBSEImage(pBSEImg);
                     //BSEData
                     ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(m_Sample,curFld);
                     MsgFieldBSE.InitFieldBSEImageMsg();

+ 12 - 18
OTSIncAMeasureApp/5-OTSMeasureStatuImageFun/OTSMeasureStatusWindow.Designer.cs

@@ -39,12 +39,11 @@
             this.VisualAdjustingMenu = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
             this.grayToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
             this.ChangeDiffImageShow = new System.Windows.Forms.ToolStripMenuItem();
             this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
+            this.AIProcessToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.AbandonGrayStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
             this.MenuItemLineScan = new System.Windows.Forms.ToolStripMenuItem();
             this.PointScanElementMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.ExportScanInfoMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -78,17 +77,16 @@
             this.VisualAdjustingMenu,
             this.toolStripMenuItem1,
             this.grayToolStripMenuItem,
-            this.toolStripSeparator1,
             this.ChangeDiffImageShow,
             this.ToolStripMenuItem,
             this.toolStripMenuItem2,
+            this.AIProcessToolStripMenuItem,
             this.AbandonGrayStripMenuItem,
-            this.toolStripSeparator2,
             this.MenuItemLineScan,
             this.PointScanElementMenuItem,
             this.ExportScanInfoMenuItem});
             this.contextMenuStrip1.Name = "contextMenuStrip1";
-            this.contextMenuStrip1.Size = new System.Drawing.Size(243, 258);
+            this.contextMenuStrip1.Size = new System.Drawing.Size(243, 290);
             this.contextMenuStrip1.Opened += new System.EventHandler(this.contextMenuStrip1_Opened);
             // 
             // SampleParaLock
@@ -119,11 +117,6 @@
             this.grayToolStripMenuItem.Text = "显示BSE灰度曲线图";
             this.grayToolStripMenuItem.Click += new System.EventHandler(this.ShowGrayLevelImage_Click);
             // 
-            // toolStripSeparator1
-            // 
-            this.toolStripSeparator1.Name = "toolStripSeparator1";
-            this.toolStripSeparator1.Size = new System.Drawing.Size(239, 6);
-            // 
             // ChangeDiffImageShow
             // 
             this.ChangeDiffImageShow.Name = "ChangeDiffImageShow";
@@ -145,6 +138,13 @@
             this.toolStripMenuItem2.Text = "BSE去背景彩色图";
             this.toolStripMenuItem2.Click += new System.EventHandler(this.toolStripMenuItem2_Click);
             // 
+            // AIProcessToolStripMenuItem
+            // 
+            this.AIProcessToolStripMenuItem.Name = "AIProcessToolStripMenuItem";
+            this.AIProcessToolStripMenuItem.Size = new System.Drawing.Size(242, 22);
+            this.AIProcessToolStripMenuItem.Text = "AI自动识别";
+            this.AIProcessToolStripMenuItem.Click += new System.EventHandler(this.aI自动识别ToolStripMenuItem_Click);
+            // 
             // AbandonGrayStripMenuItem
             // 
             this.AbandonGrayStripMenuItem.Name = "AbandonGrayStripMenuItem";
@@ -152,11 +152,6 @@
             this.AbandonGrayStripMenuItem.Text = "显示BSE去背景灰度曲线图";
             this.AbandonGrayStripMenuItem.Click += new System.EventHandler(this.ShowAbandonGrayLevelImage_Click);
             // 
-            // toolStripSeparator2
-            // 
-            this.toolStripSeparator2.Name = "toolStripSeparator2";
-            this.toolStripSeparator2.Size = new System.Drawing.Size(239, 6);
-            // 
             // MenuItemLineScan
             // 
             this.MenuItemLineScan.CheckOnClick = true;
@@ -231,7 +226,7 @@
             this.Controls.Add(this.picBox);
             this.Controls.Add(this.myChart);
             this.DockAreas = ((OTS.WinFormsUI.Docking.DockAreas)((OTS.WinFormsUI.Docking.DockAreas.DockTop | OTS.WinFormsUI.Docking.DockAreas.Document)));
-            this.Font = new System.Drawing.Font("SimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.Name = "OTSMeasureStatusWindow";
             this.Text = "OTSMeasureStatus";
             this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
@@ -250,8 +245,6 @@
         private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem grayToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem MenuItemLineScan;
-        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
-        private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
         public System.Windows.Forms.PictureBox picBox;
         private System.Windows.Forms.ToolStripMenuItem AbandonGrayStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem ChangeDiffImageShow;
@@ -263,5 +256,6 @@
         private System.Windows.Forms.ToolStripMenuItem VisualAdjustingMenu;
         private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
         private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2;
+        private System.Windows.Forms.ToolStripMenuItem AIProcessToolStripMenuItem;
     }
 }

+ 193 - 12
OTSIncAMeasureApp/5-OTSMeasureStatuImageFun/OTSMeasureStatusWindow.cs

@@ -1,4 +1,7 @@
-using OTS.WinFormsUI.Docking;
+
+
+using OpenCvSharp.Extensions;
+using OTS.WinFormsUI.Docking;
 using OTSCLRINTERFACE;
 using OTSDataType;
 using OTSIncAGraph.Controls;
@@ -39,14 +42,16 @@ namespace OTSMeasureApp
         //BSE去背景图
         DelBSEBG = 5,
         ColoredBSENoBG = 6,
+
+        AIProcess=7,
         //显示BSE去背景灰度曲线图
-        SampleHoleBSEImage = 7,
+        SampleHoleBSEImage = 8,
         //线扫描曲线
-        MenuItemLineScam = 8,
+        MenuItemLineScam = 9,
         //单点采集Xray与元素信息
-        PointScanElementMenuItem = 9,
+        PointScanElementMenuItem = 10,
         //导出采集信息报告
-        ExportReport = 10
+        ExportReport = 11
     }
     public partial class OTSMeasureStatusWindow : DockContent
     {
@@ -267,21 +272,21 @@ namespace OTSMeasureApp
         #region 处理获取调试图菜单事件
         private void AcquireBSEImage_Click(object sender, EventArgs e)
         {
-           
-                if (m_ElementPointGDIObjects != null)
+            if (m_ElementPointGDIObjects != null)
                 {
                     m_ElementPointGDIObjects.Clear();
                 }
                 //设置右键菜单中的项 是否可编辑
                 SetContextMenuEnabled(true);
-                AcquireBSEImage();
-
-           
-           
+       
+                AcquireBSEImage();                   
                 DelElementPointGDIObjects();
                 panelXray.Visible = false;
                 m_CurrentMultiple = 0;
-           
+            var name0 = contextMenuStrip1.Items[0].Name;
+            var name7 = contextMenuStrip1.Items[7].Name;
+            var name8 = contextMenuStrip1.Items[8].Name;
+            contextMenuStrip1.Items[(int)MeasureStateMenuType.AIProcess].Enabled = true;
         }
         /// <summary>
         /// 获取BSE图方法
@@ -573,6 +578,69 @@ namespace OTSMeasureApp
 
         }
 
+        protected void ShowColoredRemoveBGImage_Ai(byte[] originalBseData)
+        {
+
+            //获取电镜中图像大小
+            string str = m_MeasureAppForm.m_ProjParam.GetBSEImageResolutionStr();
+            string[] sArray = str.Split('X');
+            if (sArray[0] != "" && sArray[1] != "")
+            {
+                m_iWidth = Convert.ToInt32(sArray[0]);
+                m_iHeight = Convert.ToInt32(sArray[1]);
+            }
+            //获取图像数据
+            COTSSample WSample = m_MeasureAppForm.m_ProjData.GetWorkingSample();
+            double pixelSize = WSample.CalculatePixelSize();
+
+            var imageProcessParam = WSample.GetMsrParams().GetImageProcessParam();
+
+            var imageHandle = new CImageHandler();
+
+            coloredParticleImage = new Bitmap(m_iWidth, m_iHeight);
+            CBSEImgClr pImgNoBG = new CBSEImgClr(new Rectangle(0, 0, m_iWidth, m_iHeight));
+            bfResult = imageHandle.GetColoredImage(imageProcessParam, pixelSize, originalBseData, m_iWidth, m_iHeight, ref pImgNoBG, ref coloredParticleImage);
+
+            removeBGBseData = pImgNoBG.GetImageDataPtr();
+
+            //获取去背景灰度图数据
+            dGrayAbandonLevelData = new double[(int)GrayLevel.Max];
+            dGrayAbandonLevelData = GetGrayAbandonData(removeBGBseData, dGrayAbandonLevelData);
+
+            //计算灰度去背景最大值
+            dGrayAbandonLevelMax = dGrayAbandonLevelData[0];
+            for (int i = 1; i < (int)GrayLevel.Max; i++)
+            {
+                dGrayAbandonLevelMax = Math.Max(dGrayAbandonLevelMax, dGrayAbandonLevelData[i]);
+            }
+
+
+
+            //取图不成功就返回
+            if (!bfResult) { return; }
+
+
+
+            ShowBitmap(m_iWidth, m_iHeight, coloredParticleImage);
+
+            IsShowGrayLevelLine = false;
+
+
+            myChart.Visible = false;
+            picBox.Show();
+            //切换显示至BSE图
+            contextMenuStrip1.Items[(int)MeasureStateMenuType.ChangeDiffImageShow].Enabled = true;
+            if (OTSCommon.Language.ReadDefaultLanguage() == "ZH")
+            {
+                contextMenuStrip1.Items[(int)MeasureStateMenuType.ChangeDiffImageShow].Text = "切换显示至BSE图";
+            }
+            else
+            {
+                contextMenuStrip1.Items[(int)MeasureStateMenuType.ChangeDiffImageShow].Text = "SwitchDisplayToBSEDiagram";
+            }
+
+        }
+
         #endregion
         //显示灰度曲线
         #region 显示灰度曲线
@@ -1961,6 +2029,119 @@ namespace OTSMeasureApp
             m_CurrentMultiple = 0;
             panelXray.Visible = false;
         }
+        /// <summary>
+        /// 调用AI http 服务获得二值图
+        /// </summary>
+        private void aiProcess()
+        {
+            //获取电镜中图像大小
+            string str = m_MeasureAppForm.m_ProjParam.GetBSEImageResolutionStr();
+            string[] sArray = str.Split('X');
+            if (sArray[0] != "" && sArray[1] != "")
+            {
+                m_iWidth = Convert.ToInt32(sArray[0]);
+                m_iHeight = Convert.ToInt32(sArray[1]);
+            }
+            //获取图像数据
+            COTSSample WSample = m_MeasureAppForm.m_ProjData.GetWorkingSample();
+            double pixelSize = WSample.CalculatePixelSize();
+            var imageProcessParam = WSample.GetMsrParams().GetImageProcessParam();
+            var aiserver = imageProcessParam.GetAIServer();
+            OpenCvSharp.Mat input = new OpenCvSharp.Mat();
+            Bitmap bitmap = CImageHandler.ToGrayBitmap(originalBseData, m_iWidth, m_iHeight);
+            input = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
+            //OpenCvSharp.Cv2.ImShow("img", input);
+            //OpenCvSharp.Cv2.WaitKey(0);
+            //OpenCvSharp.Cv2.DestroyAllWindows();
+            string baseurl = "http://" + aiserver;
+            //test server 
+            bool test = false;
+            if(test)
+            {
+                if (!AI_HttpClient.AI_Test(baseurl))
+                {
+                    log.Info("server erro!");
+                    MessageBox.Show("server erro!");
+                    input.Dispose();
+                    return;
+                }
+            }
+            if (!input.Empty())
+            {
+                OpenCvSharp.Mat output = new OpenCvSharp.Mat();
+                AI_HttpClient.AI_SegformerImage_cxx(baseurl, input, ref output, 1007, 1);
+                if (output.Empty())
+                {
+                    log.Info("aiserver out erro!");
+                    MessageBox.Show("aiserver  erro!");
+                    input.Dispose();
+                    output.Dispose();
+                    return;
+                }
+                //output = output - 30;
+                output = ~output;  //适配 ShowColoredRemoveBGImage_Ai    
+                // setcoloredParticleImage(output, ref coloredParticleImage);
+                // ShowBitmap(m_iWidth, m_iHeight, coloredParticleImage);
+                removeBGBseData = CImageHandler.BitmapToGrayByte(output.ToBitmap());
+                //设置右键菜单中的项 是否可编辑
+                SetContextMenuEnabled(true);
+                ShowColoredRemoveBGImage_Ai(CImageHandler.BitmapToGrayByte(output.ToBitmap()));
+                 m_CurrentMultiple = 0;
+                panelXray.Visible = false;
+                //OpenCvSharp.Cv2.ImShow("out", output);
+                //OpenCvSharp.Cv2.WaitKey(0);
+                //OpenCvSharp.Cv2.DestroyAllWindows();
+                input.Dispose();
+                output.Dispose();                   
+                IsShowGrayLevelLine = false;
+                myChart.Visible = false;
+                //切换显示至BSE图
+                contextMenuStrip1.Items[(int)MeasureStateMenuType.ChangeDiffImageShow].Enabled = true;
+
+            }
+        }
+    /// <summary>
+    /// 提取aiprocess result 连通域;找到颗粒
+    /// </summary>
+    /// <param name="output">aiprocess result</param>
+    /// <param name="coloredParticleImage"></param>
+        private void setcoloredParticleImage(OpenCvSharp.Mat output, ref Bitmap coloredParticleImage)
+        {
+            //提取连通域;用不同颜色显示连通域
+            OpenCvSharp.Mat labels = new OpenCvSharp.Mat(output.Size(), OpenCvSharp.MatType.CV_32S);
+            int numLabels = OpenCvSharp.Cv2.ConnectedComponents(output, labels, OpenCvSharp.PixelConnectivity.Connectivity8, OpenCvSharp.MatType.CV_32S);
+            //随机颜色
+            Random random = new Random();
+            OpenCvSharp.Mat coloredRegion = new OpenCvSharp.Mat(output.Size(), OpenCvSharp.MatType.CV_8UC3, OpenCvSharp.Scalar.All(0)); // 初始化为黑色  
+            for (int i = 1; i < numLabels; i++)
+            {
+                // 生成随机颜色  
+                OpenCvSharp.Scalar color = new OpenCvSharp.Scalar(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256));
+                // 提取当前连通区域的掩码  
+                OpenCvSharp.Mat mask = new OpenCvSharp.Mat();
+                OpenCvSharp.Cv2.Compare(labels, i, mask, OpenCvSharp.CmpTypes.EQ); // 使用Cv2.Compare创建掩码
+                coloredRegion.SetTo(color, mask);
+            }
+            coloredRegion = ~coloredRegion;
+            //OpenCvSharp.Cv2.ImShow("coloredRegion", coloredRegion);
+            //OpenCvSharp.Cv2.WaitKey(0);
+            //OpenCvSharp.Cv2.DestroyAllWindows();
+            if (coloredParticleImage == null)
+            {
+                coloredParticleImage = new Bitmap(coloredRegion.ToBitmap());
+            }
+            else
+            {
+                coloredParticleImage = coloredRegion.ToBitmap();
+            }
+            labels.Dispose();
+            coloredRegion.Dispose();
+        }
+        private void aI自动识别ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+
+            aiProcess();
+        }
     }
 }
 

+ 4 - 0
OTSIncAMeasureApp/OTSIncAMeasureApp.csproj

@@ -222,6 +222,9 @@
       <HintPath>..\OpenDll\OpenCvSharp\OpenCvSharp.dll</HintPath>
       <Private>False</Private>
     </Reference>
+    <Reference Include="OpenCvSharp.Extensions">
+      <HintPath>..\OpenDll\OpenCvSharp\OpenCvSharp.Extensions.dll</HintPath>
+    </Reference>
     <Reference Include="OTS.WinFormsUI.Docking, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\OpenDll\WordApiDll\OTS.WinFormsUI.Docking.dll</HintPath>
@@ -546,6 +549,7 @@
     <Compile Include="5-OTSMeasureStatuImageFun\ToolWindow.Designer.cs">
       <DependentUpon>ToolWindow.cs</DependentUpon>
     </Compile>
+    <Compile Include="ServiceCenter\AI_HttpClient.cs" />
     <Compile Include="ServiceCenter\CClassifyEngine.cs" />
     <Compile Include="ServiceCenter\CImageHandler.cs" />
     <Compile Include="ServiceCenter\CPP%28Bruker%29API\EDSController.cs" />

+ 327 - 0
OTSIncAMeasureApp/ServiceCenter/AI_HttpClient.cs

@@ -0,0 +1,327 @@
+#define cxx_server
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using OpenCvSharp;
+using System.Drawing;
+using OpenCvSharp.Extensions;
+using Newtonsoft.Json.Linq;
+using System.Runtime.InteropServices;
+using System.Security.Policy;
+using static OpenCvSharp.XImgProc.CvXImgProc;
+
+namespace OTSModelSharp.ServiceCenter
+{
+    public class class_result
+    {
+        public string Result { get; set; }
+        public float Confidence { get; set; }
+    }
+    public class AI_HttpClient
+    {
+        /// <summary>
+        /// 从分割模型获取二值图
+        /// </summary>
+        /// <param name="baseUrl">包括ip地址端口号</param>
+        /// <param name="input">输入mat 3通道 bgr格式</param>
+        /// <param name="output">输出mat 灰度图</param>
+        /// <param name="catagory">模型类别和模型配置文件对应</param>
+        /// <param name="item">模型序号和模型配置文件对应</param>
+        /// <param name="filename">input mat 原图完整路径</param>
+        public static void AI_SegmentImage(string baseUrl, Mat input, ref Mat output, int catagory = 1000, int item = 1, string filename = "1.jpg")
+        {
+#if cxx_server
+            AI_SegmentImage_cxx(baseUrl, input, ref output, catagory, item, filename);
+#else
+AI_SegmentImage_cshape(baseUrl, input, ref output, catagory, item, filename);
+#endif
+        }
+        /// <summary>
+        /// 从模型获得分类结果 需做进一步筛选获得分类
+        /// </summary>
+        /// <param name="baseUrl"></param>
+        /// <param name="input">输入mat 3通道 bgr格式</param>
+        /// <param name="resultDic">label confiden 字典</param>
+        /// <param name="catagory">模型类别和模型配置文件对应</param>
+        /// <param name="item">模型序号和模型配置文件对应</param>
+        /// <param name="filename">input mat 原图完整路径</param>
+        public static void AI_ClassImage(string baseUrl, Mat input, ref Dictionary<string, string> resultDic, int catagory = 1000, int item = 2, string filename = "1.jpg")
+        {
+#if cxx_server
+            AI_ClassImage_cxx(baseUrl, input, ref resultDic, catagory, item, filename);
+#else
+ AI_ClassImage_cshape(baseUrl, input, ref resultDic, catagory, item, filename);
+#endif
+        }
+
+        /// <summary>
+        /// 从分割模型获取二值图 cshape httpserver
+        /// </summary>
+        /// <param name="baseUrl">包括ip地址端口号</param>
+        /// <param name="input">输入mat 3通道 bgr格式</param>
+        /// <param name="output">输出mat 灰度图</param>
+        /// <param name="catagory">模型类别和模型配置文件对应</param>
+        /// <param name="item">模型序号和模型配置文件对应</param>
+        /// <param name="filename">input mat 原图完整路径</param>
+        public static void AI_SegmentImage_cshape(string baseUrl, Mat input, ref Mat output, int catagory = 1000, int item = 1, string filename = "1.jpg")
+        {
+            string reqUrl = baseUrl + "/api/MetalAI/SegmentImage?catagory=" + catagory.ToString() + "&item=" + item.ToString();
+            try
+            {
+
+                HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false });
+                var postContent = new MultipartFormDataContent();
+                string boundary = string.Format("--{0}", DateTime.Now.Ticks.ToString("x"));
+                postContent.Headers.Add("ContentType", $"multipart/form-data, boundary={boundary}");
+                MemoryStream ms = input.ToMemoryStream(".jpg");
+                postContent.Add(new StreamContent(ms, (int)ms.Length), "formFiles", Path.GetFileName(filename));
+                var response = client.PostAsync(reqUrl, postContent).Result;
+                Console.WriteLine(response);
+                if (response.IsSuccessStatusCode)
+                {
+                    var streamFromService = response.Content.ReadAsStreamAsync().Result;
+                    Bitmap bmp = new Bitmap(streamFromService);
+                    output = BitmapConverter.ToMat(bmp);
+                    if (output.Channels() == 4)
+                    {
+                        Cv2.CvtColor(output, output, ColorConversionCodes.BGRA2GRAY);
+                    }
+                    return;
+                }
+            }
+            catch (Exception ex)
+            {
+
+                Console.WriteLine(ex.ToString());
+            }
+        }
+        /// <summary>
+        /// 从模型获得分类结果 需做进一步筛选获得分类 cshape httpserver
+        /// </summary>
+        /// <param name="baseUrl"></param>
+        /// <param name="input">输入mat 3通道 bgr格式</param>
+        /// <param name="resultDic">label confiden 字典</param>
+        /// <param name="catagory">模型类别和模型配置文件对应</param>
+        /// <param name="item">模型序号和模型配置文件对应</param>
+        /// <param name="filename">input mat 原图完整路径</param>
+        public static void AI_ClassImage_cshape(string baseUrl, Mat input, ref Dictionary<string, string> resultDic, int catagory = 1000, int item = 2, string filename = "1.jpg")
+        {
+            string reqUrl = baseUrl + "/api/MetalAI/Classify?catagory=" + catagory.ToString() + "&item=" + item.ToString();
+            try
+            {
+
+                HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false });
+                var postContent = new MultipartFormDataContent();
+                string boundary = string.Format("--{0}", DateTime.Now.Ticks.ToString("x"));
+                postContent.Headers.Add("ContentType", $"multipart/form-data, boundary={boundary}");
+                MemoryStream ms = input.ToMemoryStream(".jpg");
+                postContent.Add(new StreamContent(ms, (int)ms.Length), "formFiles", Path.GetFileName(filename));
+                var response = client.PostAsync(reqUrl, postContent).Result;
+                //Console.WriteLine(response);
+                if (response.IsSuccessStatusCode)
+                {
+                    var streamFromService = response.Content.ReadAsStringAsync().Result;
+                    resultDic = JsonConvert.DeserializeObject<Dictionary<string, string>>(streamFromService);
+                    //var maxItem = resultDic.OrderByDescending(kvp => double.Parse(kvp.Value)).FirstOrDefault();//获取得分最大元素的方法
+                    return;
+                }
+            }
+            catch (Exception ex)
+            {
+                // throw new Exception("保存file异常");
+                Console.WriteLine(ex.ToString());
+            }
+        }
+        public static bool AI_Test(string baseUrl)
+        {
+            bool connect=false;
+            string reqUrl = baseUrl + "/api/metalai/Test";
+            try
+            {
+
+                HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false });
+                client.Timeout= TimeSpan.FromSeconds(3);
+                 var response = client.GetAsync(reqUrl).Result;
+                //Console.WriteLine(response);
+                if (response.IsSuccessStatusCode)
+                {
+
+                    connect=true;
+                }
+            }
+            catch (Exception ex)
+            {
+                // throw new Exception("保存file异常");
+                Console.WriteLine(ex.ToString());
+                return false;
+            }
+            return connect;
+        }
+        /// <summary>
+        /// c++ 服务器 分类模型
+        /// </summary>
+        /// <param name="baseUrl"></param>
+        /// <param name="input"></param>
+        /// <param name="resultDic"></param>
+        /// <param name="catagory"></param>
+        /// <param name="item"></param>
+        /// <param name="filename"></param>
+        public static void AI_ClassImage_cxx(string baseUrl, Mat input, ref Dictionary<string, string> resultDic, int catagory = 1000, int item = 2, string filename = "1.jpg")
+        {
+            baseUrl = baseUrl + "/api/MetalAI/Classify";
+            if (input.Empty())
+            {
+                return;
+            }
+            class_result result = new class_result();
+
+            Dictionary<string, float> resluts = new Dictionary<string, float>();
+            using (var client = new HttpClient())
+            {
+                // Create the query parameters
+                var query = $"?category={catagory}&item={item}";
+
+                // Read the image into a byte array
+                byte[] imageBytes;
+                Cv2.ImEncode(".png", input, out imageBytes);
+                // Create the content with image data
+
+
+                var imageContent = new ByteArrayContent(imageBytes);
+                //imageContent.Headers.ContentLength= imageBytes1.Length;
+                Console.WriteLine(imageBytes.Length);
+                // Send the POST request with query parameters
+                var fullUrl = baseUrl + query;
+                try
+                {
+
+                }
+                catch (Exception)
+                {
+
+                    throw;
+                }
+                var response = client.PostAsync(fullUrl, imageContent).Result;
+
+                if (response.IsSuccessStatusCode)
+                {
+                    var responseData = response.Content.ReadAsStringAsync().Result;
+                    // var  result1 = JsonConvert.DeserializeObject<class_result>(responseData);
+                    resluts = JsonConvert.DeserializeObject<Dictionary<string, float>>(responseData);
+                    foreach (var reslt in resluts)
+                    {
+                        resultDic.Add(reslt.Key, reslt.Value.ToString());
+                    }
+
+                }
+                else
+                {
+                    Console.WriteLine($"HTTP request failed with status code {response.StatusCode}");
+                }
+            }
+
+        }
+        /// <summary>
+        /// c++服务器 unet 
+        /// </summary>
+        /// <param name="baseUrl"></param>
+        /// <param name="input"></param>
+        /// <param name="output"></param>
+        /// <param name="catagory"></param>
+        /// <param name="item"></param>
+        /// <param name="filename"></param>
+        public static void AI_SegmentImage_cxx(string baseUrl, Mat input, ref Mat output, int catagory = 1000, int item = 1, string filename = "1.jpg")
+        {
+            baseUrl = baseUrl + "/api/MetalAI/SegmentImage";
+            if (input.Empty())
+            {
+                return;
+            }
+            // Create the query parameters
+            var query = $"?category={catagory}&item={item}";
+            var fullUrl = baseUrl + query;
+            send_image(fullUrl, input, ref output);
+
+        }
+        public static void UploadFile(string url, string filePath)
+        {
+            using (var client = new HttpClient())
+            using (var content = new MultipartFormDataContent())
+            {
+                var fileContent = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
+                fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg"); // 设置正确的MIME类型  
+                content.Add(fileContent, "file", Path.GetFileName(filePath)); // "file"是服务器期望的表单字段名  
+
+                var response = client.PostAsync(url, content).Result; // 使用.Result等待异步操作完成,这将阻塞当前线程  
+
+                if (response.IsSuccessStatusCode)
+                {
+                    Console.WriteLine("File uploaded successfully.");
+                }
+                else
+                {
+                    Console.WriteLine("Error uploading file: " + response.StatusCode);
+                }
+            }
+        }
+       public static void send_image(string fullUrl, Mat input, ref Mat output)
+        {
+            using (var client = new HttpClient())
+            {
+                // Create the query parameters
+
+
+                // Read the image into a byte array
+                byte[] imageBytes;
+                Cv2.ImEncode(".png", input, out imageBytes);
+                // Create the content with image data
+                var imageContent = new ByteArrayContent(imageBytes);
+                Console.WriteLine(imageBytes.Length);
+                // Send the POST request with query parameters
+
+                var response = client.PostAsync(fullUrl, imageContent).Result;
+                if (response.IsSuccessStatusCode)
+                {
+                    //var responseData = response.Content.ReadAsStringAsync().Result;
+                    var streamFromService = response.Content.ReadAsByteArrayAsync().Result;
+                    try
+                    {
+                        output = Cv2.ImDecode(streamFromService, ImreadModes.Grayscale);
+                    }
+                    catch (Exception)
+                    {
+
+                        throw;
+                    }
+                }
+                else
+                {
+                    Console.WriteLine($"HTTP request failed with status code {response.StatusCode} ");
+                }
+            }
+
+        }
+        public static void AI_SegformerImage_cxx(string baseUrl, Mat input, ref Mat output, int catagory = 1000, int item = 1)
+        {
+            baseUrl = baseUrl + "/api/MetalAI/SegformerImage";
+            if (input.Empty())
+            {
+                return;
+            }
+            var query = $"?category={catagory}&item={item}";
+            var fullUrl = baseUrl + query;
+            send_image(fullUrl, input, ref output);
+        }
+
+    }
+}