jeremy 9 meses atrás
pai
commit
b040ae5d44

+ 39 - 37
Service/AIDiagnosisService.URM.cs

@@ -18,6 +18,7 @@ using System.Diagnostics;
 using Logger = WingServerCommon.Log.Logger;
 using System.Text;
 using Newtonsoft.Json;
+using WingAIDiagnosisService.URMManage;
 
 namespace WingAIDiagnosisService.Service
 {
@@ -105,7 +106,7 @@ namespace WingAIDiagnosisService.Service
                                 urmParamers.TryAdd("RoiWPercent", request.RoiWPercent.ToString());
                                 urmParamers.TryAdd("RoiHPercent", request.RoiHPercent.ToString());
                                 // 开始URM分析
-                                var result = DoURMAnalysisV2<URMAnalysisV2Result>(remedicalCode, origialFile, converFile, currentFolder, urmParamers);
+                                var result = DoURMAnalysisV2(remedicalCode, origialFile, converFile, currentFolder, urmParamers);
                                 if (result != null)
                                 {
                                     resultData.IsSuccess = true;
@@ -113,7 +114,7 @@ namespace WingAIDiagnosisService.Service
                                     resultData.URMSrcWidth = result.URMSrcWidth;
                                     resultData.URMSrcHeight = result.URMSrcHeight;
                                     resultData.URMRes = result.URMRes;
-                                    await InitURMAnalysisDetails(resultData, fileToken, currentFolder, origialRemedicalInfo);
+                                    await InitURMAnalysisDetails(resultData, fileToken, currentFolder, origialRemedicalInfo, result.ConverImageUrl);
                                 }
                             }
                         }
@@ -132,10 +133,10 @@ namespace WingAIDiagnosisService.Service
             {
                 try
                 {
-                    if (Directory.Exists(currentFolder))
-                    {
-                        Directory.Delete(currentFolder, true);
-                    }
+                    // if (Directory.Exists(currentFolder))
+                    // {
+                    //     Directory.Delete(currentFolder, true);
+                    // }
                 }
                 catch { }
             }
@@ -716,7 +717,7 @@ namespace WingAIDiagnosisService.Service
             return false;
         }
 
-        private TResult DoURMAnalysisV2<TResult>(string remedicalCode, string origialFile, string converFile, string outputFolder, Dictionary<string, string> urmParamers)
+        private URMAnalysisV2Result DoURMAnalysisV2(string remedicalCode, string origialFile, string converFile, string outputFolder, Dictionary<string, string> urmParamers)
         {
             try
             {
@@ -759,31 +760,33 @@ namespace WingAIDiagnosisService.Service
                 arguments.Append($"{GetValue(urmParamers, "RoiWPercent")};");
                 arguments.Append($"{GetValue(urmParamers, "RoiHPercent")};");
 
-                var exeFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "URM", "net6.0");
-                // exeFolder = Path.Combine(@"D:\WingProjects\URMDemo\URMAnalysis\bin\Debug\net6.0");
-                var exePath = Path.Combine(exeFolder, "URMAnalysis.exe");
-                var psi = new ProcessStartInfo(exePath, arguments.ToString())
-                {
-                    Verb = "runas",
-                    RedirectStandardOutput = true,
-                    UseShellExecute = false,
-                };
-                using (var process = Process.Start(psi))
-                {
-                    if (process != null)
-                    {
-                        process.WaitForExit();
-                    }
-                }
-                var urmResultFile = Path.Combine(outputFolder, "urmResult.txt");
-                if (File.Exists(urmResultFile))
-                {
-                    var output = File.ReadAllText(urmResultFile);
-                    if (!string.IsNullOrWhiteSpace(output))
-                    {
-                        return JsonConvert.DeserializeObject<TResult>(output);
-                    }
-                }
+                return new URMAnalysisManager().DoURMAnalysis(arguments.ToString().Split(" "));
+
+                // var exeFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "URM", "net6.0");
+                // // exeFolder = Path.Combine(@"D:\WingProjects\URMDemo\URMAnalysis\bin\Debug\net6.0");
+                // var exePath = Path.Combine(exeFolder, "URMAnalysis.exe");
+                // var psi = new ProcessStartInfo(exePath, arguments.ToString())
+                // {
+                //     Verb = "runas",
+                //     RedirectStandardOutput = true,
+                //     UseShellExecute = false,
+                // };
+                // using (var process = Process.Start(psi))
+                // {
+                //     if (process != null)
+                //     {
+                //         process.WaitForExit();
+                //     }
+                // }
+                // var urmResultFile = Path.Combine(outputFolder, "urmResult.txt");
+                // if (File.Exists(urmResultFile))
+                // {
+                //     var output = File.ReadAllText(urmResultFile);
+                //     if (!string.IsNullOrWhiteSpace(output))
+                //     {
+                //         return JsonConvert.DeserializeObject<TResult>(output);
+                //     }
+                // }
             }
             catch (Exception ex)
             {
@@ -834,7 +837,7 @@ namespace WingAIDiagnosisService.Service
             return "0";
         }
 
-        private async Task InitURMAnalysisDetails(URMAnalysisV2Result resultData, string originalUrl, string currentFolder, ImgItem originalRemedicalInfo)
+        private async Task InitURMAnalysisDetails(URMAnalysisV2Result resultData, string originalUrl, string currentFolder, ImgItem originalRemedicalInfo, string converImagePath)
         {
             var orginal = new ImgItem
             {
@@ -844,11 +847,10 @@ namespace WingAIDiagnosisService.Service
                 CoverImgUrl = originalRemedicalInfo.CoverImgUrl,
                 PreviewFileUrl = originalRemedicalInfo.PreviewFileUrl,
             };
-            var mergeFile = Path.Combine(currentFolder, "merge.png");
-            if (File.Exists(mergeFile))
+            if (File.Exists(converImagePath))
             {
-                var fileName = Path.GetFileName(mergeFile);
-                var fileInfo = await UploadFileWithSizeAsync(mergeFile, fileName);
+                var fileName = Path.GetFileName(converImagePath);
+                var fileInfo = await UploadFileWithSizeAsync(converImagePath, fileName);
                 orginal.CoverImgUrl = fileInfo.Item1;
                 orginal.PreviewFileUrl = fileInfo.Item1;
             }

BIN
URM/ImagePPMsg.dll


BIN
URM/ImageProcessAlgWrapLib.dll


BIN
URM/UipLab.dll


BIN
URM/VCL.dll


BIN
URM/Vinno.Core.dll


BIN
URM/Vinno.CoreIn.dll


BIN
URM/Vinno.DataManager.dll


BIN
URM/Vinno.GraphTransform.dll


BIN
URM/Vinno.ImagePP.dll


BIN
URM/Vinno.Models.Base.dll


BIN
URM/Vinno.ProcessUnits.DisplayLib.dll


BIN
URM/Vinno.Services.ServiceManager.dll


BIN
URM/binResParseMsg.dll


+ 188 - 0
URMManage/ImagePostProcess.cs

@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using Vinno.DataManager.Infrastructure;
+using Vinno.DataManager.Utilities;
+using Vinno.DataTypes;
+using Vinno.Infrastructure;
+using Vinno.Services.ServiceManagerImpl;
+using static WingAIDiagnosisService.URMManage.UrmProcessRequest;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    internal class ImagePostProcess
+    {
+        private URMProcess UrmProcessor;
+
+        bool URMProcessInitSuccess;
+
+        public static List<URMProcessorClass> VideoProcessorList = new List<URMProcessorClass>();
+
+        /// <summary>
+        /// URM后处理 Draw Image
+        /// </summary>
+        /// <param name="request"></param>
+        public string DoUrmProcess(UrmProcessRequest request)
+        {
+            var imgBase64 = "";
+            try
+            {
+                InitURMProcess(request);
+                if (URMProcessInitSuccess)
+                {
+                    UrmProcessor.CalTracePointMask(request.UrmTraceDPoints);
+                    imgBase64 = UrmProcessor.getURMImageBase64();
+                }
+                UrmProcessor.Dispose();
+            }
+            catch (Exception ex)
+            {
+
+            }
+            return imgBase64;
+        }
+
+        /// <summary>
+        /// URM后处理 Measure Test
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public URMMeasureDataOutput MeasureProcess(UrmMeasureProcessRequest request)
+        {
+            try
+            {
+                InitURMProcess(request);
+                double urmMaxVal = 0;
+                double urmMinVal = 0;
+                if (URMProcessInitSuccess)
+                {
+                    UrmProcessor.getUrmVal(ref urmMaxVal, ref urmMinVal);
+                }
+                int samplingPoints = 256; // 采样点数量 (cmlength 不传的话,默认是 256)
+                if (request.CMlength != null)
+                {
+                    samplingPoints = (int)(request.CMlength * 1000);
+                }
+                URMMeasure urmMeasure = new URMMeasure(UrmProcessor);
+                var param = new URMMeasureDataInput();
+                param.SrcDPoints = request.SrcDPoints;
+                param.phywidth = request.Phywidth;
+                param.RoiType = request.ROIType;
+                param.SamplingPoints = samplingPoints;
+                param.urmMeasureType = request.UrmMeasureType;
+                param.ShellWidth = request.ShellWidth;
+                URMMeasureDataOutput outresult = urmMeasure.CalURMData(param, request.ScreenWidth, request.ScreenHeight, urmMaxVal, urmMinVal);
+                UrmProcessor.Dispose();
+                return outresult;
+            }
+            catch (Exception ex)
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// URM后处理 Draw One frame
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public string DoUrmVideoProcess(DoUrmVideoProcessRequest request)
+        {
+            var imgBase64 = "";
+            InitVideoProcessor(request);
+            try
+            {
+                var videoProcessor = VideoProcessorList.FirstOrDefault(x => x.GUID == request.GUID);
+                videoProcessor.LastActiveTime = DateTime.UtcNow;
+                imgBase64 = videoProcessor.VideoProcessor.getURMVideoImg(request.VideoFrame);
+            }
+            catch
+            {
+
+            }
+            return imgBase64;
+        }
+
+
+        private void InitVideoProcessor(DoUrmVideoProcessRequest request)
+        {
+
+            try
+            {
+                if (!VideoProcessorList.Select(x => x.GUID).Contains(request.GUID))
+                {
+                    NativeArray DenArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.DenDataPath, request.Urmsrcwidth * request.Urmsrcheight); //Den的分析后数据
+                    NativeArray DirArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.DirDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Dir的分析后数据
+                    NativeArray VelArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.VelDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Vel的分析后数据
+                    NativeArray AngleArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.AngleDataPath, request.Urmsrcwidth * request.Urmsrcheight); // 360图的数据
+                    NativeArray MaskArray = ResultDataIOHelper.ReadByteArrayFromFile(request.MaskDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Mask
+                    URMPoint[] URMPoints = ResultDataIOHelper.ReadURMPointsFromFile(request.PointsDataPath);
+                    int[] URMPointNums = ResultDataIOHelper.ReadURMPointNumsFromFile(request.PointNumsDataPath);
+                    // 参数设置
+                    var videoProcessor = new URMProcess();
+                    bool initSuccess = videoProcessor.init(request.FamilyName, request.TypeInfo, request.NativeId);
+                    // 设置视频配置
+                    videoProcessor.setUrmParams(RecordParams.URMVideoScaler, request.URMVideoScaler);
+                    videoProcessor.setUrmParams(RecordParams.URMVideoParameter, request.URMVideoParameter);
+                    videoProcessor.setUrmParams(RecordParams.URMVideoType, request.URMVideoType);
+                    // 设置图像配置
+                    videoProcessor.setUrmParams(RecordParams.UrmImageType, request.UrmImageType);
+                    videoProcessor.setUrmParams(RecordParams.UrmBlend, request.UrmBlend);
+                    videoProcessor.setUrmParams(RecordParams.URMDownSampleIndex, request.DownsampleIndex);
+                    videoProcessor.setUrmParams(RecordParams.URMIntPowerDen, request.IntPowerDen);
+                    videoProcessor.setUrmParams(RecordParams.URMIntPowerDir, request.IntPowerDir);
+                    videoProcessor.setUrmParams(RecordParams.URMSigmaGauss, request.SigmaGauss);
+                    videoProcessor.setUrmParams(RecordParams.URMVessScale, request.VessScale);
+                    videoProcessor.setUrmParams(RecordParams.URMVelMaxScaler, request.VelMaxScaler);
+                    videoProcessor.setUrmParams(RecordParams.URMVelMinScaler, request.VelMinScaler);
+                    videoProcessor.setUrmParams(RecordParams.URMIterations, request.Iterations);
+                    videoProcessor.setUrmBaseParam(request.Res, DenArray, DirArray, VelArray, AngleArray, MaskArray, request.Urmsrcwidth, request.Urmsrcheight, request.ScaleOfPixel_x, request.ScaleOfPixel_y, request.ImgProcessVer, request.Isliner
+                        );
+                    videoProcessor.setUrmDrawParam(request.ZoomOn, request.ZoomRoix, request.ZoomRoiy, request.ZoomRoiwidth, request.ZoomRoiheight, request.Roix, request.Roiy, request.Roiwidth, request.Roiheight, request.LeftRight, request.UpDown, request.ScreenWidth, request.ScreenHeight
+                        );
+                    videoProcessor.PreURMVideo(URMPoints, URMPointNums);
+                    videoProcessor.CalTracePointMask(request.UrmTraceDPoints);
+                    VideoProcessorList.Add(new URMProcessorClass { GUID = request.GUID, VideoProcessor = videoProcessor, LastActiveTime = DateTime.UtcNow });
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+
+
+
+        private void InitURMProcess(UrmProcessRequest request)
+        {
+            NativeArray DenArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.DenDataPath, request.Urmsrcwidth * request.Urmsrcheight); //Den的分析后数据
+            NativeArray DirArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.DirDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Dir的分析后数据
+            NativeArray VelArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.VelDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Vel的分析后数据
+            NativeArray AngleArray = ResultDataIOHelper.ReadDoubleArrayFromFile(request.AngleDataPath, request.Urmsrcwidth * request.Urmsrcheight); // 360图的数据
+            NativeArray MaskArray = ResultDataIOHelper.ReadByteArrayFromFile(request.MaskDataPath, request.Urmsrcwidth * request.Urmsrcheight); // Mask
+                                                                                                                                                // 参数设置
+            UrmProcessor = new URMProcess();
+            URMProcessInitSuccess = UrmProcessor.init(request.FamilyName, request.TypeInfo, request.NativeId);
+            UrmProcessor.setUrmParams(RecordParams.UrmImageType, request.UrmImageType);
+            UrmProcessor.setUrmParams(RecordParams.UrmBlend, request.UrmBlend);
+            UrmProcessor.setUrmParams(RecordParams.URMDownSampleIndex, request.DownsampleIndex);
+            UrmProcessor.setUrmParams(RecordParams.URMIntPowerDen, request.IntPowerDen);
+            UrmProcessor.setUrmParams(RecordParams.URMIntPowerDir, request.IntPowerDir);
+            UrmProcessor.setUrmParams(RecordParams.URMSigmaGauss, request.SigmaGauss);
+            UrmProcessor.setUrmParams(RecordParams.URMVessScale, request.VessScale);
+            UrmProcessor.setUrmParams(RecordParams.URMVelMaxScaler, request.VelMaxScaler);
+            UrmProcessor.setUrmParams(RecordParams.URMVelMinScaler, request.VelMinScaler);
+            UrmProcessor.setUrmParams(RecordParams.URMIterations, request.Iterations);
+            UrmProcessor.setUrmBaseParam(request.Res, DenArray, DirArray, VelArray, AngleArray, MaskArray, request.Urmsrcwidth, request.Urmsrcheight, request.ScaleOfPixel_x, request.ScaleOfPixel_y, request.ImgProcessVer, request.Isliner
+                );
+            UrmProcessor.setUrmDrawParam(request.ZoomOn, request.ZoomRoix, request.ZoomRoiy, request.ZoomRoiwidth, request.ZoomRoiheight, request.Roix, request.Roiy, request.Roiwidth, request.Roiheight, request.LeftRight, request.UpDown, request.ScreenWidth, request.ScreenHeight
+                );
+        }
+
+
+    }
+}
+

+ 27 - 0
URMManage/NativeProxy.cs

@@ -0,0 +1,27 @@
+using System.Runtime.InteropServices;
+using System.Text;
+using Vinno.Infrastructure;
+using Vinno.Services.ServiceManagerImpl;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class NativeProxy
+    {
+        [DllImport("VCL.dll", CharSet = CharSet.Ansi, EntryPoint = "UpdateSection")]
+        private static extern void UpdateSectionImpl(string section, string key, string value);
+
+        [DllImport("VCL.dll", CharSet = CharSet.Ansi)]
+        public static extern void GetValue(string section, string key, StringBuilder lpString, int maxCount);
+
+        public static void UpdateSection(string section, string key, string value, bool logit = true)
+        {
+            Logger.ForceWriteLineIf(logit, "UpdateSection({0}.{1}: {2})", section, key, value);
+            
+            var resourceManager = (ResourceManagerImpl)ResourceManager.Manager;
+            resourceManager.UpdateDefaultValue(section, key, value);
+            UpdateSectionImpl(section, key, value);
+        }
+
+    }
+}
+

+ 147 - 0
URMManage/ResultDataIOHelper.cs

@@ -0,0 +1,147 @@
+using System;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using Vinno.DataManager.Utilities;
+using Vinno.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class ResultDataIOHelper
+    {
+
+        public static void WriteArrayToFile(string filePath, NativeArray array, int length)
+        {
+            using (BinaryWriter writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
+            {
+                unsafe
+                {
+                    double* data = (double*)array.Start.ToPointer();
+                    for (int i = 0; i < length; i++)
+                    {
+                        writer.Write(data[i]);
+                    }
+                }
+            }
+        }
+
+        public static void WriteByteArrayToFile(string filePath, NativeArray array, int length)
+        {
+            using (BinaryWriter writer = new BinaryWriter(File.Open(filePath, FileMode.Create)))
+            {
+                unsafe
+                {
+                    byte* data = (byte*)array.Start.ToPointer();
+                    for (int i = 0; i < length; i++)
+                    {
+                        writer.Write(data[i]);
+                    }
+                }
+            }
+        }
+        
+        public static bool WriteURMPointsToFile(string filepath, URMPoint[] points)
+        {
+            try
+            {
+                using (FileStream stream = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.None))
+                {
+                    BinaryFormatter formatter = new BinaryFormatter();
+                    formatter.Serialize(stream, points);
+                }
+                return true;
+            }
+            catch (Exception e)
+            {
+                // Console.WriteLine("An error occurred while writing to file: " + e.Message);
+                return false;
+            }
+        }
+
+        public static bool WriteURMPointNumsToFile(string filepath, int[] nums)
+        {
+            try
+            {
+                using (FileStream stream = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.None))
+                {
+                    BinaryFormatter formatter = new BinaryFormatter();
+                    formatter.Serialize(stream, nums);
+                }
+                return true;
+            }
+            catch (Exception e)
+            {
+                // Console.WriteLine("An error occurred while writing to file: " + e.Message);
+                return false;
+            }
+        }
+        
+        public static NativeArray ReadDoubleArrayFromFile(string filePath, int length)
+        {
+            NativeArray array = new NativeArray(length * 8);
+            using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
+            {
+                unsafe
+                {
+                    double* data = (double*)array.Start.ToPointer();
+                    for (int i = 0; i < length; i++)
+                    {
+                        data[i] = reader.ReadDouble();
+                    }
+                }
+            }
+            return array;
+        }
+
+        public static NativeArray ReadByteArrayFromFile(string filePath, int length)
+        {
+            NativeArray array = new NativeArray(length);
+            using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
+            {
+                unsafe
+                {
+                    byte* data = (byte*)array.Start.ToPointer();
+                    for (int i = 0; i < length; i++)
+                    {
+                        data[i] = reader.ReadByte();
+                    }
+                }
+            }
+            return array;
+        }
+
+        public static URMPoint[] ReadURMPointsFromFile(string filepath)
+        {
+            try
+            {
+                using (FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read))
+                {
+                    BinaryFormatter formatter = new BinaryFormatter();
+                    return (URMPoint[])formatter.Deserialize(stream);
+                }
+            }
+            catch (Exception e)
+            {
+                // Console.WriteLine("An error occurred while reading from file: " + e.Message);
+                return null;
+            }
+        }
+
+        public static int[] ReadURMPointNumsFromFile(string filepath)
+        {
+            try
+            {
+                using (FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read))
+                {
+                    BinaryFormatter formatter = new BinaryFormatter();
+                    return (int[])formatter.Deserialize(stream);
+                }
+            }
+            catch (Exception e)
+            {
+                // Console.WriteLine("An error occurred while reading from file: " + e.Message);
+                return null;
+            }
+        }
+    }
+}
+

