多帧合并然后遮盖
parent
3179fca112
commit
d38ce06f90
|
|
@ -1073,6 +1073,13 @@ public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
|
|||
{
|
||||
BackBatchGetToken();
|
||||
|
||||
// 确保目标目录存在
|
||||
string directory = Path.GetDirectoryName(localFilePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15367,7 +15367,7 @@
|
|||
<param name="_userInfo"></param>
|
||||
<param name="_localizer"></param>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segmentation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentBinding},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Segment},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SegmentationVersion},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
|
||||
<summary>
|
||||
分割
|
||||
</summary>
|
||||
|
|
@ -15390,6 +15390,27 @@
|
|||
<param name="addOrEditSegmentation"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.SaveSegmentationVersionAsync(System.Guid)">
|
||||
<summary>
|
||||
添加新版本
|
||||
</summary>
|
||||
<param name="segmentationId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.GetSegmentationVersionList(IRaCIS.Core.Application.ViewModel.SegmentationVersionQuery)">
|
||||
<summary>
|
||||
获取分割组历史版本
|
||||
</summary>
|
||||
<param name="inQuery"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.RestoreSegmentationVersion(IRaCIS.Core.Application.ViewModel.RestoreSegmentationVersionInDto)">
|
||||
<summary>
|
||||
恢复分割组历史版本
|
||||
</summary>
|
||||
<param name="inDto"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.SegmentationService.DeleteSegmentation(System.Guid)">
|
||||
<summary>
|
||||
删除分割组
|
||||
|
|
@ -18103,6 +18124,11 @@
|
|||
是否保存
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IRaCIS.Core.Application.ViewModel.SegmentationAddOrEdit.FileSize">
|
||||
<summary>
|
||||
文件大小,单位字节
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:IRaCIS.Core.Application.ViewModel.SegmentBindingView.IsLock">
|
||||
<summary>
|
||||
是否锁定
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
{
|
||||
var downloadJobs = new List<Func<Task>>();
|
||||
|
||||
var rootFolder = @"E:\DownloadImage";
|
||||
//var rootFolder = @"E:\DownloadImage";
|
||||
|
||||
//var rootFolder = FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment);
|
||||
var rootFolder = FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment);
|
||||
|
||||
// 获取无效字符(系统定义的)
|
||||
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||
|
|
|
|||
|
|
@ -741,6 +741,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public class DownloadDicomInstanceDto
|
||||
{
|
||||
public int NumberOfFrames { get; set; }
|
||||
public bool IsEncapsulated { get; set; }
|
||||
public Guid InstanceId { get; set; }
|
||||
public string FileName { get; set; }
|
||||
|
|
@ -1171,4 +1172,6 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
using IRaCIS.Core.Application.Contracts;
|
||||
using FellowOakDicom;
|
||||
using FellowOakDicom.Imaging;
|
||||
using FellowOakDicom.IO.Buffer;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service.ImageAndDoc.DTO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using MathNet.Numerics;
|
||||
using Medallion.Threading;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using NetTopologySuite.Algorithm;
|
||||
using SharpCompress.Common;
|
||||
using SkiaSharp;
|
||||
using System.Drawing;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
|
|
@ -29,7 +37,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
IRepository<SystemAnonymization> _systemAnonymizationRepository,
|
||||
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
|
||||
IDistributedLockProvider _distributedLockProvider, IOSSService _oSSService,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IStudyService
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache, IWebHostEnvironment _hostEnvironment) : BaseService, IStudyService
|
||||
{
|
||||
|
||||
|
||||
|
|
@ -69,6 +77,54 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
}
|
||||
|
||||
|
||||
private static async Task<bool> TryWriteMergedDicomAsync(
|
||||
Func<Task<Stream>> sourceFactory,
|
||||
Stream output)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var source = await sourceFactory();
|
||||
// 如果你是从 stream 打开
|
||||
var dicomFile = await DicomFile.OpenAsync(source);
|
||||
|
||||
//获取像素是否为封装形式
|
||||
var syntax = dicomFile.Dataset.InternalTransferSyntax;
|
||||
|
||||
//对于封装像素的文件做转换
|
||||
if (syntax.IsEncapsulated)
|
||||
{
|
||||
// 获取 Pixel Data 标签
|
||||
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
|
||||
|
||||
// 创建一个新的片段序列
|
||||
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
|
||||
// 获取每帧数据并封装为单独的片段
|
||||
for (int n = 0; n < pixelData.NumberOfFrames; n++)
|
||||
{
|
||||
var frameData = pixelData.GetFrame(n);
|
||||
newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
|
||||
}
|
||||
|
||||
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
|
||||
|
||||
var originOffsetTable = frag?.OffsetTable;
|
||||
|
||||
newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
|
||||
// 替换原有的片段序列
|
||||
dicomFile.Dataset.AddOrUpdate(newFragments);
|
||||
}
|
||||
|
||||
await dicomFile.SaveAsync(output);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 只记录,不传播
|
||||
Log.Logger.Warning($"TryWriteMergedDicomAsync failed: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标注遮盖影像 路径后面加了.MaskImage 就是遮盖的新路径
|
||||
/// </summary>
|
||||
|
|
@ -81,16 +137,16 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
}
|
||||
|
||||
|
||||
var idPathList = new List<InstanceIdPath>();
|
||||
var idPathList = new List<DownloadDicomInstanceDto>();
|
||||
|
||||
if (inCommand.SeriesId == null && inCommand.InstanceIdList != null)
|
||||
{
|
||||
idPathList = await _dicomInstanceRepository.Where(t => inCommand.InstanceIdList.Contains(t.Id)).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
|
||||
idPathList = await _dicomInstanceRepository.Where(t => inCommand.InstanceIdList.Contains(t.Id)).ProjectTo<DownloadDicomInstanceDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
idPathList = await _dicomInstanceRepository.Where(t => t.SeriesId == inCommand.SeriesId).Select(t => new InstanceIdPath { Id = t.Id, Path = t.Path }).ToListAsync();
|
||||
idPathList = await _dicomInstanceRepository.Where(t => t.SeriesId == inCommand.SeriesId).ProjectTo<DownloadDicomInstanceDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
}
|
||||
|
||||
var errorList = new List<InstanceIdPath>();
|
||||
|
|
@ -105,7 +161,53 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
|
||||
try
|
||||
{
|
||||
var inputStream = await _oSSService.GetStreamFromOSSAsync(path);
|
||||
|
||||
await using var inputStream = new MemoryStream();
|
||||
|
||||
if (item.IsEncapsulated /*&& item.NumberOfFrames > 1*/)
|
||||
{
|
||||
|
||||
var ok = await TryWriteMergedDicomAsync(() => _oSSService.GetStreamFromOSSAsync(path), inputStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
await (await _oSSService.GetStreamFromOSSAsync(path)).CopyToAsync(inputStream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//await using var ms = new MemoryStream();
|
||||
|
||||
//await inputStream.CopyToAsync(ms);
|
||||
|
||||
//ms.Position = 0;
|
||||
|
||||
|
||||
#region 测试废弃
|
||||
//var localPath = Path.Combine(FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment), Path.GetFileName(path));
|
||||
|
||||
//await _oSSService.DownLoadFromOSSAsync(path, localPath);
|
||||
|
||||
//await using var input = File.OpenRead(localPath);
|
||||
|
||||
//var outputPath = Path.Combine(FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment), "After", Path.GetFileName(path));
|
||||
|
||||
//var outputFolder = Path.GetDirectoryName(outputPath);
|
||||
//if (!string.IsNullOrEmpty(outputFolder))
|
||||
//{
|
||||
// Directory.CreateDirectory(outputFolder);
|
||||
//}
|
||||
|
||||
//await using var output = File.Create(outputPath);
|
||||
|
||||
//await DicomPixelMasker.MaskAsync(inputStream, output,inCommand.MaskRegionList);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
var outPutStream = await DicomPixelMasker.MaskAsync(inputStream, inCommand.MaskRegionList);
|
||||
|
||||
|
|
@ -120,7 +222,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
await _oSSService.DeleteFromPrefix(path, true); //清理缓存的里面的遮盖图,多次遮盖同一张图时,清除缓存很重要
|
||||
|
||||
//本身就是遮盖的图,那么就要要替换guid
|
||||
var length = Guid.Empty.ToString().Length + ".MaskDicom_".Length ;
|
||||
var length = Guid.Empty.ToString().Length + ".MaskDicom_".Length;
|
||||
|
||||
var restorePath = item.Path[..^length];
|
||||
|
||||
|
|
@ -136,14 +238,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
|
||||
var newPath = $"/{prefix}/{maskFileName}";
|
||||
|
||||
okList.Add(new InstanceIdPath() { Id = item.Id, Path = newPath });
|
||||
okList.Add(new InstanceIdPath() { Id = item.InstanceId, Path = newPath });
|
||||
|
||||
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, u => new DicomInstance() { Path = newPath, IsMasked = true });
|
||||
await _dicomInstanceRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.InstanceId, u => new DicomInstance() { Path = newPath, IsMasked = true });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
errorList.Add(new InstanceIdPath() { Id = item.Id, Path = path });
|
||||
errorList.Add(new InstanceIdPath() { Id = item.InstanceId, Path = path });
|
||||
|
||||
Log.Logger.Error(ex, $"StudyMaskImage Error for InstanceIdList Path:{path} {ex.Message}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
CreateMap<ImageMarkNoneDicomStudyBasicInfo, NoneDicomStudyBasicInfo>();
|
||||
|
||||
|
||||
CreateMap<DicomInstance, DownloadDicomInstanceDto>()
|
||||
.ForMember(d => d.InstanceId, u => u.MapFrom(s => s.Id));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,8 +129,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
public async Task<IResponseOutput> MaskImage()
|
||||
{
|
||||
|
||||
var sourceDir = @"D:\images\11\像素匿名\隐私信息2&测量值\08\08017\基线(V1)\ST01371_1970-01-01_US\IMAGE";
|
||||
var targetDir = @"D:\images\11\像素匿名\隐私信息2&测量值\08\08017\基线(V1)\ST01371_1970-01-01_US\IMAGE\after";
|
||||
var sourceDir = @"C:\work\gitea\irc-netcore-api\DownloadImage";
|
||||
var targetDir = @"C:\work\gitea\irc-netcore-api\DownloadImage\after";
|
||||
|
||||
Directory.CreateDirectory(targetDir);
|
||||
var regions = new[]
|
||||
|
|
|
|||
Loading…
Reference in New Issue