123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- using Emgu.CV;
- using Emgu.CV.CvEnum;
- using Emgu.CV.Structure;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Threading.Tasks;
- using System.IO.Compression;
- using System.Text;
- using WingAIDiagnosisService.Carotid.Utilities;
- using WingAIDiagnosisService.Carotid.Utilities.DetectPlaque;
- using WingAIDiagnosisService.Manage;
- using Vinno.vCloud.Common.Vid2;
- using WingAIDiagnosisService.Carotid.CarotidInterFacesData;
- using WingServerCommon.Log;
- using Vinno.vCloud.Common.Vid2.Visuals;
- using System.Runtime.InteropServices;
- using AI.DiagSystem;
- namespace WingAIDiagnosisService.Carotid
- {
- /// <summary>
- /// 模型重采样错误码
- /// </summary>
- public enum ResampleErrorCode
- {
- Success = 1000,
- InvalidVidFile,
- TooFewSourceImages,
- SaveMdlFileFailed,
- SaveSurfaceFileFailed,
- Fail
- }
- public class ResampleResult
- {
- public ResampleErrorCode ResampleErrorCode { get; }
- public CarotidAIMeasureResult CarotidAIMeasureResult { get; }
- public ResampleResult(ResampleErrorCode resampleErrorCode, CarotidAIMeasureResult carotidAIMeasureResult)
- {
- ResampleErrorCode = resampleErrorCode;
- CarotidAIMeasureResult = carotidAIMeasureResult;
- }
- public ResampleResult(ResampleErrorCode resampleErrorCode)
- {
- ResampleErrorCode = resampleErrorCode;
- CarotidAIMeasureResult = new CarotidAIMeasureResult(new DetectIntimaResult(false), new DetectPlaqueResult(false), false);
- }
- }
- struct ResampleInputData
- {
- public const string MdlZipFileVersion = "V1";
- public string MdlFilePath { get; set; }
- public string MdlZipFilePath { get; set; }
- public string SurfaceFilePath { get; set; }
- public string BaseAIImagePath { get; set; }
- public string YShapeAIImagePath { get; set; }
- public string PlaqueAIImagePath { get; set; }
- public CarotidScanType ScanType { get; set; }
- public float ScanDistance { get; set; }
- public CarotidScanDirection CarotidScanDirection { get; set; }
- }
- class ResampleModel : IDisposable
- {
- //新建模型的推荐宽度
- private int RecommendResizeX = 600;
- //从vid文件中读到的模型数据
- private byte[][] _modelDataSrc;
- //重采样生成的模型数据
- private byte[][] _modelDataDst;
- private byte[][] _surfacePicList;
- //最多线程数
- private readonly ParallelOptions _parallelOption = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount / 2 };
- //图像个数
- private int _srcLengthZ;
- //重采样后图像的宽
- //此宽度为剪掉两侧黑色区域的宽
- private int _dstLengthX;
- //重采样后图像的高
- private int _dstLengthY;
- //重采样后图像个数
- private int _dstLengthZ;
- //病人相关信息
- private byte[] _patientInformation;
- //扫描深度
- private float _scanDepth;
- private bool _isDoingResample = false;
- private static ResampleModel _instance;
- /// <summary>
- /// Instance of CntkDetect detector.
- /// </summary>
- public static ResampleModel Instance
- {
- get => _instance ?? (_instance = new ResampleModel());
- }
- /// <summary>
- /// 执行模型重采样的入口函数
- /// </summary>
- /// <returns></returns>
- public ResampleResult Resample(VinnoImageData vinnoImageData, ResampleInputData inputData, EnumPerformance performance)
- {
- try
- {
- //This is a walkaround : vid's first frame seldom have no depth info.
- var middleCount = vinnoImageData.ImageCount / 2;
- var vinnoImage = vinnoImageData.GetImage(middleCount);
- var resampleResult = PreCheckData(vinnoImageData, vinnoImage);
- if (resampleResult.ResampleErrorCode != ResampleErrorCode.Success)
- {
- return resampleResult;
- }
- var initRes = Initialize(vinnoImage, vinnoImageData, inputData.ScanType);
- if (initRes.ErrorCode == ResampleErrorCode.Success)
- {
- var result = ResampleWorkflow(vinnoImageData, inputData, initRes);
- //保存模型数据
- if (ResampleErrorCode.Success == result)
- {
- result = SaveResampleModel(inputData.MdlFilePath, inputData.MdlZipFilePath);
- }
- if (result != ResampleErrorCode.Success)
- {
- Logger.WriteLineWarn($"Resample Model SaveResampleModel failed.");
- return new ResampleResult(result);
- }
- //保存表面数据
- if (ResampleErrorCode.Success == result)
- {
- result = SaveSurface(inputData.SurfaceFilePath);
- }
- var aiResult = new CarotidAIMeasureResult(new DetectIntimaResult(false), new DetectPlaqueResult(false), false);
- bool isReadedModel = false;
- isReadedModel = GetModelVesselAndPlaque.Instance.InitializationStatus();
- if (isReadedModel == false)
- {
- GetModelVesselAndPlaque.Instance.Initialization(performance, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"));
- isReadedModel = true;
- // //Ai检测血管和斑块
- // //读取模型文件
- // string plaqueModelName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks", "Carotid",
- // Environment.OSVersion.Platform == PlatformID.Unix ? "PlaqueModel" : "PlaqueModel.emd");
- // string arteryModelName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks", "Carotid",
- // Environment.OSVersion.Platform == PlatformID.Unix ? "ArteryModel" : "ArteryModel.emd");
- // isReadedModel = GetModelVesselAndPlaque.Instance.Initialization(EnumPerformance.Medium, plaqueModelName);
- }
- List<Vector3D> points = new List<Vector3D>();
- if (isReadedModel)
- {
- //初始胡模型------------------------------------------------
- SliceHelper.Instance.SetModelSource(inputData.MdlFilePath, _dstLengthX, _dstLengthY, _dstLengthZ);
- var physicalPerPixel = _scanDepth / SliceHelper.Instance.GetModeSzie().ModelLengthY;
- GetModelVesselAndPlaque.Instance.DoDetect(SliceHelper.Instance.GetModelData(), SliceHelper.Instance.GetModeSzie());
- //获得内膜切面
- DetectIntimaResult detectIntimaResult = new DetectIntimaResult();
- detectIntimaResult = GetIntimaImage.Instance.GetImage(inputData.BaseAIImagePath, physicalPerPixel);
- //内膜平面上的点
- if (detectIntimaResult.IsSuccess)
- {
- var aiPlanePoint = GetIntimaImage.Instance.GetIntimaPlanePoint();
- if (aiPlanePoint.Count > 2)
- {
- points = new List<Vector3D>(aiPlanePoint);
- WriteIntimaAiPoint(inputData.SurfaceFilePath, points);
- }
- //获得Y型切面
- //var isGetedYImage = GetPlaneOfVesselY.Instance.GetPlane(SliceHelper.Instance.GetModelData(), SliceHelper.Instance.GetModeSzie(), inputData.YShapeAIImagePath);
- var isGetedYImage = false;
- //获得最大斑块切面
- DetectPlaqueResult detectPlaqueResult = CarotidPlaqueAutoDetection.Instance.GetPlaqueImage(SliceHelper.Instance.GetModelData(), SliceHelper.Instance.GetModeSzie(), inputData.PlaqueAIImagePath, physicalPerPixel * 10);
- aiResult = new CarotidAIMeasureResult(detectIntimaResult, detectPlaqueResult, isGetedYImage);
- }
- }
- else
- {
- Logger.WriteLineWarn($"Read cntk Model failed!");
- }
- //保存模型数据
- if (ResampleErrorCode.Success == result)
- {
- Logger.WriteLineInfo($"Resample Model success.");
- return new ResampleResult(result, aiResult);
- }
- }
- Logger.WriteLineInfo($"Resample Model InitializeData failed!");
- return new ResampleResult(ResampleErrorCode.Fail);
- }
- catch (Exception e)
- {
- Logger.WriteLineInfo($"Resample Model failed.");
- Logger.WriteLineError($"Resample Model have an error{e}");
- return new ResampleResult(ResampleErrorCode.Fail);
- }
- finally
- {
- Instance.Dispose();
- //因为每个模型大小不一样,slicehelp的复用性不大,所有释放掉
- SliceHelper.Instance.Dispose();
- GC.Collect();
- Instance._isDoingResample = false;
- }
- }
- private static ResampleResult PreCheckData(VinnoImageData vinnoImageData, VinnoImage vinnoImage)
- {
- if (Instance._isDoingResample == true)
- {
- Logger.WriteLineWarn("Resample was called multiple times.");
- return new ResampleResult(ResampleErrorCode.Fail);
- }
- Instance._isDoingResample = true;
- Logger.WriteLineInfo($"Begin Resample Model.");
- if (vinnoImageData.ImageCount < 3)
- {
- Logger.WriteLineWarn($"Resample Model too few SourceImages");
- return new ResampleResult(ResampleErrorCode.TooFewSourceImages);
- }
- if (vinnoImage == null || !vinnoImage.Visuals.Any())
- {
- Logger.WriteLineWarn($"Resample Model vinnoImage is null.");
- return new ResampleResult(ResampleErrorCode.InvalidVidFile);
- }
- return new ResampleResult(ResampleErrorCode.Success);
- }
- private bool WriteIntimaAiPoint(string surfaceFilePath, List<Vector3D> points)
- {
- using var stream = File.OpenWrite(surfaceFilePath);
- stream.Position = stream.Length;
- //写人切割面上的点
- if (points.Count > 2)
- {
- var aiClip = "AIClip";
- var data = System.Text.Encoding.Unicode.GetBytes(aiClip);
- stream.Write(BitConverter.GetBytes(data.Length), 0, sizeof(int));
- stream.Write(data, 0, data.Length);
- for (var i = 0; i < 3; ++i)
- {
- stream.Write(BitConverter.GetBytes(ChangePrecision(points[i].X)), 0, sizeof(float));
- stream.Write(BitConverter.GetBytes(ChangePrecision(points[i].Y)), 0, sizeof(float));
- stream.Write(BitConverter.GetBytes(ChangePrecision(points[i].Z)), 0, sizeof(float));
- }
- }
- return true;
- }
- private float GetScanDepth(VinnoImage vinnoImage)
- {
- if (vinnoImage.Visuals.First() is Vinno2DVisual visual)
- {
- if (visual.PhysicalCoordinates.ContainsKey(VinnoVisualAreaType.Tissue))
- {
- var physicalCoordinate = visual.PhysicalCoordinates[VinnoVisualAreaType.Tissue];
- if (physicalCoordinate is VinnoTissuePhysicalCoordinate coordinate)
- return (float)(coordinate.DepthEnd - coordinate.DepthStart);
- }
- }
- return 0;
- }
- private ResampleErrorCode ResampleWorkflow(VinnoImageData vinnoImageData, ResampleInputData inputData, ResampleInitResult result)
- {
- ResampleErrorCode errorCode = PreProcessSrcImages(vinnoImageData, result);
- if (ResampleErrorCode.Success == errorCode)
- {
- errorCode = ModelResample(inputData.ScanDistance);
- if (ResampleErrorCode.Success == errorCode)
- {
- errorCode = GetSurfacePic();
- }
- }
- return errorCode;
- }
- /// <summary>
- /// 释放资源
- /// </summary>
- public void Dispose()
- {
- _srcLengthZ = 0;
- _dstLengthX = 0;
- _dstLengthY = 0;
- _dstLengthZ = 0;
- _scanDepth = 0;
- _patientInformation = null;
- _surfacePicList = null;
- _modelDataSrc = null;
- _modelDataDst = null;
- }
- private ResampleInitResult Initialize(VinnoImage img, VinnoImageData imageData, CarotidScanType scanType)
- {
- ResampleInitResult result = new ResampleInitResult
- {
- ErrorCode = ResampleErrorCode.Fail
- };
- try
- {
- result.ResizeSize = GetResizeSize(img);
- using (var mat = new Mat())
- {
- using (var resizeImage = new Image<Gray, byte>(result.ResizeSize))
- {
- CvInvoke.Imdecode(img.ImageData, ImreadModes.Grayscale, mat);
- CvInvoke.Resize(mat, resizeImage, result.ResizeSize);
- //result.Edge = ImageEdgeDetector.DetectImageEdge(resizeImage.Mat);
- result.Edge = ImageCrop.CropImageByInfo(resizeImage.Mat, img, _scanDepth);
- }
- }
- if (result.Edge != null)
- {
- _dstLengthX = result.Edge.Width;
- _dstLengthY = result.Edge.Height;
- _modelDataSrc = new byte[imageData.ImageCount][];
- _scanDepth = GetScanDepth(img);
- _patientInformation = new VinnoCarotid3DPhysicalData(scanType == CarotidScanType.CarotidLeft ? CarotidType.Left : CarotidType.Right,
- imageData.Probe, img.Visuals).ToBytes();
- result.ErrorCode = ResampleErrorCode.Success;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Resample initialize failed:{ex}");
- }
- return result;
- }
- /// <summary>
- /// Reisze bitmaps and convert to gray8 and crop by image edge.
- /// </summary>
- /// <param name="vinnoImageData">vinno image data</param>
- /// <returns>Resample error code</returns>
- private ResampleErrorCode PreProcessSrcImages(VinnoImageData vinnoImageData, ResampleInitResult initRes)
- {
- var roiRect = new Rectangle(initRes.Edge.Left, 0, initRes.Edge.Width, initRes.Edge.Height);
- try
- {
- using (var mat = new Mat())
- {
- using (var resizeMat = new Mat(initRes.ResizeSize, DepthType.Cv8U, 1))
- {
- _srcLengthZ = 0;
- for (int i = 0; i < vinnoImageData.ImageCount; ++i)
- {
- var imageBuffer = vinnoImageData.GetImage(i).ImageData;
- if (imageBuffer.Length > 0)
- {
- CvInvoke.Imdecode(imageBuffer, ImreadModes.Grayscale, mat);
- CvInvoke.Resize(mat, resizeMat, initRes.ResizeSize);
- using var cropMat = new Mat(resizeMat, roiRect);
- _modelDataSrc[_srcLengthZ] = cropMat.ToImage<Gray, byte>().Bytes;
- _srcLengthZ++;
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Resize bitmap error when resample vid: {ex}");
- return ResampleErrorCode.Fail;
- }
- if (_srcLengthZ < DiagnosisHelper.CarotidMinImageCounts)
- {
- Logger.WriteLineWarn($"Too few images,total iamge num " + vinnoImageData.ImageCount + ", actual number of images " + _srcLengthZ + ".");
- return ResampleErrorCode.TooFewSourceImages;
- }
- return ResampleErrorCode.Success;
- }
- private Size GetResizeSize(VinnoImage img)
- {
- if (img.Width > RecommendResizeX)
- {
- double ratio = (double)img.Width / RecommendResizeX;
- return new Size(RecommendResizeX, (int)Math.Ceiling(img.Height / ratio));
- }
- else
- {
- var offset = img.Width % 4;
- var x = offset == 0 ? img.Width : img.Width - offset;
- return new Size(x, img.Height);
- }
- }
- /// <summary>
- /// 模型重采样
- /// </summary>
- /// <returns></returns>
- private ResampleErrorCode ModelResample(float scanDistance)
- {
- try
- {
- //resize后----------------------------------------------------------------------------------------
- int widthHeightDst = _dstLengthX * _dstLengthY;
- _dstLengthZ = (int)Math.Ceiling(scanDistance * _dstLengthY / _scanDepth);
- _modelDataDst = new byte[_dstLengthZ][];
- for (int i = 0; i < _dstLengthZ; i++)
- {
- _modelDataDst[i] = new byte[widthHeightDst];
- }
- int zSrc = _srcLengthZ - 1;
- int zDst = _dstLengthZ - 1;
- double ratioZ = (double)zSrc / zDst;
- double zSrcDistancePerImage = scanDistance / zSrc;
- double zDstDistancePerImage = scanDistance / zDst;
- Parallel.For(0, _dstLengthZ - 1, _parallelOption, z =>
- {
- double dstDistance = zDstDistancePerImage * z;
- //求取值区间
- var m1 = (int)Math.Floor(ratioZ * z);
- var m2 = m1 + 1;
- var d1 = dstDistance - m1 * zSrcDistancePerImage;
- var d2 = m2 * zSrcDistancePerImage - dstDistance;
- for (int cursor = 0; cursor < widthHeightDst; cursor++)
- {
- var grayM1 = _modelDataSrc[m1][cursor];
- var grayM2 = _modelDataSrc[m2][cursor];
- _modelDataDst[z][cursor] = (byte)((d2 * grayM1 + d1 * grayM2) / (d1 + d2));
- }
- });
- //拷贝最后一张图像
- Array.Copy(_modelDataSrc[zSrc], _modelDataDst[zDst], widthHeightDst);
- return ResampleErrorCode.Success;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"An error occurred during the model resampling process{e}" + "_dstLengthZ=" + _dstLengthZ + ",_srcLengthZ=" + _srcLengthZ + "," +
- "dstCount=" + _modelDataDst[_dstLengthZ - 1].Length + ",srcCount=" + _modelDataSrc[_srcLengthZ - 1].Length);
- return ResampleErrorCode.SaveMdlFileFailed;
- }
- }
- /// <summary>
- /// 保存重采样后数据
- /// </summary>
- /// <returns></returns>
- private ResampleErrorCode SaveResampleModel(string mdlFilePath, string mdlZipFilePath)
- {
- try
- {
- using (var stream = File.OpenWrite(mdlFilePath))
- {
- //写入图像张数
- stream.Write(BitConverter.GetBytes(_dstLengthZ), 0, sizeof(int));
- using var imageTemp = new Image<Gray, byte>(_dstLengthX, _dstLengthY);
- //写入图像
- for (var i = 0; i < _dstLengthZ; ++i)
- {
- WritePicFor(imageTemp, stream, _modelDataDst[i]);
- }
- }
- using (var fileStream = new FileStream(mdlZipFilePath, FileMode.Create))
- {
- var data = Encoding.Unicode.GetBytes(ResampleInputData.MdlZipFileVersion);
- fileStream.Write(BitConverter.GetBytes(data.Length), 0, sizeof(int));
- fileStream.Write(data, 0, data.Length);
- var bytes = Compress(mdlFilePath);
- fileStream.Write(BitConverter.GetBytes(bytes.Length), 0, sizeof(int));
- fileStream.Write(bytes, 0, bytes.Length);
- }
- return ResampleErrorCode.Success;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"Save the rsampled model error{e}");
- return ResampleErrorCode.SaveMdlFileFailed;
- }
- }
- private static byte[] Compress(string mdlFile)
- {
- using (var memoryStream = new MemoryStream())
- {
- using (var compressionStream = new GZipStream(memoryStream, CompressionMode.Compress))
- {
- var bytes = File.ReadAllBytes(mdlFile);
- compressionStream.Write(bytes, 0, bytes.Length);
- compressionStream.Close();
- return memoryStream.ToArray();
- }
- }
- }
- /// <summary>
- /// 获得模型的表面图
- /// </summary>
- /// <returns></returns>
- private ResampleErrorCode GetSurfacePic()
- {
- try
- {
- _surfacePicList = new byte[6][];
- _surfacePicList[0] = new byte[_dstLengthZ * _dstLengthY];
- _surfacePicList[1] = new byte[_dstLengthZ * _dstLengthY];
- _surfacePicList[2] = new byte[_dstLengthX * _dstLengthY];
- _surfacePicList[3] = new byte[_dstLengthX * _dstLengthY];
- _surfacePicList[4] = new byte[_dstLengthX * _dstLengthZ];
- _surfacePicList[5] = new byte[_dstLengthX * _dstLengthZ];
- Parallel.Invoke(
- () => CreateRightPic(_surfacePicList[0]),//pic1
- () => CreateLeftPic(_surfacePicList[1]),//pic2
- () => CreateBehindPic(_surfacePicList[2]),//pic3
- () => CreateFrontPic(_surfacePicList[3]),//第一张图,//pic4
- () => CreateTopPic(_surfacePicList[4]),//pic5
- () => CreateBottomPic(_surfacePicList[5]));//pic6
- return ResampleErrorCode.Success;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"Get the model surface picture error!{e}");
- return ResampleErrorCode.SaveSurfaceFileFailed;
- }
- }
- private void CreateBottomPic(byte[] pic)
- {
- //6
- int stride = 0;
- var temp = _dstLengthX * (_dstLengthY - 1);
- for (int j = 0; j != _dstLengthZ; ++j)
- {
- for (int i = 0; i < _dstLengthX; ++i)
- {
- pic[stride + i] = _modelDataDst[j][temp + i];
- }
- stride += _dstLengthX;
- }
- }
- private void CreateTopPic(byte[] pic)
- {
- //5
- int stride = 0;
- for (int j = 0; j != _dstLengthZ; ++j)
- {
- var j1 = _dstLengthZ - 1 - j;
- for (int i = 0; i < _dstLengthX; ++i)
- {
- pic[stride + i] = _modelDataDst[j1][i];
- }
- stride += _dstLengthX;
- }
- }
- private void CreateFrontPic(byte[] pic)
- {
- _modelDataDst[0].CopyTo(pic, 0);
- }
- private void CreateBehindPic(byte[] pic)
- {
- int stride = 0;
- int zNum = _dstLengthZ - 1;
- //最后一帧图像,围绕x轴反转
- for (int j = _dstLengthY - 1; j != -1; --j)
- {
- var count = j * _dstLengthX;
- for (int i = 0; i != _dstLengthX; ++i)
- {
- pic[stride + i] = _modelDataDst[zNum][count];
- ++count;
- }
- stride += _dstLengthX;
- }
- }
- private void CreateLeftPic(byte[] pic)
- {
- //贴图2
- for (int i = 0; i < _dstLengthY; ++i)
- {
- var stride = i * _dstLengthZ;
- for (int j = 0; j < _dstLengthZ; ++j)
- {
- var stride1 = stride + _dstLengthZ - j - 1;
- pic[stride1] = _modelDataDst[j][_dstLengthX * i];
- }
- }
- }
- private void CreateRightPic(byte[] pic)
- {
- //贴图1
- for (int j = 0; j < _dstLengthZ; ++j)
- {
- for (int i = 0; i < _dstLengthY; ++i)
- {
- var stride = i * _dstLengthZ + j;
- pic[stride] = _modelDataDst[j][_dstLengthX * i + _dstLengthX - 1];
- }
- }
- }
- private bool WritePicFor(Image<Gray, byte> imageTemp, FileStream stream, byte[] picData)
- {
- try
- {
- Marshal.Copy(picData, 0, imageTemp.Mat.DataPointer, picData.Length);
- using var buf = new Emgu.CV.Util.VectorOfByte();
- CvInvoke.Imencode(".jpg", imageTemp, buf,
- new KeyValuePair<ImwriteFlags, int>(ImwriteFlags.JpegQuality, 80));
- var jpgByte = buf.ToArray();
- stream.Write(BitConverter.GetBytes(jpgByte.Length), 0, sizeof(int));
- stream.Write(jpgByte, 0, jpgByte.Length);
- return true;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"save one surface pic failed {e}");
- return false;
- }
- }
- private bool WritePic(FileStream stream, byte[] picData, int width, int height)
- {
- try
- {
- using var imageTemp = new Mat(height, width, DepthType.Cv8U, 1);
- Marshal.Copy(picData, 0, imageTemp.DataPointer, picData.Length);
- var buf = new Emgu.CV.Util.VectorOfByte();
- using var image = imageTemp.ToImage<Gray, byte>();
- CvInvoke.Imencode(".jpg", image, buf,
- new KeyValuePair<ImwriteFlags, int>(ImwriteFlags.JpegQuality, 80));
- var jpgByte = buf.ToArray();
- stream.Write(BitConverter.GetBytes(jpgByte.Length), 0, sizeof(int));
- stream.Write(jpgByte, 0, jpgByte.Length);
- return true;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"save one surface pic failed {e}");
- return false;
- }
- }
- /// <summary>
- /// 保存表面图
- /// </summary>
- /// <returns></returns>
- private ResampleErrorCode SaveSurface(string surfaceFilePath)
- {
- try
- {
- using (var stream = File.OpenWrite(surfaceFilePath))
- {
- //模型的长宽高
- stream.Write(BitConverter.GetBytes(_dstLengthX), 0, sizeof(int));
- stream.Write(BitConverter.GetBytes(_dstLengthY), 0, sizeof(int));
- stream.Write(BitConverter.GetBytes(_dstLengthZ), 0, sizeof(int));
- //写入病人信息
- stream.Write(BitConverter.GetBytes(_patientInformation.Length), 0, sizeof(int));
- stream.Write(_patientInformation, 0, _patientInformation.Length);
- //写入图像张数
- stream.Write(BitConverter.GetBytes(6), 0, sizeof(int));
- var dic = new Dictionary<int, Size>
- {
- {0, new Size(_dstLengthZ, _dstLengthY)},
- {1, new Size(_dstLengthZ, _dstLengthY)},
- {2, new Size(_dstLengthX, _dstLengthY)},
- {3, new Size(_dstLengthX, _dstLengthY)},
- {4, new Size(_dstLengthX, _dstLengthZ)},
- {5, new Size(_dstLengthX, _dstLengthZ)}
- };
- //写入图片
- foreach (var item in dic)
- {
- if (!WritePic(stream, _surfacePicList[item.Key], item.Value.Width, item.Value.Height))
- {
- return ResampleErrorCode.SaveSurfaceFileFailed;
- }
- }
- }
- return ResampleErrorCode.Success;
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"save surface pic failed {e}");
- return ResampleErrorCode.SaveSurfaceFileFailed;
- }
- }
- private float ChangePrecision(double value)
- {
- return (float)Math.Round(value, 3, MidpointRounding.AwayFromZero);
- }
- }
- }
|