+ 294 - 0
URMManage/URMAnalysisManager.cs

@@ -0,0 +1,294 @@
+using System;
+using System.IO;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Processing;
+using Vinno.DataTypes;
+using Vinno.Infrastructure;
+using WingInterfaceLibrary.Request.RemedicalAISelected;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class URMAnalysisManager
+    {
+        public URMAnalysisV2Result DoURMAnalysis(string[] args)
+        {
+            AppendEnvironmentPath();
+            var arg2Params = args[3].Split(";");
+            var familyName = "Linear";
+            var typeInfo = "Linear_U5-15LE";
+            var nativeId = "Breast";
+            var VecLens = 568;
+            var Mlas = 128;
+            var FramesGot = 2200;
+            var CenterFrequencyMhz = 4.7;
+            var SupersonicSpeed = 1540;
+            var FrequencyMin = 6.5;
+            var FrameRateDisplay = 101.9;
+            var Depth = 0;
+            var X0 = 0;
+            var Z0 = 0;
+            var ProbeType = "1";
+            var ScaleOfPixel_x = 0.214925914347303;
+            var ScaleOfPixel_y = 0.61038961038961;
+            var section = "URMAnalysisParam:Level4";
+            var MOCOYN = "0";
+            var MidProc_DeciFactor = 1;
+            var VectorStartForMid = 11;
+            var isliner = false;
+            // 前端调用时传入
+            var startX = 47;
+            var startY = 14;
+            var width = 74;
+            var height = 492;
+            int? CustomizedStartFrame = null;
+            int? CustomizedEndFrame = null;
+
+            var UrmDatapath = arg2Params[0];
+            // var familyName = arg2Params[1];
+            // var typeInfo = arg2Params[2];
+            // var nativeId = arg2Params[3];
+            // var VecLens = ConvertToInt(arg2Params[4]);
+            // var Mlas = ConvertToInt(arg2Params[5]);
+            // var FramesGot = ConvertToInt(arg2Params[6]);
+            // var CenterFrequencyMhz = ConvertToDouble(arg2Params[7]);
+            // var SupersonicSpeed = ConvertToInt(arg2Params[8]);
+            // var FrequencyMin = ConvertToDouble(arg2Params[9]);
+            // var FrameRateDisplay = ConvertToDouble(arg2Params[10]);
+            // var Depth = ConvertToInt(arg2Params[11]);
+            // var X0 = ConvertToInt(arg2Params[12]);
+            // var Z0 = ConvertToInt(arg2Params[13]);
+            // var ProbeType = arg2Params[14];
+            // var ScaleOfPixel_x = ConvertToDouble(arg2Params[15]);
+            // var ScaleOfPixel_y = ConvertToDouble(arg2Params[16]);
+            // var section = arg2Params[17];
+            // var MOCOYN = arg2Params[18];
+            // var MidProc_DeciFactor = ConvertToInt(arg2Params[19]);
+            // var VectorStartForMid = ConvertToInt(arg2Params[20]);
+            // var isliner = arg2Params[21]?.ToLower() == "true";
+            // // 前端调用时传入
+            // var startX = ConvertToInt(arg2Params[22]);
+            // var startY = ConvertToInt(arg2Params[23]);
+            // var width = ConvertToInt(arg2Params[24]);
+            // var height = ConvertToInt(arg2Params[25]);
+            // int? CustomizedStartFrame = ConvertToIntCanNull(arg2Params[26]);
+            // int? CustomizedEndFrame = ConvertToIntCanNull(arg2Params[27]);
+            var roiXPercent = ConvertToDouble(arg2Params[28]);
+            var roiYPercent = ConvertToDouble(arg2Params[29]);
+            var roiWPercent = ConvertToDouble(arg2Params[30]);
+            var roiHPercent = ConvertToDouble(arg2Params[31]);
+            // 开始执行分析
+            URMFileIO urmFileIO = new URMFileIO(familyName: familyName, typeInfo: typeInfo, nativeId: nativeId);
+            urmFileIO.UpdateParamJson(UrmDatapath, VecLens, Mlas, FramesGot, CenterFrequencyMhz, SupersonicSpeed, FrequencyMin, FrameRateDisplay, Depth, X0, Z0, ProbeType, ScaleOfPixel_x, ScaleOfPixel_y, section, MOCOYN, MidProc_DeciFactor, VectorStartForMid, startX, startY, width, height, CustomizedStartFrame, CustomizedEndFrame, out string urmParams);
+
+            var modeRecord = new URMAnalysisModeRecord();
+            try
+            {
+                var outputFolder = args[1];
+                if (!Directory.Exists(outputFolder))
+                {
+                    Directory.CreateDirectory(outputFolder);
+                }
+                bool success = URMAnalysisProcess.GetInstance().URMAnalysis(urmParams, modeRecord);
+                // 读取输出
+                var SrcWidth = modeRecord.URMSrcWidth;
+                var SrcHeight = modeRecord.URMSrcHeight;
+                var denPath = Path.Combine(outputFolder, "srcDenArray.bin");
+                var dirPath = Path.Combine(outputFolder, "srcDirArray.bin");
+                var velPath = Path.Combine(outputFolder, "srcVelArray.bin");
+                var angelPath = Path.Combine(outputFolder, "srcAngleArray.bin");
+                var maskPath = Path.Combine(outputFolder, "srcMaskArray.bin");
+                var pointsPath = Path.Combine(outputFolder, "URMPoints.bin");
+                var pointNumsPath = Path.Combine(outputFolder, "URMPointNums.bin");
+                ResultDataIOHelper.WriteArrayToFile(denPath, modeRecord.URMDenArray, SrcWidth * SrcHeight);
+                ResultDataIOHelper.WriteArrayToFile(dirPath, modeRecord.URMDirArray, SrcWidth * SrcHeight);
+                ResultDataIOHelper.WriteArrayToFile(velPath, modeRecord.URMVelArray, SrcWidth * SrcHeight);
+                ResultDataIOHelper.WriteArrayToFile(angelPath, modeRecord.URMAngleImgArray, SrcWidth * SrcHeight);
+                ResultDataIOHelper.WriteByteArrayToFile(maskPath, modeRecord.URMMask, SrcWidth * SrcHeight);
+                ResultDataIOHelper.WriteURMPointsToFile(pointsPath, modeRecord.URMPoints);
+                ResultDataIOHelper.WriteURMPointNumsToFile(pointNumsPath, modeRecord.URMPointNums);
+
+                var coverFile = args[2];
+                int coverImageWidth = 0;
+                int coverImageHeight = 0;
+                using (var image = Image.Load(coverFile))
+                {
+                    coverImageWidth = image.Width;
+                    coverImageHeight = image.Height;
+                }
+                var urmProcess = new ImagePostProcess();
+                var imgBase64 = urmProcess.DoUrmProcess(new UrmProcessRequest
+                {
+                    FamilyName = familyName,
+                    TypeInfo = typeInfo,
+                    NativeId = nativeId,
+                    Isliner = isliner,
+                    ScaleOfPixel_x = ScaleOfPixel_x,
+                    ScaleOfPixel_y = ScaleOfPixel_y,
+                    Urmsrcwidth = SrcWidth,
+                    Urmsrcheight = SrcHeight,
+                    DenDataPath = denPath,
+                    DirDataPath = dirPath,
+                    VelDataPath = velPath,
+                    AngleDataPath = angelPath,
+                    MaskDataPath = maskPath,
+                    Res = modeRecord.URMRes,
+                    UrmImageType = "0",
+                    UrmBlend = true,
+                    DownsampleIndex = 3,
+                    IntPowerDen = 4,
+                    IntPowerDir = 4,
+                    SigmaGauss = 2.4f,
+                    VessScale = 1,
+                    VelMaxScaler = 1,
+                    VelMinScaler = 0,
+                    Iterations = 1,
+                    ImgProcessVer = 1,
+                    ZoomOn = false,
+                    ZoomRoix = 0,
+                    ZoomRoiy = 0,
+                    ZoomRoiwidth = 1,
+                    ZoomRoiheight = 1,
+                    LeftRight = false,
+                    UpDown = false,
+                    UrmTraceDPoints = new DPoint[] { },
+                    Roix = (int)(coverImageWidth * roiXPercent),
+                    Roiy = (int)(coverImageHeight * roiYPercent),
+                    Roiwidth = (int)(coverImageWidth * roiWPercent),
+                    Roiheight = (int)(coverImageHeight * roiHPercent),
+                    ScreenWidth = coverImageWidth,
+                    ScreenHeight = coverImageHeight,
+                });
+                var mergeFilePath = coverFile;
+                if (!string.IsNullOrWhiteSpace(imgBase64))
+                {
+                    mergeFilePath = Path.Combine(outputFolder, $"{Guid.NewGuid():N}.png");
+                    using (var image1 = Image.Load(coverFile))
+                    {
+                        // 将base64字符串转换为字节数组
+                        byte[] bytes = Convert.FromBase64String(imgBase64);
+
+                        // 将字节数组转换为Image对象
+                        using (var image2 = Image.Load(bytes))
+                        {
+                            // 将第二张图片画在第一张图片上
+                            image1.Mutate(ctx => ctx.DrawImage(image2, new Point(0, 0), 1f));
+
+                            // 保存合成后的图片
+                            image1.Save(mergeFilePath);
+                        }
+                    }
+                }
+
+                var outMsg = new URMAnalysisV2Result
+                {
+                    URMSrcWidth = modeRecord.URMSrcWidth,
+                    URMSrcHeight = modeRecord.URMSrcHeight,
+                    URMRes = modeRecord.URMRes,
+                    ConverImageUrl = mergeFilePath,
+                };
+                return outMsg;
+            }
+            catch (Exception ex)
+            {
+
+            }
+            return null;
+        }
+
+
+        private void AppendEnvironmentPath()
+        {
+            var urmFolder = Path.Combine(ServiceManager.RootPath, "URM");
+            var privatePath = @$"C:\VinnoApp_Lab\Depends;C:\VinnoApp_Lab\ipp_2018;AIMeasure;AI;Depends;DicomMpeg;Syncfusion;RemoteDiagnosis;vCloud;Test;VFetus;{urmFolder}";
+            bool enforcePentiumMode = false;
+            string workPathPerCPU = string.Empty;
+            string workPathForGPU = string.Empty;
+            workPathPerCPU = Path.Combine(ServiceManager.RootPath, "NON_PENTIUM");
+
+            privatePath = privatePath + ";" + workPathPerCPU + ";";
+
+            string gpuName = string.Empty;
+
+            workPathForGPU = Path.Combine(ServiceManager.RootPath, "NVIDIA");
+
+            if (!string.IsNullOrEmpty(workPathForGPU))
+            {
+                privatePath = privatePath + workPathForGPU + ";";
+            }
+
+            if (!string.IsNullOrEmpty(privatePath))
+            {
+                string path = Environment.GetEnvironmentVariable("PATH");
+                string newPath = string.Empty;
+                if (path != null)
+                {
+                    string upperPath = path.ToUpper();
+                    var subPathes = privatePath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+                    foreach (var subPath in subPathes)
+                    {
+                        VinnoDirectoryInfo dir = null;
+                        if (Path.IsPathRooted(subPath))
+                        {
+                            dir = new VinnoDirectoryInfo(subPath);
+                        }
+                        else
+                        {
+                            dir = new VinnoDirectoryInfo(Path.Combine(ServiceManager.RootPath, subPath));
+                        }
+                        if (dir.Exists)
+                        {
+                            var fullName = dir.FullName;
+                            if (!upperPath.Contains(fullName.ToUpper()))
+                            {
+                                newPath += ";" + fullName;
+                            }
+                        }
+                    }
+
+                    if (!string.IsNullOrEmpty(newPath))
+                    {
+                        Environment.SetEnvironmentVariable("PATH", newPath + ";" + path, EnvironmentVariableTarget.Process);
+                    }
+                }
+            }
+        }
+
+        private int ConvertToInt(string value)
+        {
+            if (string.IsNullOrWhiteSpace(value))
+            {
+                return 0;
+            }
+            if (int.TryParse(value, out int x))
+            {
+                return x;
+            }
+            return 0;
+        }
+        private int? ConvertToIntCanNull(string value)
+        {
+            if (string.IsNullOrWhiteSpace(value))
+            {
+                return null;
+            }
+            if (int.TryParse(value, out int x))
+            {
+                return x;
+            }
+            return 0;
+        }
+        private double ConvertToDouble(string value)
+        {
+            if (string.IsNullOrWhiteSpace(value))
+            {
+                return 0;
+            }
+            if (double.TryParse(value, out double x))
+            {
+                return x;
+            }
+            return 0;
+        }
+    }
+}
+

