using System.IO; using System.Runtime.InteropServices; using Vinno.DataManager.Process; using Vinno.DataTypes; using Vinno.Infrastructure; 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; using System.Diagnostics; using WingServerCommon.Log; using Logger = WingServerCommon.Log.Logger; 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; public ImagePP ImagePP { get; private set; } private int 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) { 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({familyName},{typeInfo},{nativeId})"); ImagePP.Initial(familyName, typeInfo, nativeId); // TODO Delete me var maplength = new List(); 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 = (int)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) { _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.vespekeltype = ImagePP.GetValue("URMVSpeckel", "URMVSpeckelType", 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, bool setImagePixels = true) { // 初始化图像 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.Screenimgptr = handle.AddrOfPinnedObject(); // 图像指针(最重要,用于获取图像) _urmImgDrawParam.ZoomOn = ZoomOn ? 1 : 0; // 是否启用 zoom _urmImgDrawParam.ZoomRoix = ZoomRoix; // zoom 后 ROI X _urmImgDrawParam.ZoomRoiy = ZoomRoiy; // zoom 后 ROI X _urmImgDrawParam.ZoomRoiwidth = ZoomRoiwidth; // zoom 后 ROI 宽度 _urmImgDrawParam.ZoomRoiheight = ZoomRoiheight; // zoom 后 ROI 宽度 _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 GetURMImage() { // SKBitmap bitmap = new SKBitmap(ScreenWidth, ScreenHeight); _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 bitmap; return; } _urmProcessAlg.DrawURM((int)_urmType.Current, Colormapptr, Mixflag); // using (var surface = SKSurface.Create(new SKImageInfo(ScreenWidth, ScreenHeight, SKColorType.Bgra8888))) // { // SKCanvas canvas = surface.Canvas; // // Draw your URM image on the canvas here // SKImage image = surface.Snapshot(); // byte[] imageBytes = image.Encode().ToArray(); // bitmap = SKBitmap.Decode(imageBytes); // } // 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(bool calUrmImg, ref double urmMinVal, ref double urmMaxVal) { _urmProcessAlg.SetURMParam(_urmProcessParams); urmMinVal = 0; // 这个输出需要给到前端 urmMaxVal = 0; // 这个输出需要给到前端 if (calUrmImg) { Stopwatch sw = new Stopwatch(); sw.Start(); try { _urmProcessAlg.CalURMImg(ref urmMaxVal, ref urmMinVal, (int)_urmType.Current); } catch (Exception ex) { WingServerCommon.Log.Logger.WriteLineInfo($"_urmProcessAlg.CalURMImg error :{ex}"); } sw.Stop(); WingServerCommon.Log.Logger.WriteLineInfo($"_urmProcessAlg.CalURMImg time :{sw.ElapsedMilliseconds}"); } WingServerCommon.Log.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 ""; } int mix = 0; mix = Mixflag; if (Mixflag == 1) { mix = 0; } _urmProcessAlg.DrawURM((int)_urmType.Current, Colormapptr, mix); //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); if (Mixflag == 1) { for (int y = 0; y < skBitmap.Height; y++) { for (int x = 0; x < skBitmap.Width; x++) { SKColor pixelColor = skBitmap.GetPixel(x, y); if (pixelColor.Alpha == 255 && pixelColor.Red == 0 && pixelColor.Green == 0 && pixelColor.Blue == 0) { SKColor modifiedColor = new SKColor(0, 0, 0, 128); // 将全黑像素设置为50%透明 skBitmap.SetPixel(x, y, modifiedColor); } } } } } 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(); var gValue = new List(); var bValue = new List(); var maplength = new List(); 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 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(); 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, ref double urmMaxVal, ref double urmMinVal) { var vediotable = GetURMColorMap("SRColorMap:ColorMap4"); urmMaxVal = 0; 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 unsafe string CreateUrmColorbarImage() { SKImageInfo info = new SKImageInfo(10, 128, SKColorType.Bgra8888, SKAlphaType.Unpremul); // Create an SKBitmap with the given SKImageInfo SKBitmap bitmap = new SKBitmap(info); var res = GetIntPow(); var ismidecenter = res.Item1; var intpow = res.Item2;//通过修改这个值 colorbar的颜色会有变化,视频的话这个是1 var urmcolormapname = getColormapname((int)_urmType.Current); var colorbarTable = GetURMColorMap(urmcolormapname); var tablelength = colorbarTable.Length / 4; byte[] rgbTable = new byte[tablelength * 3]; var midlength = tablelength / 2; double midpow = Math.Pow((double)(midlength), intpow); double maxpow = Math.Pow((double)(tablelength - 1), intpow); byte* source = (byte*)colorbarTable.Address; for (int i = 0; i < tablelength; i++) { int index = i; if (ismidecenter) { if (i > midlength) { index = (int)(Math.Pow((double)i - midlength, intpow) / midpow * (midlength)) + midlength; } else if (i < midlength) { index = midlength - (int)(Math.Pow((double)midlength - i, intpow) / midpow * (midlength)); } } else { index = (int)(Math.Pow((double)i, intpow) / maxpow * (tablelength - 1)); } if (index < 0) index = 0; if (index > tablelength - 1) index = tablelength - 1; byte r = (byte)source[4 * index + 2]; byte g = (byte)source[4 * index + 1]; byte b = (byte)source[4 * index]; rgbTable[i * 3] = r; rgbTable[i * 3 + 1] = g; rgbTable[i * 3 + 2] = b; } // Different platforms have different color formats, // such as ARGB for Windows and ABGR for Android. // So by default its default value is TRUE, which is FALSE on Android bool isArgbFormat = (ServiceManager.Os != VinnoOsPlatform.Android); int height = bitmap.Height; int width = bitmap.Width; SKColor* pixels = (SKColor*)bitmap.GetPixels(); for (int y = 0; y < height; y++) { int col = y * tablelength / height; int rowStart = (height - 1 - y) * width; for (int x = 0; x < width; x++) { int index = col; try { SKColor color; if (isArgbFormat) { color = new SKColor(rgbTable[index * 3], rgbTable[index * 3 + 1], rgbTable[index * 3 + 2]); } else { color = new SKColor(rgbTable[index * 3 + 2], rgbTable[index * 3 + 1], rgbTable[index * 3]); } pixels[rowStart + x] = color; } catch (Exception ex) { Logger.WriteLineError($"x:{x}, y:{y}, index:{index}, ex:{ex.Message}"); throw; } } } using (var image = SKImage.FromBitmap(bitmap)) using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) { byte[] imageBytes = data.ToArray(); string base64String = Convert.ToBase64String(imageBytes); return base64String; } } private Tuple GetIntPow() { bool ismidecenter = false; double intpow = 0d; URMType urmType = _urmType.Current; switch (urmType) { case URMType.Den: ismidecenter = false; intpow = _urmProcessParams.IntPowerDen; break; case URMType.Dir: ismidecenter = true; intpow = _urmProcessParams.IntPowerDir; break; case URMType.Vel: intpow = 1; ismidecenter = false; break; case URMType.Angle: break; default: ismidecenter = false; break; } return Tuple.Create(ismidecenter, intpow); } public void Dispose() { try { handle.Free(); } catch (Exception ex) { Logger.WriteLineWarn(ex.ToString()); } try { _urmProcessAlg.Release(); } catch (Exception ex) { Logger.WriteLineWarn(ex.ToString()); } if (ImagePP != null) { try { ImagePP.Dispose(); ImagePP = null; } catch (Exception ex) { Logger.WriteLineWarn(ex.ToString()); } } } } }