+ 29 - 0
URMManage/URMAnalysisModeRecord.cs

@@ -0,0 +1,29 @@
+using Vinno.DataManager.Utilities;
+using Vinno.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class URMAnalysisModeRecord
+    {
+        // 输入部分
+        public double URMRes { get; set; } = 10.0;
+        public int URMStabilizer { get; set; } = 0;
+
+        // 输出部分
+        public double URMScaleOfPixel_x { get; set; }
+        public double URMScaleOfPixel_y { get; set; }
+
+        public RecordNativeArray URMDenArray { get; set; }
+        public RecordNativeArray URMDirArray { get; set; }
+        public RecordNativeArray URMVelArray { get; set; }
+        public RecordNativeArray URMAngleImgArray { get; set; }
+        public RecordNativeArray URMMask { get; set; }
+
+        public int URMSrcHeight { get; set; }
+        public int URMSrcWidth { get; set; }
+
+        public URMPoint[] URMPoints { get; set; }
+        public int[] URMPointNums { get; set; }
+    }
+}
+

+ 399 - 0
URMManage/URMAnalysisProcessV3.cs

@@ -0,0 +1,399 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Vinno.Infrastructure;
+using System.Diagnostics;
+using System.IO.MemoryMappedFiles;
+using System.Threading;
+using Vinno.DataManager.Utilities;
+using Vinno.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    [StructLayout(LayoutKind.Sequential)]
+    public class URMAVIParam
+    {
+        public double Res { get; set; }
+        public double ScaleOfPixel_x { get; set; }
+        public double ScaleOfPixel_y { get; set; }
+        public double IntPowerDir { get; set; }
+        public double DownsampleIndexVideo { get; set; }
+        public IntPtr MaskArray { get; set; }
+        public URMAVIParam()
+        {
+            Res = 10;
+            ScaleOfPixel_x = 1.0;
+            ScaleOfPixel_y = 1.0;
+            IntPowerDir = 0.25;
+            DownsampleIndexVideo = 2;
+            MaskArray = IntPtr.Zero;
+        }
+    };
+
+
+
+    public class URMAnalysisProcess
+    {
+
+        private bool initSrMain;
+        private int _urmwidth;
+        private int _urmheight;
+        private int aviFrames;
+        private URMAnalysisModeRecord _urmModeRecord;
+        private Process _SRLibWrapperProcess;
+        private MemoryMappedFile _file;
+        string mapName = "VinnoSrResultV1";
+        private static ManualResetEvent signal = new ManualResetEvent(false);
+        private int urmStabilizer = 0;
+        private static URMAnalysisProcess instance;
+        private bool _processFlag = false;
+        private static readonly bool Debug = true;
+
+        //private IMode _mode; // _mode 只是用于读取一个 urmStabilizer(int) 这里直接省略,先默认为 1,后续直接传入 urmStabilizer
+        private URMAVIParam _urmaviParam;
+        private URMAnalysisProcess()
+        {
+
+            _SRLibWrapperProcess = new Process();
+            var analyzeHostName = Path.Combine(ServiceManager.RootPath, "URM", "NET6.0", "SRLibWrapper.exe");
+            //if (!VinnoFile.Exists(analyzeHostName) || !DigitalSignatureChecker.VerifySignature(analyzeHostName))
+            //{
+            //    Logger.WriteLineErrorIf(Debug, "SRLibWrapper.exe not found or signature is invalid.");
+            //}
+            var startInfo = new ProcessStartInfo
+            {
+                FileName = analyzeHostName,
+                Arguments = $"",
+                CreateNoWindow = true,
+                UseShellExecute = false,
+                RedirectStandardOutput = true,
+                RedirectStandardInput = true,
+                RedirectStandardError = true,
+            };
+            _SRLibWrapperProcess.StartInfo = startInfo;
+            _SRLibWrapperProcess.Start();
+            _SRLibWrapperProcess.OutputDataReceived += OutputHandler;
+            _SRLibWrapperProcess.ErrorDataReceived += OutputHandler;
+            _SRLibWrapperProcess.BeginOutputReadLine();
+            _SRLibWrapperProcess.BeginErrorReadLine();
+
+        }
+        ~URMAnalysisProcess()
+        {
+            if (_file != null)
+                _file.Dispose();
+            if (_SRLibWrapperProcess != null && !_SRLibWrapperProcess.HasExited)
+            {
+                _SRLibWrapperProcess.Kill();
+                _SRLibWrapperProcess.Dispose();
+            }
+        }
+
+        public static URMAnalysisProcess GetInstance()
+        {
+            if (instance == null)
+            {
+                instance = new URMAnalysisProcess();
+            }
+            return instance;
+        }
+
+
+        private void OutputHandler(object sender, DataReceivedEventArgs e)
+        {
+            if (!string.IsNullOrEmpty(e.Data))
+            {
+                if (!e.Data.Contains("SRLibLog"))
+                    return;
+                var infos = e.Data.Split(',');
+                if (!string.IsNullOrEmpty(infos[1]))
+                {
+                    _processFlag = true;
+                    switch (infos[1])
+                    {
+                        case "step1ok":
+                            var needmemorysize = long.Parse(infos[2]);
+                            Logger.ForceWriteLineIf(Debug, "Akio step1ok needmemorysize is {0}", needmemorysize);
+                            if (_file != null)
+                                _file.Dispose();
+                            _file = MemoryMappedFile.CreateNew(mapName, needmemorysize,
+                                MemoryMappedFileAccess.ReadWrite);
+                            var step2info = "Step2," + mapName;
+                            _SRLibWrapperProcess.StandardInput.WriteLine(step2info);
+                            break;
+                        case "step2ok":
+                            Logger.ForceWriteLineIf(Debug, "Akio step2ok");
+                            signal.Set();
+                            break;
+                        case "SRLibFail":
+                            _processFlag = false;
+                            signal.Set();
+                            Logger.WriteLineErrorIf(Debug, "AKio " + e.Data);
+                            break;
+
+                    }
+                }
+            }
+        }
+
+        public bool URMAnalysis(string urmFold, URMAnalysisModeRecord urmModeRecord)
+        {
+            using (new AutoPerformance("Akio:URMAnalysisProcess"))
+            {
+                signal.Reset();
+                if (ResourceManager.GetValue("Product-GeneralSpecification", "UrmParamLogOut", false))
+                {
+                    Logger.ForceWriteLine("Matlab " + urmFold);
+                }
+
+                if (_SRLibWrapperProcess.HasExited)
+                {
+                    var analyzeHostName = Path.Combine(ServiceManager.RootPath, "URM", "NET6.0", "SRLibWrapper.exe");
+                    //if (!VinnoFile.Exists(analyzeHostName) || !DigitalSignatureChecker.VerifySignature(analyzeHostName))
+                    //{
+                    //    Logger.WriteLineErrorIf(Debug, "SRLibWrapper.exe not found or signature is invalid.");
+                    //}
+                    var startInfo = new ProcessStartInfo
+                    {
+                        FileName = analyzeHostName,
+                        Arguments = $"",
+                        CreateNoWindow = false,
+                        UseShellExecute = false,
+                        RedirectStandardOutput = true,
+                        RedirectStandardInput = true,
+                        RedirectStandardError = true,
+                    };
+                    _SRLibWrapperProcess.StartInfo = startInfo;
+                    _SRLibWrapperProcess.Start();
+                    _SRLibWrapperProcess.OutputDataReceived += OutputHandler;
+                    _SRLibWrapperProcess.ErrorDataReceived += OutputHandler;
+                    _SRLibWrapperProcess.BeginOutputReadLine();
+                }
+
+                _urmModeRecord = urmModeRecord;
+                //_mode = Mode;
+                // TODO 通过接口传入 urmStabilizer 的值
+                //urmStabilizer = (int)_mode.Parameters.GetItem<FloatParameter>(RecordParams.URMStabilizer).Value;
+                var step1info = "Step1," + urmStabilizer.ToString() + "," + urmFold;
+                _SRLibWrapperProcess.StandardInput.WriteLine(step1info);
+                int alltime = 0;
+                while (alltime < 1800000)
+                {
+                    if (!signal.WaitOne(5000))
+                    {
+                        alltime += 5000;
+                        if (_SRLibWrapperProcess.HasExited)
+                        {
+                            _processFlag = false;
+                            signal.Set();
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                if (signal.WaitOne() && !_SRLibWrapperProcess.HasExited)
+                {
+                    if (_processFlag)
+                        URMAnalysis();
+                }
+                else
+                {
+                    Logger.WriteLineErrorIf(Debug, "Akio:URMAnalysisi TimeOut Or _SRLibWrapperProcess not exit");
+                }
+                if (_file != null)
+                    _file.Dispose();
+                return _processFlag;
+
+            }
+        }
+
+
+        public bool URMAnalysis()
+        {
+            RecordNativeArray maskArray = new RecordNativeArray(0);
+            using (var accessor = _file.CreateViewAccessor(0, 0))
+            {
+                IntPtr accessorptr = accessor.SafeMemoryMappedViewHandle.DangerousGetHandle();
+                unsafe
+                {
+                    var pointptr = (byte*)accessorptr.ToPointer();
+                    if (urmStabilizer < 2)
+                    {
+                        int packets = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        _urmwidth = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        _urmheight = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        aviFrames = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        if (packets <= 0 || _urmwidth <= 0 || _urmheight <= 0 || aviFrames <= 0)
+                        {
+                            return false;
+                        }
+
+                        var res = _urmModeRecord.URMRes;
+                        var scaleofx = *(float*)pointptr * res;
+                        pointptr += sizeof(float);
+                        var scaleofy = *(float*)pointptr * res;
+                        pointptr += sizeof(float);
+                        //_urmModeRecord.SetParameter(RecordParams.URMScaleOfPixel_x, scaleofx);
+                        //_urmModeRecord.SetParameter(RecordParams.URMScaleOfPixel_y, scaleofy);
+                        _urmModeRecord.URMScaleOfPixel_x = scaleofx;
+                        _urmModeRecord.URMScaleOfPixel_y = scaleofy;
+
+                        maskArray.Resize(_urmwidth * _urmheight * sizeof(byte));
+                        Buffer.MemoryCopy(pointptr, maskArray.Start.ToPointer(), _urmwidth * _urmheight * sizeof(byte), _urmwidth * _urmheight * sizeof(byte));
+                        pointptr += _urmwidth * _urmheight * sizeof(byte);
+
+                        RecordNativeArray matout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matdirout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matdirout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matvelout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matvelout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matangleout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matangleout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        Logger.WriteLineInfo("Akio:_urmBeams is {0},_urmSamples is {1},packets is {2}", _urmwidth,
+                            _urmheight, packets);
+
+
+                        //_urmModeRecord.SetParameter(RecordParams.URMDenArray, matout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMDirArray, matdirout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMVelArray, matvelout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMAngleImgArray, matangleout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMMask, maskArray, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMSrcHeight, _urmheight, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMSrcWidth, _urmwidth, TimeStamp.ErrorTime);
+                        _urmModeRecord.URMDenArray = matout;  // RecordNativeArray
+                        _urmModeRecord.URMDirArray = matdirout; // RecordNativeArray
+                        _urmModeRecord.URMVelArray = matvelout; // RecordNativeArray
+                        _urmModeRecord.URMAngleImgArray = matangleout; // RecordNativeArray
+                        _urmModeRecord.URMMask = maskArray; // RecordNativeArray
+                        _urmModeRecord.URMSrcHeight = _urmheight; // int
+                        _urmModeRecord.URMSrcWidth = _urmwidth; // int
+
+
+                        int[] PointNumList = new int[aviFrames];
+                        for (int i = 0; i < aviFrames; i++)
+                        {
+                            PointNumList[i] = *(int*)pointptr;
+                            pointptr += sizeof(int);
+                        }
+
+                        var AllPointNum = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        var pointsArray = new URMPoint[AllPointNum];
+                        int sizeOfPoint = Marshal.SizeOf<URMPoint>();
+                        int totalSize = sizeOfPoint * AllPointNum;
+                        fixed (URMPoint* PointsArrayptr = pointsArray)
+                        {
+                            Buffer.MemoryCopy(pointptr, PointsArrayptr, totalSize, totalSize);
+                        }
+                        //_urmModeRecord.SetParameter(RecordParams.URMPoints, pointsArray, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMPointNums, PointNumList, TimeStamp.ErrorTime);
+                        _urmModeRecord.URMPoints = pointsArray; // URMPoint[]
+                        _urmModeRecord.URMPointNums = PointNumList; // int[]
+                    }
+                    else
+                    {
+                        _urmwidth = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        _urmheight = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        aviFrames = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        if (_urmwidth <= 0 || _urmheight <= 0 || aviFrames <= 0)
+                        {
+                            return false;
+                        }
+
+                        //var res = _urmModeRecord.GetParameter(RecordParams.URMRes, 10.0);
+                        var res = _urmModeRecord.URMRes;
+                        var scaleofx = *(float*)pointptr * res;
+                        pointptr += sizeof(float);
+                        var scaleofy = *(float*)pointptr * res;
+                        pointptr += sizeof(float);
+                        //_urmModeRecord.SetParameter(RecordParams.URMScaleOfPixel_x, scaleofx);
+                        //_urmModeRecord.SetParameter(RecordParams.URMScaleOfPixel_y, scaleofy);
+                        _urmModeRecord.URMScaleOfPixel_x = scaleofx;
+                        _urmModeRecord.URMScaleOfPixel_y = scaleofy;
+
+                        maskArray.Resize(_urmwidth * _urmheight * sizeof(byte));
+
+                        Buffer.MemoryCopy(pointptr, maskArray.Start.ToPointer(), _urmwidth * _urmheight * sizeof(byte), _urmwidth * _urmheight * sizeof(byte));
+                        pointptr += _urmwidth * _urmheight * sizeof(byte);
+
+                        RecordNativeArray matangleout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matangleout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matdirout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matdirout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        RecordNativeArray matvelout = new RecordNativeArray(_urmwidth * _urmheight * sizeof(double));
+                        Buffer.MemoryCopy(pointptr, matvelout.Start.ToPointer(), _urmwidth * _urmheight * sizeof(double), _urmwidth * _urmheight * sizeof(double));
+                        pointptr += _urmwidth * _urmheight * sizeof(double);
+
+                        Logger.WriteLineInfo("Akio:_urmBeams is {0},_urmSamples is {1}", _urmwidth,
+                            _urmheight);
+
+                        //_urmModeRecord.SetParameter(RecordParams.URMDenArray, matout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMDirArray, matdirout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMVelArray, matvelout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMAngleImgArray, matangleout, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMMask, maskArray, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMSrcHeight, _urmheight, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMSrcWidth, _urmwidth, TimeStamp.ErrorTime);
+                        _urmModeRecord.URMDenArray = matout;  // RecordNativeArray
+                        _urmModeRecord.URMDirArray = matdirout; // RecordNativeArray
+                        _urmModeRecord.URMVelArray = matvelout; // RecordNativeArray
+                        _urmModeRecord.URMAngleImgArray = matangleout; // RecordNativeArray
+                        _urmModeRecord.URMMask = maskArray; // RecordNativeArray
+                        _urmModeRecord.URMSrcHeight = _urmheight; // int
+                        _urmModeRecord.URMSrcWidth = _urmwidth;
+                        int[] PointNumList = new int[aviFrames];
+                        for (int i = 0; i < aviFrames; i++)
+                        {
+                            PointNumList[i] = *(int*)pointptr;
+                            pointptr += sizeof(int);
+                        }
+
+                        var AllPointNum = *(int*)pointptr;
+                        pointptr += sizeof(int);
+                        var pointsArray = new URMPoint[AllPointNum];
+                        int sizeOfPoint = Marshal.SizeOf<URMPoint>();
+                        int totalSize = sizeOfPoint * AllPointNum;
+                        fixed (URMPoint* PointsArrayptr = pointsArray)
+                        {
+                            Buffer.MemoryCopy(pointptr, PointsArrayptr, totalSize, totalSize);
+                        }
+                        //_urmModeRecord.SetParameter(RecordParams.URMPoints, pointsArray, TimeStamp.ErrorTime);
+                        //_urmModeRecord.SetParameter(RecordParams.URMPointNums, PointNumList, TimeStamp.ErrorTime);
+                        _urmModeRecord.URMPoints = pointsArray; // URMPoint[]
+                        _urmModeRecord.URMPointNums = PointNumList; // int[]
+                    }
+
+                }
+            }
+            return true;
+        }
+    }
+}
+

+ 140 - 0
URMManage/URMFileIO.cs

@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+using Newtonsoft.Json;
+using Vinno.DataManager.Process;
+using Vinno.Infrastructure;
+using Vinno.Services.ServiceManagerImpl;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class URMAnalysisParam
+    {
+        public string UrmDatapath { get; set; }
+        public string VecLens { get; set; }
+        public string Mlas { get; set; }
+        public string FramesGot { get; set; }
+        public string CenterFrequencyMHz { get; set; }
+        public string SupersonicSpeed { get; set; }
+        public string FrequencyMin { get; set; }
+        public string FrameRateDisplay { get; set; }
+        public string ScaleOfPixel_x { get; set; }
+        public string ScaleOfPixel_y { get; set; }
+        public string ULMCount { get; set; }
+        public string PacketsNum { get; set; }
+        public string Res { get; set; }
+        public string MaxLinkingDistance { get; set; }
+        public string MinLength { get; set; }
+        public string MaxGapClosing { get; set; }
+        public string LocMethod { get; set; }
+        public string NLocalMax { get; set; }
+        public string Fwhm { get; set; }
+        public string MOCOYN { get; set; }
+        public string MOCOLevel { get; set; }
+        public string MOCOThresh1 { get; set; }
+        public string MOCOThresh2 { get; set; }
+        public string MOCOThresh3 { get; set; }
+        public string LocaFixmethod { get; set; }
+        public string LocFixThresh { get; set; }
+        public string MotionCorrThresh { get; set; }
+        public string Pos { get; set; }
+        public string FilterDeci { get; set; }
+        public string PSFNum { get; set; }
+        public string PSFCorr { get; set; }
+
+        public string Depth { get; set; }
+
+        public string X0 { get; set; }
+
+        public string Z0 { get; set; }
+
+        public string ProbeType { get; set; }
+
+        public string SizeScan { get; set; }
+        public string MotionAngleThresh { get; set; }
+
+        public string TrackInterpFactor { get; set; }
+
+        public string FrameStart { get; set; }
+        public string FrameEnd { get; set; }
+    }
+
+    //负责URM的参数文件读写
+    public class URMFileIO
+    {
+        protected ImagePP ImagePPRes;
+
+        public URMFileIO(string familyName, string typeInfo, string nativeId)
+        {
+            ResourceManagerImpl resourceManager = new ResourceManagerImpl(Path.Combine(ServiceManager.RootPath, "URM", "dev"));
+            ResourceManager.Initialize(resourceManager);
+            var dir = new VinnoDirectoryInfo(Path.Combine(ServiceManager.RootPath, "URM"));
+            NativeProxy.UpdateSection("Path", "ShippedRoot", dir.FullName);
+            NativeProxy.UpdateSection("Product-GeneralSpecification", "ImagePPFileName", "ImagePP_Tulip");
+            if (ServiceManager.Os.IsWin())
+            {
+                ImagePPRes = new ImagePPNative_Win();
+            }
+            else
+            {
+                ImagePPRes = new ImagePPNative();
+            }
+            ImagePPRes.Initial();
+            Logger.WriteLineInfo("ImagePPRes Initial", familyName, typeInfo, nativeId);
+            ImagePPRes.Initial(familyName, typeInfo, nativeId);
+        }
+
+        public void UpdateParamJson(String UrmDatapath, int VecLens, int Mlas, int FramesGot, double CenterFrequencyMhz, int SupersonicSpeed, double FrequencyMin, double FrameRateDisplay, double Depth, double X0, double Z0, string ProbeType, double ScaleOfPixel_x, double ScaleOfPixel_y, string section, string MOCOYN, int MidProc_DeciFactor, int VectorStartForMid, int startX, int startY, int width, int height, int? CustomizedStartFrame, int? CustomizedEndFrame, out string parms)
+        {
+            var urmnalysisparams = new URMAnalysisParam();
+            urmnalysisparams.UrmDatapath = UrmDatapath;
+            urmnalysisparams.VecLens = VecLens.ToString();
+            urmnalysisparams.Mlas = Mlas.ToString();
+            urmnalysisparams.FramesGot = FramesGot.ToString();
+            urmnalysisparams.CenterFrequencyMHz = CenterFrequencyMhz.ToString();
+            urmnalysisparams.SupersonicSpeed = SupersonicSpeed.ToString();
+            urmnalysisparams.FrequencyMin = FrequencyMin.ToString();
+            urmnalysisparams.FrameRateDisplay = FrameRateDisplay.ToString();
+            urmnalysisparams.Depth = Depth.ToString();
+            urmnalysisparams.X0 = X0.ToString();
+            urmnalysisparams.Z0 = Z0.ToString();
+            urmnalysisparams.ProbeType = ProbeType;
+            urmnalysisparams.ScaleOfPixel_x = ScaleOfPixel_x.ToString();
+            urmnalysisparams.ScaleOfPixel_y = ScaleOfPixel_y.ToString();
+            urmnalysisparams.ULMCount = ImagePPRes.GetValue(section, "ULMCount", 400).ToString();
+            urmnalysisparams.PacketsNum = ImagePPRes.GetValue(section, "PacketsNum", 200).ToString();
+            urmnalysisparams.Res = ImagePPRes.GetValue(section, "Res", 10.0d).ToString();
+            urmnalysisparams.MaxLinkingDistance = ImagePPRes.GetValue(section, "MaxLinkingDistance", 2.0).ToString();
+            urmnalysisparams.MinLength = ImagePPRes.GetValue(section, "MinLength", 5.0).ToString();
+            urmnalysisparams.MaxGapClosing = ImagePPRes.GetValue(section, "MaxGapClosing", 0).ToString();
+            urmnalysisparams.LocMethod = ImagePPRes.GetValue(section, "LocMethod", "radial");
+            urmnalysisparams.NLocalMax = ImagePPRes.GetValue(section, "NLocalMax", 3).ToString();
+            urmnalysisparams.Fwhm = ImagePPRes.GetValue(section, "Fwhm", 3).ToString();
+            urmnalysisparams.MOCOYN = MOCOYN.ToString();
+            urmnalysisparams.MOCOLevel = ImagePPRes.GetValue(section, "MOCOLevel", 0.05).ToString();
+            urmnalysisparams.MOCOThresh1 = ImagePPRes.GetValue(section, "MOCOThresh1", 0.05).ToString();
+            urmnalysisparams.MOCOThresh2 = ImagePPRes.GetValue(section, "MOCOThresh2", 0.05).ToString();
+            urmnalysisparams.MOCOThresh3 = ImagePPRes.GetValue(section, "MOCOThresh3", 5).ToString();
+            urmnalysisparams.LocaFixmethod = ImagePPRes.GetValue(section, "LocaFixmethod", "fixgray");
+            urmnalysisparams.LocFixThresh = ImagePPRes.GetValue(section, "LocFixThresh", 15).ToString();
+            urmnalysisparams.MotionCorrThresh = ImagePPRes.GetValue(section, "MotionCorrThresh", 0.5).ToString();
+            var roiInfo = $" {startX},{startY * MidProc_DeciFactor + VectorStartForMid},{width},{height * MidProc_DeciFactor} ";
+            urmnalysisparams.Pos = roiInfo;
+            urmnalysisparams.FilterDeci = ImagePPRes.GetValue(section, "FilterDeci", 1).ToString();
+            urmnalysisparams.PSFNum = ImagePPRes.GetValue(section, "PSFNum", 10).ToString();
+            urmnalysisparams.PSFCorr = ImagePPRes.GetValue(section, "PSFCorr", 0.5).ToString();
+            urmnalysisparams.SizeScan = Math.Min(VecLens, 1024).ToString();
+            urmnalysisparams.MotionAngleThresh = ImagePPRes.GetValue(section, "MotionAngleThresh", 2).ToString();
+            urmnalysisparams.TrackInterpFactor = ImagePPRes.GetValue(section, "TrackInterpFactor", 0.8).ToString();
+            int starttime;
+            int endtime;
+            starttime = CustomizedStartFrame ?? 1;
+            endtime = CustomizedEndFrame ?? FramesGot;
+            starttime = Math.Min(starttime, FramesGot - 200);
+            endtime = Math.Min(endtime, FramesGot);
+            urmnalysisparams.FrameStart = starttime.ToString();
+            urmnalysisparams.FrameEnd = endtime.ToString();
+            parms = JsonConvert.SerializeObject(urmnalysisparams);
+        }
+    }
+}
+

+ 44 - 0
URMManage/URMMeasure.cs

@@ -0,0 +1,44 @@
+using System.Runtime.InteropServices;
+using System.Text;
+using Vinno.DataTypes;
+using Vinno.Infrastructure;
+using Vinno.Services.ServiceManagerImpl;
+
+namespace WingAIDiagnosisService.URMManage
+{
+
+    public class URMMeasure
+    {
+        private URMMeasureAlg _urmMeasureAlg;
+
+        public URMMeasure(URMProcess processor)
+        {
+            _urmMeasureAlg = new URMMeasureAlg(processor);
+        }
+
+        public void SetScreenSize(int width, int height)
+        {
+            _urmMeasureAlg._URMDenMeasureImg.Resize(width * height);
+            _urmMeasureAlg._URMVelMeasureImg.Resize(width * height);
+        }
+
+        public URMMeasureDataOutput CalURMData(URMMeasureDataInput arg, int screenWidth, int screenHeight, double urmMaxVel, double urmMinVel)
+        {
+            SetScreenSize(screenWidth, screenHeight);
+            var inparam = (URMMeasureDataInput)arg;
+            var outresult = new URMMeasureDataOutput();
+            if (screenWidth > 1 && screenHeight > 1)
+            {
+                outresult = _urmMeasureAlg.CalURMMeasureData(inparam, screenWidth, screenHeight, urmMaxVel, urmMinVel);
+                outresult.ResultFlag = true;
+            }
+            return outresult;
+        }
+
+        public void Dispose()
+        {
+            _urmMeasureAlg.Relase();
+        }
+    }
+}
+

+ 332 - 0
URMManage/URMMeasureAlg.cs

@@ -0,0 +1,332 @@
+using System.Runtime.InteropServices;
+using Vinno.Infrastructure;
+using System;
+using Vinno.DataTypes;
+using Vinno.DataManager.Utilities;
+using System.Collections.Generic;
+using Vinno.Enums;
+using System.Linq;
+using Vinno.Infrastructure.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+
+    public class URMMeasureAlg
+    {
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern IntPtr PIA_CreateURMMeasure();
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe DPoint* PIA_CalURMCurvature(IntPtr _handPtr, IntPtr SrcImg, int width, int height, DPoint* Points, int Pointnum, ref double curvature, ref int outPointsNum);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe double PIA_CalURMDen(IntPtr _handPtr, IntPtr SrcImg, int width, int height, URMRoiMeasureParam roiparam);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe double PIA_CalURMFractalDim(IntPtr _handPtr, IntPtr SrcImg, int width, int height, URMRoiMeasureParam roiparam);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe double PIA_CalURMVel(IntPtr _handPtr, IntPtr SrcImg, int width, int height, URMRoiMeasureParam roiparam);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe void PIA_ReleaseURMCurvaturePoints(DPoint* pointsptr);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe bool PIA_CalDenMeasureResults(IntPtr _handPtr, IntPtr SrcImg, int width,
+            int height, URMRoiMeasureParam roiparam, double piexlScaler, ref URMDenMeasureResult result);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe bool PIA_CalVelMeasureResults(IntPtr _handPtr, IntPtr SrcImg, int width,
+            int height, URMRoiMeasureParam roiparam, double piexlScaler, ref URMVelMeasureResult result);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe DPoint* PIA_CalVessMeasureResults(IntPtr _handPtr, IntPtr SrcImg, int width,
+            int height, DPoint* Points, int Pointnum, double piexlScaler, ref URMVessMeasureResult result,
+            DPoint* OutPoints, int SamplingPoints);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern double PIA_CalPerfusion(IntPtr handle, IntPtr DenImg, IntPtr VelImg, int width,
+            int height, URMRoiMeasureParam roiparam, ref int rectx, ref int recty, ref int rectwidth, ref int rectheight);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe double PIA_GetPerfusionColorImg(IntPtr handle, IntPtr PerfusionImgPtr, IntPtr colormapptr);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe bool PIA_CalHistogarm(IntPtr handle, IntPtr SrcImg, int width, int height,
+            URMRoiMeasureParam roiparam, DPoint* OutPointsList, int OutPointscount);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern unsafe DPoint* PIA_GetShellOuterPoints(IntPtr _handPtr, int width, int height, DPoint* PointsList, int Pointscount, ref int outerPointCount, double shellwidth, double piexlScaler);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_URMMeasure_Release(IntPtr handPtr);
+
+
+
+        private IntPtr _handle;
+        public NativeArray _URMDenMeasureImg;
+        public NativeArray _URMVelMeasureImg;
+        public double _denMax, _denMin;
+        public double _velMax, _velMin;
+        private URMProcess owner;
+
+        public URMMeasureAlg(URMProcess tf)
+        {
+            _handle = PIA_CreateURMMeasure();
+            _URMDenMeasureImg = new NativeArray(0);
+            _URMVelMeasureImg = new NativeArray(0);
+            owner = tf;
+        }
+        private unsafe void ReleaseSRCurvaturePoints(DPoint* pointsptr)
+        {
+            PIA_ReleaseURMCurvaturePoints(pointsptr);
+        }
+
+        public void Relase()
+        {
+            PIA_URMMeasure_Release(_handle);
+            _URMDenMeasureImg.Dispose();
+            _URMVelMeasureImg.Dispose();
+        }
+
+
+
+        public URMMeasureDataOutput CalURMMeasureData(URMMeasureDataInput inputparam, int width, int height, double colorMapMax, double colorMapMin)
+        {
+            var result = new URMMeasureDataOutput();
+            var srcPoint = inputparam.SrcDPoints;
+            if (srcPoint.Count < 1)
+                return result;
+            List<DPoint> piexlPoints = new List<DPoint>();
+            for (int i = 0; i < srcPoint.Count; i++)
+            {
+                piexlPoints.Add(new DPoint(srcPoint[i].X * width, srcPoint[i].Y * height));
+            }
+            DPoint[] Points = piexlPoints.ToArray();
+            owner.CreateURMMeasuerImg(URMType.Den, _URMDenMeasureImg.Start, ref _denMax,ref _denMin);
+            owner.CreateURMMeasuerImg(URMType.Vel, _URMVelMeasureImg.Start, ref _velMax, ref _velMin);
+            double resultData = 0;
+            double velScaler = (_velMax - _velMin) / 255;
+            double denScaler = _denMax / 255.0;
+            double piexlScaler = inputparam.phywidth / width;
+            URMRoiMeasureParam roiparam = new URMRoiMeasureParam();
+            unsafe
+            {
+                fixed (DPoint* pointsptr = Points)
+                {
+                    roiparam.PointsList = pointsptr;
+                    roiparam.Pointscount = Points.Length;
+                    roiparam.RoiType = inputparam.RoiType;
+                    if (roiparam.RoiType == URMROIType.URMShell)
+                    {
+                        int outershellpointcount = 0;
+                        var outpointptr = PIA_GetShellOuterPoints(_handle, width, height, roiparam.PointsList,
+                            roiparam.Pointscount, ref outershellpointcount, inputparam.ShellWidth, piexlScaler);
+                        for (int i = 0; i < outershellpointcount; i++)
+                        {
+                            result.OuterExterPoints.Add(new DPoint(outpointptr[i].X, outpointptr[i].Y));//归一化的值
+                        }
+                    }
+                    switch (inputparam.urmMeasureType)
+                    {
+                        case URMMeasureType.URMFracetalDim:
+                            resultData = PIA_CalURMFractalDim(_handle, _URMDenMeasureImg.Start, width, height, roiparam);
+                            result.ResultData = resultData;
+                            break;
+                        case URMMeasureType.URMVel:
+                            resultData = PIA_CalURMVel(_handle, _URMVelMeasureImg.Start, width, height, roiparam);
+                            result.ResultData = resultData * velScaler + _velMin;
+                            break;
+                        case URMMeasureType.URMDen:
+                            resultData = PIA_CalURMDen(_handle, _URMDenMeasureImg.Start, width, height, roiparam);
+                            result.ResultData = resultData;
+                            break;
+                        case URMMeasureType.URMCurvature:
+                            double curvature = 0;
+                            int outpointcount = 0;
+                            var outpointptr = PIA_CalURMCurvature(_handle, _URMDenMeasureImg.Start, width, height, pointsptr, Points.Length,
+                                ref curvature, ref outpointcount);
+                            for (int i = 0; i < outpointcount; i++)
+                            {
+                                result.ResultDPoints.Add(new DPoint(outpointptr[i].X / width, outpointptr[i].Y / height));
+                            }
+                            ReleaseSRCurvaturePoints(outpointptr);
+                            result.ResultData = curvature;
+                            break;
+                        case URMMeasureType.URMTraceCurvature:
+                            //弯曲度等于直线距离÷曲线距离
+                            //直线距离就是起点跟终点的距离
+                            //曲线距离就是每两个的距离和 比如有4个点 直线距离就是1点跟4点的距离 弯曲距离就是1和2的距离+2和3的距离 + 3和4的距离
+                            double traceCurvature = 0;
+                            double Skelength = 0; //所有点的距离和
+                            for (int i = 0; i < Points.Length; i++)
+                            {
+                                if (i > 0)
+                                {
+                                    Skelength += Math.Sqrt(Math.Pow((Points[i].X - Points[i - 1].X), 2) +
+                                                           Math.Pow(Points[i].Y - Points[i - 1].Y, 2));
+                                }
+                            }
+                            double linelength = Math.Sqrt(Math.Pow((Points[0].X - Points.Last().X), 2) +
+                                                          Math.Pow(Points[0].Y - Points.Last().Y, 2)); //起点和终点的距离
+                            Logger.WriteLineInfo("URMCurvature Start Trace" + Points[0].X + " " + Points[0].Y);
+                            Logger.WriteLineInfo("URMCurvature End Trace" + Points.Last().X + " " + Points.Last().Y);
+                            Logger.WriteLineInfo("URMCurvature linelength Trace" + linelength);
+                            Logger.WriteLineInfo("URMCurvature Skelength Trace" + Skelength);
+                            traceCurvature = Math.Abs(Skelength / linelength);
+                            if (traceCurvature < 1.0)
+                                traceCurvature = 1.0;
+                            result.ResultData = traceCurvature;
+                            break;
+
+                        case URMMeasureType.URMDenMeasure:
+                            var denmesureresult = new URMDenMeasureResult();
+                            PIA_CalDenMeasureResults(_handle, _URMDenMeasureImg.Start, width, height, roiparam, piexlScaler, ref denmesureresult);
+                            denmesureresult.MaxDensity *= denScaler;
+                            denmesureresult.MinDensity *= denScaler;
+                            denmesureresult.MeanDensity *= denScaler;
+                            denmesureresult.VarianceDensity *= (denScaler * denScaler);
+                            if (roiparam.RoiType == URMROIType.URMShell)
+                            {
+                                denmesureresult.InMaxDensity *= denScaler;
+                                denmesureresult.InMinDensity *= denScaler;
+                                denmesureresult.InMeanDensity *= denScaler;
+                                denmesureresult.InVarianceDensity *= (denScaler * denScaler);
+                                denmesureresult.OutMaxDensity *= denScaler;
+                                denmesureresult.OutMinDensity *= denScaler;
+                                denmesureresult.OutMeanDensity *= denScaler;
+                                denmesureresult.OutVarianceDensity *= (denScaler * denScaler);
+                            }
+                            result.DenMeasureResult = denmesureresult;
+                            break;
+                        case URMMeasureType.URMVelMeasure:
+                            var velmesureresult = new URMVelMeasureResult();
+                            PIA_CalVelMeasureResults(_handle, _URMVelMeasureImg.Start, width, height, roiparam, piexlScaler, ref velmesureresult);
+                            velmesureresult.MaxVel = (velmesureresult.MaxVel * velScaler + _velMin);
+                            velmesureresult.MinVel = (velmesureresult.MinVel * velScaler + _velMin); ;
+                            velmesureresult.MeanVel = (velmesureresult.MeanVel * velScaler + _velMin);
+                            velmesureresult.VarianceVel *= (velScaler * velScaler);
+                            if (roiparam.RoiType == URMROIType.URMShell)
+                            {
+                                velmesureresult.InMaxVel = (velmesureresult.InMaxVel * velScaler + _velMin);
+                                velmesureresult.InMinVel = (velmesureresult.InMinVel * velScaler + _velMin);
+                                velmesureresult.InMeanVel = (velmesureresult.InMeanVel * velScaler + _velMin);
+                                velmesureresult.InVarianceVel *= (velScaler * velScaler);
+                                velmesureresult.OutMaxVel = (velmesureresult.OutMaxVel * velScaler + _velMin);
+                                velmesureresult.OutMinVel = (velmesureresult.OutMinVel * velScaler + _velMin);
+                                velmesureresult.OutMeanVel = (velmesureresult.OutMeanVel * velScaler + _velMin);
+                                velmesureresult.OutVarianceVel *= (velScaler * velScaler);
+                            }
+                            result.VelMeasureResult = velmesureresult;
+                            break;
+                        case URMMeasureType.URMVesselMeasure:
+                            var vessmesureresult = new URMVessMeasureResult();
+                            DPoint[] outPoints = new DPoint[inputparam.SamplingPoints];
+                            fixed (DPoint* vessPointptr = outPoints)
+                            {
+                                var outlocpointptr = PIA_CalVessMeasureResults(_handle, _URMDenMeasureImg.Start, width, height, pointsptr, Points.Length,
+                                    piexlScaler, ref vessmesureresult, vessPointptr, inputparam.SamplingPoints);
+                                for (int i = 0; i < vessmesureresult.vesselCount; i++)
+                                {
+                                    result.OuterExterPoints.Add(new DPoint(outlocpointptr[i].X, outlocpointptr[i].Y));//归一化的值
+                                }
+                                ReleaseSRCurvaturePoints(outlocpointptr);
+                            }
+                            var vessoutdpoints = new List<DPoint>(outPoints);
+                            result.ResultDPoints = vessoutdpoints;
+                            result.VessMeasureResult = vessmesureresult;
+                            break;
+                        case URMMeasureType.URMLocationVel:
+                            var curpoint = inputparam.SrcDPoints[0];
+                            var col = (int)curpoint.X;
+                            var row = (int)curpoint.Y;
+                            if (col >= 0 && col < width && row >= 0 && row < height)
+                            {
+                                var curptr = _URMVelMeasureImg.Start + (row * width + col);
+                                byte[] curvel = new byte[1];
+                                Marshal.Copy(curptr, curvel, 0, 1);
+                                if (curvel[0] == 0)
+                                    result.ResultData = 0;
+                                else
+                                {
+                                    result.ResultData = (double)curvel[0] * velScaler + _velMin;
+                                }
+                            }
+                            break;
+                        case URMMeasureType.URMPerfusion:
+                            var perfusioncolormap = owner.GetURMColorMap("SRColorMap:PerfusionMap");
+                            int rectx = 0, recty = 0, rectwidth = 0, rectheight = 0;
+                            var perfusion = PIA_CalPerfusion(_handle, _URMDenMeasureImg.Start, _URMVelMeasureImg.Start,
+                                width, height, roiparam, ref rectx, ref recty, ref rectwidth, ref rectheight);
+                            if (rectwidth == 0 || rectheight == 0)
+                            {
+                                result.ResultFlag = false;
+                                return result;
+                            }
+                            result.PerfusionPiexlRect = new IntRect(rectx, recty, rectwidth, rectheight);
+                            result.PerfusionScaleDRect = new DRect((double)rectx / width, (double)recty / height, (double)rectwidth / width, (double)rectheight / height);
+                            result.PerfusionImgData.Resize(rectwidth * rectheight * 4);
+                            PIA_GetPerfusionColorImg(_handle, result.PerfusionImgData.Start, perfusioncolormap.Address);
+                            result.ResultData = perfusion * _velMax;
+                            break;
+                        case URMMeasureType.URMHist:
+                            DPoint[] outHistPoints = new DPoint[inputparam.SamplingPoints];
+                            var MeasureArray = owner._urmType == URMType.Den ? _URMDenMeasureImg : _URMVelMeasureImg;
+                            fixed (DPoint* outHistPointsptr = outHistPoints)
+                            {
+                                PIA_CalHistogarm(_handle, MeasureArray.Start, width, height, roiparam,
+                                    outHistPointsptr, inputparam.SamplingPoints);
+                            }
+                            for (int i = 0; i < outHistPoints.Length; i++)
+                            {
+                                outHistPoints[i].X = outHistPoints[i].X / 256 * (Math.Abs(colorMapMax - colorMapMin));
+                            }
+                            var histoutdpoints = new List<DPoint>(outHistPoints);
+                            result.ResultDPoints = histoutdpoints;
+                            break;
+                        case URMMeasureType.URMDenVelMeasure:
+                            var denresult = new URMDenMeasureResult();
+                            PIA_CalDenMeasureResults(_handle, _URMDenMeasureImg.Start, width, height, roiparam, piexlScaler, ref denresult);
+                            denresult.MaxDensity *= denScaler;
+                            denresult.MinDensity *= denScaler;
+                            denresult.MeanDensity *= denScaler;
+                            denresult.VarianceDensity *= (denScaler * denScaler);
+                            if (roiparam.RoiType == URMROIType.URMShell)
+                            {
+                                denresult.InMaxDensity *= denScaler;
+                                denresult.InMinDensity *= denScaler;
+                                denresult.InMeanDensity *= denScaler;
+                                denresult.InVarianceDensity *= (denScaler * denScaler);
+                                denresult.OutMaxDensity *= denScaler;
+                                denresult.OutMinDensity *= denScaler;
+                                denresult.OutMeanDensity *= denScaler;
+                                denresult.OutVarianceDensity *= (denScaler * denScaler);
+                            }
+                            result.DenMeasureResult = denresult;
+                            var velresult = new URMVelMeasureResult();
+                            PIA_CalVelMeasureResults(_handle, _URMVelMeasureImg.Start, width, height, roiparam, piexlScaler, ref velresult);
+                            velresult.MaxVel = (velresult.MaxVel * velScaler + _velMin);
+                            velresult.MinVel = (velresult.MinVel * velScaler + _velMin);
+                            velresult.MeanVel = (velresult.MeanVel * velScaler + _velMin);
+                            velresult.VarianceVel *= (velScaler * velScaler);
+                            if (roiparam.RoiType == URMROIType.URMShell)
+                            {
+                                velresult.InMaxVel = (velresult.InMaxVel * velScaler + _velMin);
+                                velresult.InMinVel = (velresult.InMinVel * velScaler + _velMin);
+                                velresult.InMeanVel = (velresult.InMeanVel * velScaler + _velMin);
+                                velresult.InVarianceVel *= (velScaler * velScaler);
+                                velresult.OutMaxVel = (velresult.OutMaxVel * velScaler + _velMin);
+                                velresult.OutMinVel = (velresult.OutMinVel * velScaler + _velMin);
+                                velresult.OutMeanVel = (velresult.OutMeanVel * velScaler + _velMin);
+                                velresult.OutVarianceVel *= (velScaler * velScaler);
+                            }
+                            result.VelMeasureResult = velresult;
+                            break;
+                    }
+                }
+                return result;
+            }
+        }
+    }
+}
+

+ 371 - 0
URMManage/URMProcess.cs

@@ -0,0 +1,371 @@
+using System.IO;
+using System.Runtime.InteropServices;
+using Vinno.DataManager.Process;
+using Vinno.DataTypes;
+using Vinno.Infrastructure;
+using Vinno.Services.ServiceManagerImpl;
+using Vinno.DataManager.GraphTransform;
+using Vinno.Enums;
+using Vinno.ProcessUnits.DisplayLib;
+using System.Collections.Generic;
+using Vinno.DataManager.Infrastructure;
+using System;
+using Vinno.DataManager.Utilities;
+using SkiaSharp;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class URMProcess
+    {
+        private URMProcessAlg _urmProcessAlg;
+        private URMProcessParams _urmProcessParams = new URMProcessParams();
+        private URMImgBaseParam _urmImgBaseParam = new URMImgBaseParam();
+        private URMImgDrawParam _urmImgDrawParam = new URMImgDrawParam();
+        private URMVideoParam _urmVideoParam = new URMVideoParam();
+        public ProcessUnitParam<URMType> _urmType;
+        public ImagePP ImagePP { get; private set; }
+        private bool Mixflag;
+        private DPoint[] urmTraceDPoints;
+
+        private byte[] imagePixels;
+        private int ScreenWidth;
+        private int ScreenHeight;
+        private GCHandle handle;
+        private ColorTable videoColorTable;
+
+        public bool init(string familyName, string typeInfo, string nativeId)
+        {
+            ResourceManagerImpl resourceManager = new ResourceManagerImpl(Path.Combine(ServiceManager.RootPath, "URM", "dev"));
+            ResourceManager.Initialize(resourceManager);
+            var dir = new VinnoDirectoryInfo(Path.Combine(ServiceManager.RootPath, "URM"));
+            NativeProxy.UpdateSection("Path", "ShippedRoot", dir.FullName);
+            NativeProxy.UpdateSection("Product-GeneralSpecification", "ImagePPFileName", "ImagePP_Tulip");
+            if (ServiceManager.Os.IsWin())
+            {
+                ImagePP = new ImagePPNative_Win();
+            }
+            else
+            {
+                ImagePP = new ImagePPNative();
+            }
+            ImagePP.Initial();
+            Logger.WriteLineInfo("Record.SetProbeApp({0},{1},{2})", familyName, typeInfo, nativeId);
+            ImagePP.Initial(familyName, typeInfo, nativeId);
+            // TODO Delete me
+            var maplength = new List<int>();
+            var result = ImagePP.GetParameter("SRColorMap:AngleMap", "SR_Map_Length", maplength, null);
+            Logger.WriteLineInfo("ImagePP.GetParameter", result);
+            // TODO Delete me
+            _urmProcessAlg = new URMProcessAlg(ImagePP);
+            _urmType.Init(URMType.Den);
+            urmTraceDPoints = new DPoint[0];
+            return result;
+        }
+
+        // 调节后处理参数调用此函数
+        public void setUrmParams(RecordParams paramName, object param)
+        {
+            switch (paramName)
+            {
+                case RecordParams.URMDownSampleIndex:
+                    _urmProcessParams.DownsampleIndex = (float)param;
+                    break;
+                case RecordParams.URMIntPowerDen:
+                    _urmProcessParams.IntPowerDen = (float)param / 10.0;
+                    break;
+                case RecordParams.URMIntPowerDir:
+                    _urmProcessParams.IntPowerDir = (float)param / 10.0;
+                    break;
+                case RecordParams.URMSigmaGauss:
+                    _urmProcessParams.SigmaGauss = (float)param / 2.0;
+                    break;
+                case RecordParams.URMVessScale:
+                    _urmProcessParams.VessScale = (float)param / 5.0;
+                    break;
+                case RecordParams.URMVelMaxScaler:
+                    _urmProcessParams.VelMaxScaler = (float)param;
+                    break;
+                case RecordParams.URMVelMinScaler:
+                    _urmProcessParams.VelMinScaler = (float)param;
+                    break;
+                case RecordParams.URMIterations:
+                    _urmProcessParams.iterations = (int)(float)param;
+                    break;
+                case RecordParams.URMSigmaDen:
+                    _urmProcessParams.URMSigmaDen = (float)param;
+                    break;
+                case RecordParams.URMSigmaStep:
+                    _urmProcessParams.URMSigmaStep = (float)param;
+                    break;
+                case RecordParams.URMDirIterGauss:
+                    _urmProcessParams.URMDirIterGauss = (int)(float)param;
+                    break;
+                case RecordParams.URMVideoScaler:
+                    _urmVideoParam._VideoScaler = (float)param;
+                    break;
+                case RecordParams.URMVideoParameter:
+                    _urmVideoParam._VideoDownSampleIndex = (float)param;
+                    break;
+                case RecordParams.URMVideoType:
+                    _urmVideoParam._VideoType = (float)param;
+                    break;
+                case RecordParams.UrmImageType:
+                    _urmType.SetCurrent((URMType)Enum.Parse(typeof(URMType), (string)param));
+                    break;
+                case RecordParams.UrmBlend:
+                    Mixflag = (bool)param;
+                    break;
+            }
+        }
+
+        public void setUrmBaseParam(double res, NativeArray urmDenArray, NativeArray urmDirArray, NativeArray urmVelArray, NativeArray urmAngleArray, NativeArray urmMask, int urmSrcWidth, int urmSrcHeight, double scaleOfPixel_x, double scaleOfPixel_y, int ImgProcessVer, bool isliner)
+        {
+            _urmImgBaseParam.Res = res; // 参数
+            _urmImgBaseParam.Denptr = urmDenArray.Start; // den 数组的指针
+            _urmImgBaseParam.Dirptr = urmDirArray.Start; // dir 数组的指针
+            _urmImgBaseParam.Velptr = urmVelArray.Start; // vel 数组的指针
+            _urmImgBaseParam.Angleptr = urmAngleArray.Start; // angle 数组的指针
+            _urmImgBaseParam.MaskPtr = urmMask.Start; // mask 数组的指针
+            _urmImgBaseParam.Urmsrcwidth = urmSrcWidth; // 参数
+            _urmImgBaseParam.Urmsrcheight = urmSrcHeight; // 参数
+            _urmImgBaseParam.ScaleOfPixel_x = scaleOfPixel_x; // 参数
+            _urmImgBaseParam.ScaleOfPixel_y = scaleOfPixel_y; // 参数
+            _urmImgBaseParam.ImgProcessVer = ImgProcessVer; // urm算法版本 0 是 v2 1 是 v3
+            _urmImgBaseParam.ProbeType = isliner ? 0 : 1;
+            _urmProcessAlg.SetURMBaseParam(_urmImgBaseParam);
+        }
+
+        public void setUrmDrawParam(
+            bool ZoomOn, double ZoomRoix, double ZoomRoiy, double ZoomRoiwidth, double ZoomRoiheight, int Roix, int Roiy, int Roiwidth, int Roiheight, bool LeftRight, bool UpDown, int screenWidth, int screenHeight)
+        {
+            // 初始化图像
+            ScreenWidth = screenWidth;
+            ScreenHeight = screenHeight;
+            imagePixels = new byte[ScreenWidth * ScreenHeight * 4];
+            for (int i = 0; i < ScreenWidth * ScreenHeight; i++)
+            {
+                int index = i * 4;
+                imagePixels[index] = 0;     // Blue
+                imagePixels[index + 1] = 0; // Green
+                imagePixels[index + 2] = 0; // Red
+                imagePixels[index + 3] = 1; // Alpha
+            }
+            // 获取指针
+            handle = GCHandle.Alloc(imagePixels, GCHandleType.Pinned);
+            _urmImgDrawParam.ZoomOn = ZoomOn; // 是否启用 zoom
+            _urmImgDrawParam.ZoomRoix = ZoomRoix; // zoom 后 ROI X
+            _urmImgDrawParam.ZoomRoiy = ZoomRoiy; // zoom 后 ROI X
+            _urmImgDrawParam.ZoomRoiwidth = ZoomRoiwidth; // zoom 后 ROI 宽度
+            _urmImgDrawParam.ZoomRoiheight = ZoomRoiheight; // zoom 后 ROI 宽度
+            _urmImgDrawParam.Screenimgptr = handle.AddrOfPinnedObject(); // 图像指针(最重要,用于获取图像)
+            _urmImgDrawParam.Screenimgwidth = ScreenWidth; // 图像输出的宽度
+            _urmImgDrawParam.Screenimgheight = ScreenHeight; // 图像输出的高度
+            _urmImgDrawParam.Roix = Roix; // ROI x
+            _urmImgDrawParam.Roiy = Roiy; // ROI  y
+            _urmImgDrawParam.Roiwidth = Roiwidth; // 宽度
+            _urmImgDrawParam.Roiheight = Roiheight; // 高度
+            _urmImgDrawParam.LeftRight = LeftRight ? 1 : 0; // 是否左右翻转
+            _urmImgDrawParam.UpDown = UpDown ? 1 : 0; // 是否上下翻转
+            _urmProcessAlg.SetURMDrawParam(_urmImgDrawParam);
+        }
+
+        // public WriteableBitmap getURMImage()
+        // {
+        //     WriteableBitmap bitmap = new WriteableBitmap(ScreenWidth, ScreenHeight, 96, 96, PixelFormats.Bgra32, null);
+        //     _urmProcessAlg.SetURMParam(_urmProcessParams);
+        //     double urmMaxVal = 0; // 这个输出需要给到前端
+        //     double urmMinVal = 0; // 这个输出需要给到前端
+        //     _urmProcessAlg.CalURMImg(ref urmMaxVal, ref urmMinVal, (int)_urmType.Current);
+        //     Logger.WriteLineInfo($"CalURMImg urmMaxVal:{urmMaxVal} urmMinVal:{urmMinVal} {bitmap.PixelWidth}");
+        //     var urmcolormapname = getColormapname((int)_urmType.Current);
+        //     var urmcolortable = GetURMColorMap(urmcolormapname);
+        //     var Colormapptr = urmcolortable.Address; // 获取颜色映射表
+        //     if (_urmType == URMType.Angle && urmcolortable.Length != 1440)
+        //     {
+        //         Logger.WriteLineInfo("Akio:Angle ColorMapError");
+        //         return bitmap;
+        //     }
+        //     _urmProcessAlg.DrawURM((int)_urmType.Current, Colormapptr, Mixflag);
+        //     Int32Rect rect = new Int32Rect(0, 0, ScreenWidth, ScreenHeight);
+        //     bitmap.WritePixels(rect, imagePixels, ScreenWidth * 4, 0);
+        //     return bitmap;
+        // }
+
+        public void getUrmVal(ref double urmMaxVal, ref double urmMinVal)
+        {
+            _urmProcessAlg.SetURMParam(_urmProcessParams);
+            _urmProcessAlg.CalURMImg(ref urmMaxVal, ref urmMinVal, (int)_urmType.Current);
+            Logger.WriteLineInfo($"CalURMImg urmMaxVal:{urmMaxVal} urmMinVal:{urmMinVal}");
+        }
+
+        public string getURMImageBase64()
+        {
+            _urmProcessAlg.SetURMParam(_urmProcessParams);
+            double urmMaxVal = 0; // 这个输出需要给到前端
+            double urmMinVal = 0; // 这个输出需要给到前端
+            _urmProcessAlg.CalURMImg(ref urmMaxVal, ref urmMinVal, (int)_urmType.Current);
+            Logger.WriteLineInfo($"CalURMImg urmMaxVal:{urmMaxVal} urmMinVal:{urmMinVal}");
+            var urmcolormapname = getColormapname((int)_urmType.Current);
+            var urmcolortable = GetURMColorMap(urmcolormapname);
+            var Colormapptr = urmcolortable.Address; // 获取颜色映射表
+            if (_urmType == URMType.Angle && urmcolortable.Length != 1440)
+            {
+                Logger.WriteLineInfo("Akio:Angle ColorMapError");
+                return "";
+            }
+            _urmProcessAlg.DrawURM((int)_urmType.Current, Colormapptr, Mixflag);
+            //using (SKImage image = SKImage.FromEncodedData(SKData.CreateCopy(imagePixels)))
+            //{
+            //    SKBitmap bitMap = SKBitmap.FromImage(image);
+            //}
+            SKImageInfo info = new SKImageInfo(ScreenWidth, ScreenHeight, SKColorType.Bgra8888, SKAlphaType.Unpremul);
+
+            // Create an SKBitmap with the given SKImageInfo
+            SKBitmap skBitmap = new SKBitmap(info);
+            // Copy the pixel data from the imagePixels array to the SKBitmap
+            using (SKImage skImage = SKImage.FromPixelCopy(info, imagePixels))
+            {
+                skImage.ReadPixels(skBitmap.Info, skBitmap.GetPixels(), skBitmap.RowBytes, 0, 0);
+            }
+            using (var image = SKImage.FromBitmap(skBitmap))
+            using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
+            {
+                byte[] imageBytes = data.ToArray();
+                string base64String = Convert.ToBase64String(imageBytes);
+                return base64String;
+            }
+        }
+
+
+        string getColormapname(int type)
+        {
+            switch (type)
+            {
+                case 0:
+                    return "SRColorMap:ColorMap1";
+                case 1:
+                    return "SRColorMap:ColorMap2";
+                case 2:
+                    return "SRColorMap:ColorMap3";
+                case 3:
+                    return "SRColorMap:AngleMap";
+                default:
+                    return "SRColorMap:ColorMap1";
+            }
+
+        }
+
+        public ColorTable GetURMColorMap(string colorMap)
+        {
+            var rValue = new List<int>();
+            var gValue = new List<int>();
+            var bValue = new List<int>();
+
+            var maplength = new List<int>();
+            var result = ImagePP.GetParameter(colorMap, "SR_Map_R", rValue, null);
+            result = result && ImagePP.GetParameter(colorMap, "SR_Map_G", gValue, null);
+            result = result && ImagePP.GetParameter(colorMap, "SR_Map_B", bValue, null);
+            result = result && ImagePP.GetParameter(colorMap, "SR_Map_Length", maplength, null);
+            ColorTable URMTable = new ColorTable(maplength[0] * sizeof(uint));
+            if (result)
+            {
+                IValueAccessor<uint> intValueAccessor = URMTable;
+                for (int i = 0; i < maplength[0]; i++)
+                {
+                    var temp = rValue[i] << 16 | gValue[i] << 8 | bValue[i] | 0xFF000000;
+                    intValueAccessor[i] = (uint)temp;
+                }
+
+            }
+            return URMTable;
+        }
+
+        public void CalTracePointMask(DPoint[] traceDPoints)
+        {
+            urmTraceDPoints = traceDPoints;
+            var tracePointCount = urmTraceDPoints.Length;
+            var validPoints = new List<DPoint>();
+            for (int i = 0; i < tracePointCount; i++)
+            {
+                var curPiexlPoint = new DPoint(urmTraceDPoints[i].X * ScreenWidth, urmTraceDPoints[i].Y * ScreenHeight);
+                validPoints.Add(curPiexlPoint);
+            }
+            _urmProcessAlg.CalTraceMaskImg(ScreenWidth, ScreenHeight, validPoints);
+        }
+
+        public void PreURMVideo(URMPoint[] urmPoints, int[] Pointsnums)
+        {
+            var vediotable = GetURMColorMap("SRColorMap:ColorMap4");
+            double urmMaxVal = 0;
+            double urmMinVal = 0;
+            _urmProcessAlg.SetURMParam(_urmProcessParams);
+            _urmProcessAlg.CalURMImg(ref urmMaxVal, ref urmMinVal, (int)_urmType.Current);
+            unsafe
+            {
+                fixed (URMPoint* AllPointsPtr = urmPoints)
+                {
+                    fixed (int* pointlengthsptr = Pointsnums)
+                    {
+                        _urmProcessAlg.PreURMVideo(_urmVideoParam, AllPointsPtr, Pointsnums.Length, pointlengthsptr, ref urmMaxVal, ref urmMinVal);
+                    }
+                }
+            }
+            videoColorTable = GetURMColorMap("SRColorMap:ColorMap4");
+            Logger.WriteLineInfo($"PreURMVideo urmMaxVal:{urmMaxVal} urmMinVal:{urmMinVal}");
+        }
+
+        // public void getURMVideoImg(int index, WriteableBitmap dataHolder)
+        // {
+        //     _urmProcessAlg.DrawURMVideo(index, videoColorTable.Address, Mixflag);
+        //     Int32Rect rect = new Int32Rect(0, 0, ScreenWidth, ScreenHeight);
+        //     dataHolder.WritePixels(rect, imagePixels, ScreenWidth * 4, 0);
+        // }
+
+        public string getURMVideoImg(int index)
+        {
+            _urmProcessAlg.DrawURMVideo(index, videoColorTable.Address, Mixflag);
+            SKImageInfo info = new SKImageInfo(ScreenWidth, ScreenHeight, SKColorType.Bgra8888, SKAlphaType.Unpremul);
+
+            // Create an SKBitmap with the given SKImageInfo
+            SKBitmap skBitmap = new SKBitmap(info);
+            // Copy the pixel data from the imagePixels array to the SKBitmap
+            using (SKImage skImage = SKImage.FromPixelCopy(info, imagePixels))
+            {
+                skImage.ReadPixels(skBitmap.Info, skBitmap.GetPixels(), skBitmap.RowBytes, 0, 0);
+            }
+            using (var image = SKImage.FromBitmap(skBitmap))
+            using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
+            {
+                byte[] imageBytes = data.ToArray();
+                string base64String = Convert.ToBase64String(imageBytes);
+                return base64String;
+            }
+        }
+
+        public void CreateURMMeasuerImg(URMType urmtype, IntPtr MeasureImgStart, ref double max, ref double min)
+        {
+            if (urmtype == URMType.Den)
+            {
+                _urmProcessAlg.CalURMMeasurImg(MeasureImgStart, (int)urmtype, ref max,
+                    ref min);
+            }
+            else if (urmtype == URMType.Vel)
+            {
+                _urmProcessAlg.CalURMMeasurImg(MeasureImgStart, (int)urmtype, ref max,
+                    ref min);
+            }
+        }
+
+        public void Dispose()
+        {
+            handle.Free();
+            _urmProcessAlg.Release();
+            if (ImagePP != null)
+            {
+                ImagePP.Dispose();
+                ImagePP = null;
+            }
+        }
+    }
+}
+

+ 202 - 0
URMManage/URMProcessAlg.cs

@@ -0,0 +1,202 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using Vinno.DataManager.Process;
+using Vinno.DataManager.Utilities;
+using Vinno.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    [StructLayout(LayoutKind.Sequential)]
+    public class URMProcessParams
+    {
+        public double DownsampleIndex { get; set; }
+        public double IntPowerDen { get; set; }
+        public double IntPowerDir { get; set; }
+        public double SigmaGauss { get; set; }
+        public double VessScale { get; set; }
+
+        public double VelMaxScaler { get; set; }
+        public double VelMinScaler { get; set; }
+
+        public int iterations { get; set; }
+
+        public double URMSigmaDen { get; set; }
+        public double URMSigmaStep { get; set; }
+
+        public int URMDirIterGauss { get; set; }
+
+        public URMProcessParams()
+        {
+            DownsampleIndex = 3;
+            IntPowerDen = 0.33;
+            IntPowerDir = 0.25;
+            SigmaGauss = 0.8;
+            VessScale = 0.6;
+            VelMaxScaler = 1;
+            VelMinScaler = 0;
+            iterations = 1;
+            URMSigmaDen = 5;
+            URMSigmaStep = 0.1;
+            URMDirIterGauss = 10;
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public class URMImgBaseParam
+    {
+        public IntPtr Denptr { get; set; } //Den的分析后数据
+        public IntPtr Dirptr { get; set; } //Dir的分析后数据
+        public IntPtr Velptr { get; set; } //Vel的分析后数据
+        public IntPtr Angleptr { get; set; }//360图的数据
+        public IntPtr MaskPtr { get; set; }//Mask
+        public int Urmsrcwidth { get; set; }//URM分析后的数据宽度
+        public int Urmsrcheight { get; set; }//URM分析后的数据高度
+
+        public double Res { get; set; }
+
+        public double ScaleOfPixel_x { get; set; }
+        public double ScaleOfPixel_y { get; set; }
+
+        public int ImgProcessVer { get; set; }//后处理算法版本  0 Ver2(<2.7) 1 Ver3(2.7)
+
+        public int ProbeType { get; set; }
+    }
+    [StructLayout(LayoutKind.Sequential)]
+    public class URMImgDrawParam
+    {
+        public IntPtr Screenimgptr { get; set; }
+        public int Screenimgwidth { get; set; }
+        public int Screenimgheight { get; set; }
+        public bool ZoomOn { get; set; }
+        public double ZoomRoix { get; set; }
+        public double ZoomRoiy { get; set; }
+        public double ZoomRoiwidth { get; set; }
+        public double ZoomRoiheight { get; set; }
+        public int Roix { get; set; }
+        public int Roiy { get; set; }
+        public int Roiwidth { get; set; }
+        public int Roiheight { get; set; }
+        public int LeftRight { get; set; }
+        public int UpDown { get; set; }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public class URMVideoParam
+    {
+        public double _VideoDownSampleIndex { get; set; }
+        public double _VideoType { get; set; }
+
+        public double _VideoScaler { get; set; }
+
+        public URMVideoParam()
+        {
+            _VideoDownSampleIndex = 2;
+            _VideoType = 1;
+            _VideoScaler = 3;
+        }
+    }
+
+    public class URMProcessAlg
+    {
+
+        [DllImport("ImageProcessAlgWrapLib.dll", CharSet = CharSet.Ansi)]
+        private static extern IntPtr PIA_CreateURMProcess(IntPtr imagePP);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_SetURMParam(IntPtr handPtr, URMProcessParams srParams);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_SetURMImgBaseParams(IntPtr handPtr, URMImgBaseParam srParams);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_SetURMImgDrawParams(IntPtr handPtr, URMImgDrawParam srParams);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_CalURMImg(IntPtr handPtr, ref double barmax, ref double barmin, int type);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_DrawURMImg(IntPtr handPtr, int type, IntPtr colormap, bool mixflag);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern bool PIA_CalURMMeasurImg(IntPtr handle, IntPtr urmdmeasurimgptr, int urmtype, ref double barmax, ref double barmin);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static unsafe extern void PIA_CalURMTraceMaskImg(IntPtr handle, int width, int height, DPoint* Points, int PointCount);
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static unsafe extern void PIA_CalURMVideo(IntPtr handle, IntPtr dstarray, URMVideoParam videoparam, URMPoint* Points, int framecount, int* PointsCounts, IntPtr colormap, bool mixflage);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static unsafe extern void PIA_PreURMVideo(IntPtr handle, URMVideoParam videoparam, URMPoint* Points, int framecount, int* PointsCounts, ref double barmax, ref double barmin);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_DrawURMVideo(IntPtr handle, int index, IntPtr colormapptr, bool mixflag);
+
+        [DllImport("ImageProcessAlgWrapLib.dll")]
+        private static extern void PIA_URMMain_Release(IntPtr handPtr);
+
+
+        private IntPtr _handle;
+
+
+        public URMProcessAlg(ImagePP imgpp)
+        {
+            _handle = PIA_CreateURMProcess(imgpp.Handle);
+        }
+        public void SetURMParam(URMProcessParams srParams)
+        {
+            PIA_SetURMParam(_handle, srParams);
+        }
+
+        public void SetURMBaseParam(URMImgBaseParam Params)
+        {
+            PIA_SetURMImgBaseParams(_handle, Params);
+        }
+
+        public void SetURMDrawParam(URMImgDrawParam Params)
+        {
+            PIA_SetURMImgDrawParams(_handle, Params);
+        }
+        public void CalURMImg(ref double barmax, ref double barmin, int type)
+        {
+            PIA_CalURMImg(_handle, ref barmax, ref barmin, type);
+        }
+        public void DrawURM(int type, IntPtr colormap, bool mixflag)
+        {
+            PIA_DrawURMImg(_handle, type, colormap, mixflag);
+        }
+
+        public void CalURMMeasurImg(IntPtr urmdmeasurimgptr,
+            int urmtype, ref double barmax, ref double barmin)
+        {
+            PIA_CalURMMeasurImg(_handle, urmdmeasurimgptr, urmtype, ref barmax, ref barmin);
+        }
+
+        public unsafe void CalTraceMaskImg(int width, int height, List<DPoint> Points)
+        {
+            var pointarray = Points.ToArray();
+            fixed (DPoint* pointptr = pointarray)
+            {
+                PIA_CalURMTraceMaskImg(_handle, width, height, pointptr, Points.Count);
+            }
+
+        }
+
+        public unsafe void CalURMVideo(NativeArray dstarray, URMVideoParam videoparam, URMPoint* Points,
+            int framecount, int* PointsCounts, IntPtr colormap, bool mixflag)
+        {
+            PIA_CalURMVideo(_handle, dstarray.Start, videoparam, Points, framecount, PointsCounts, colormap, mixflag);
+        }
+
+        public unsafe void PreURMVideo(URMVideoParam videoparam, URMPoint* Points,
+            int framecount, int* PointsCounts, ref double barmax, ref double barmin)
+        {
+            PIA_PreURMVideo(_handle, videoparam, Points, framecount, PointsCounts, ref barmax, ref barmin);
+        }
+
+        public void DrawURMVideo(int index, IntPtr colormap, bool mixflag)
+        {
+            PIA_DrawURMVideo(_handle, index, colormap, mixflag);
+        }
+
+        public void Release()
+        {
+            PIA_URMMain_Release(_handle);
+        }
+    }
+}
+

+ 129 - 0
URMManage/UrmProcessRequest.cs

@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using Vinno.DataTypes;
+
+namespace WingAIDiagnosisService.URMManage
+{
+    public class UrmProcessRequest
+    {
+        //文件路径
+        public string DenDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\srcDenArray.bin";
+        public string DirDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\srcDirArray.bin";
+        public string VelDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\srcVelArray.bin";
+        public string AngleDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\srcAngleArray.bin";
+        public string MaskDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\srcMaskArray.bin";
+        ///// <summary>
+        ///// 生成图片保存路径
+        ///// </summary>
+        //public string ImgFilePath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\test0627.png";
+
+        //探头信息
+        public string FamilyName { get; set; } = "Linear";
+        public string TypeInfo { get; set; } = "Linear_U5-15LE";
+        public string NativeId { get; set; } = "Breast";
+        // 图像配置
+        public string UrmImageType { get; set; } = "0"; // Den 0, Dir 1, Vel 2, Angle 3
+        public bool UrmBlend { get; set; } = true;
+        // 用于后处理计算的算法参数(需要传入)
+        public float DownsampleIndex { get; set; } = 3f;
+        public float IntPowerDen { get; set; } = 4f;
+        public float IntPowerDir { get; set; } = 4f;
+        public float SigmaGauss { get; set; } = 2.4f;
+        public float VessScale { get; set; } = 1f;
+        public float VelMaxScaler { get; set; } = 1f;
+        public float VelMinScaler { get; set; } = 0f;
+        public float Iterations { get; set; } = 1f; // URM的基础参数包括分析结果的数据与大小以及Res
+        public double Res { get; set; } = 2.5;
+        public int Urmsrcwidth { get; set; } = 188;  // URM分析后的数据宽度
+        public int Urmsrcheight { get; set; } = 1233;  // URM分析后的数据高度
+        public double ScaleOfPixel_x { get; set; } = 0.214925914347303;
+        public double ScaleOfPixel_y { get; set; } = 0.61038961038961;
+        public int ImgProcessVer { get; set; } = 1;//后处理算法版本  0 Ver2(<2.7) 1 Ver3(2.7)
+        public bool Isliner { get; set; } = true;
+        // URM的绘制参数 
+        public bool ZoomOn { get; set; } = false; // 是否开启 zoom
+        public double ZoomRoix { get; set; } = 0; // zoom 区域在 ROI 中的归一化坐标
+        public double ZoomRoiy { get; set; } = 0; // zoom 区域在 ROI 中的归一化坐标
+        public double ZoomRoiwidth { get; set; } = 1; // zoom 区域在 ROI 中的归一化坐标
+        public double ZoomRoiheight { get; set; } = 1; // zoom 区域在 ROI 中的归一化坐标
+        public int Roix { get; set; } = 274;// Roi 区域在整个图像中的像素位置
+        public int Roiy { get; set; } = 16;// Roi 区域在整个图像中的像素位置
+        public int Roiwidth { get; set; } = 243; // Roi 区域在整个图像中的像素位置
+        public int Roiheight { get; set; } = 616; // Roi 区域在整个图像中的像素位置
+        public bool LeftRight { get; set; } = false;
+        public bool UpDown { get; set; } = false;
+        public int ScreenWidth { get; set; } = 666;// 输出的图像的尺寸
+        public int ScreenHeight { get; set; } = 650; // 输出的图像的尺寸
+
+
+    public class UrmMeasureProcessRequest: UrmProcessRequest
+    {
+        /// <summary>
+        /// 测量项枚举
+        /// </summary>
+        public URMMeasureType UrmMeasureType { get; set; }
+        /// <summary>
+        /// 点集
+        /// </summary>
+        public List<DPoint> SrcDPoints { get; set; }
+
+        /// <summary>
+        /// 两点物理距离
+        /// </summary>
+        public double? CMlength { get; set; }
+
+        /// <summary>
+        /// 画布物理宽度
+        /// </summary>
+        public double Phywidth { get; set; }
+
+        /// <summary>
+        /// ROI 类型
+        /// </summary>
+        public URMROIType ROIType { get; set; }
+
+        /// <summary>
+        /// Rim 宽度
+        /// </summary>
+        public double ShellWidth { get; set; }
+
+    }
+
+    public class URMProcessorClass
+    {
+        /// <summary>
+        /// GUID
+        /// </summary>
+        public string GUID { get; set; }
+
+        public URMProcess VideoProcessor { get; set; }
+
+        public DateTime LastActiveTime { get; set; }
+    }
+
+
+
+    public class DoUrmVideoProcessRequest : UrmProcessRequest
+    {
+        /// <summary>
+        /// GUID
+        /// </summary>
+        public string GUID { get; set; }
+
+        // 当前播放帧
+        public int VideoFrame { get; set; } = 0;
+
+        // 视频配置
+        public float URMVideoScaler { get; set; } = 3;
+        public float URMVideoParameter { get; set; } = 2;
+        public float URMVideoType { get; set; } = 1;
+        //数据路径
+        public string PointsDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\URMPoints.bin";
+        public string PointNumsDataPath { get; set; } = "D:\\Projects\\URMDemo\\URMDemo\\bin\\Debug\\URMTemp\\393f5673dc424b5e87334f8ba4a90aae\\URMPointNums.bin";
+
+    }
+        public DPoint[] UrmTraceDPoints { get; set; } = new DPoint[0];
+
+    }
+}
+

+ 11 - 25
WingAIDiagnosisService.csproj

@@ -16,6 +16,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
     <PackageReference Include="WingInterfaceLibrary" Version="1.2.0.1" />
     <PackageReference Include="WingServerCommon" Version="1.2.0.1" />
     <PackageReference Include="Emgu.CV" Version="4.2.0.3662" />
@@ -36,27 +37,6 @@
       <HintPath>AIDiagnosis\ContourModifyUtils.dll</HintPath>
     </Reference>
     
-    <Reference Include="FrameFirstGen">
-      <HintPath>URM\FrameFirstGen.dll</HintPath>
-    </Reference>
-    <Reference Include="MWArray">
-      <HintPath>URM\MWArray.dll</HintPath>
-    </Reference>
-    <Reference Include="SkiaSharp">
-      <HintPath>URM\SkiaSharp.dll</HintPath>
-    </Reference>
-    <Reference Include="SR_Main">
-      <HintPath>URM\SR_Main.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Buffers">
-      <HintPath>URM\System.Buffers.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Memory">
-      <HintPath>URM\System.Memory.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Runtime.CompilerServices.Unsafe">
-      <HintPath>URM\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
-    </Reference>
     <Reference Include="Vinno.Core">
       <HintPath>URM\Vinno.Core.dll</HintPath>
     </Reference>
@@ -66,14 +46,20 @@
     <Reference Include="Vinno.DataManager">
       <HintPath>URM\Vinno.DataManager.dll</HintPath>
     </Reference>
+    <Reference Include="Vinno.GraphTransform">
+      <HintPath>URM\Vinno.GraphTransform.dll</HintPath>
+    </Reference>
     <Reference Include="Vinno.Models.Base">
       <HintPath>URM\Vinno.Models.Base.dll</HintPath>
     </Reference>
-    <Reference Include="ImageProcessAlgWrapLib">
-      <HintPath>URM\ImageProcessAlgWrapLib.dll</HintPath>
+    <Reference Include="Vinno.ImagePP">
+      <HintPath>URM\Vinno.ImagePP.dll</HintPath>
+    </Reference>
+    <Reference Include="Vinno.ProcessUnits.DisplayLib">
+      <HintPath>URM\Vinno.ProcessUnits.DisplayLib.dll</HintPath>
     </Reference>
-    <Reference Include="ImageProcessAlgWrapLibV2">
-      <HintPath>URM\ImageProcessAlgWrapLibV2.dll</HintPath>
+    <Reference Include="Vinno.Services.ServiceManager">
+      <HintPath>URM\Vinno.Services.ServiceManager.dll</HintPath>
     </Reference>
   </ItemGroup>