Як анонімізувати папку досліджень DICOM

Як анонімізувати папку досліджень DICOM

Цей навчальний заклад показує, як анонімізувати кілька файлів DICOM з папки за допомогою C#. При роботі з сотнями або тисячами медичних зображень, обробка пакетів є необхідною для ефективності та послідовності.

Переваги анонімності Batch

  • Ефективність:- Проводити цілі дослідження або архіви в одній операції.

  • Конзистентність:- Використовуйте ті ж правила анонімності для всіх файлів.

  • Автоматизація:- Інтеграція в автоматизовані робочі потоки та трубопроводи.

Докладніше: Підготовка навколишнього середовища

  • Налаштування Visual Studio або будь-якого сумісного .NET IDE.
  • Створення нового проекту .NET 8 консолі.
  • Завантажити Aspose.Medical з NuGet Package Manager.
  • Підготуйте вхідну папку з файлами DICOM і створіть поштовх виходу.

Крок за кроком Посібник для анонімності файлів DICOM

Крок 1: Інсталяція Aspose.Medical

Додайте бібліотеку Aspose.Medical до вашого проекту за допомогою NuGet.

Install-Package Aspose.Medical

Крок 2: Включити необхідні іменні простори

Додайте посилання на необхідні іменні простори у вашому коді.

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Anonymization;

Крок 3: Налаштування маршрутів каталогу

Визначте маршрути входу та виходу.

string inputDirectory = @"C:\DicomStudies\Input";
string outputDirectory = @"C:\DicomStudies\Anonymized";

// Ensure output directory exists
Directory.CreateDirectory(outputDirectory);

Крок 4: Завантажити файли DICOM

Отримати всі файли DICOM з вхідного каталогу, в тому числі піддиректорії.

string[] dicomFiles = Directory.GetFiles(
    inputDirectory, 
    "*.dcm", 
    SearchOption.AllDirectories
);

Console.WriteLine($"Found {dicomFiles.Length} DICOM files to process.");

Крок 5: Створіть анонімний

Створіть анонімний приклад з бажаним профілем.

Anonymizer anonymizer = new();
// Or with a custom profile:
// ConfidentialityProfile profile = ConfidentialityProfile.CreateDefault(
//     ConfidentialityProfileOptions.BasicProfile
// );
// Anonymizer anonymizer = new(profile);

Крок 6: Використання кожного файлу

Перейти через кожен файл, анонімізувати його і зберегти в каталог виходу.

int successCount = 0;
int failCount = 0;

foreach (string filePath in dicomFiles)
{
    try
    {
        // Load DICOM file
        DicomFile dcm = DicomFile.Open(filePath);
        
        // Anonymize
        DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);
        
        // Preserve relative directory structure
        string relativePath = Path.GetRelativePath(inputDirectory, filePath);
        string outputPath = Path.Combine(outputDirectory, relativePath);
        
        // Ensure subdirectory exists
        Directory.CreateDirectory(Path.GetDirectoryName(outputPath)!);
        
        // Save anonymized file
        anonymizedDcm.Save(outputPath);
        
        successCount++;
        Console.WriteLine($"✓ Processed: {relativePath}");
    }
    catch (Exception ex)
    {
        failCount++;
        Console.WriteLine($"✗ Failed: {filePath} - {ex.Message}");
    }
}

Console.WriteLine($"\nCompleted: {successCount} succeeded, {failCount} failed.");

Повний код прикладу для анонімності Batch

Ось повноцінний приклад демонстрації анонімності комплекту з доповіддю про прогрес:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Anonymization;

string inputDirectory = @"C:\DicomStudies\Input";
string outputDirectory = @"C:\DicomStudies\Anonymized";

// Ensure output directory exists
Directory.CreateDirectory(outputDirectory);

// Get all DICOM files
string[] dicomFiles = Directory.GetFiles(inputDirectory, "*.dcm", SearchOption.AllDirectories);
Console.WriteLine($"Found {dicomFiles.Length} DICOM files to process.\n");

// Create anonymizer
Anonymizer anonymizer = new();

int successCount = 0;
int failCount = 0;
int total = dicomFiles.Length;

foreach (string filePath in dicomFiles)
{
    try
    {
        DicomFile dcm = DicomFile.Open(filePath);
        DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);
        
        string relativePath = Path.GetRelativePath(inputDirectory, filePath);
        string outputPath = Path.Combine(outputDirectory, relativePath);
        Directory.CreateDirectory(Path.GetDirectoryName(outputPath)!);
        
        anonymizedDcm.Save(outputPath);
        successCount++;
        
        // Progress reporting
        double progress = (double)(successCount + failCount) / total * 100;
        Console.WriteLine($"[{progress:F1}%] ✓ {relativePath}");
    }
    catch (Exception ex)
    {
        failCount++;
        Console.WriteLine($"✗ Failed: {Path.GetFileName(filePath)} - {ex.Message}");
    }
}

Console.WriteLine($"\n========================================");
Console.WriteLine($"Batch Anonymization Complete");
Console.WriteLine($"Succeeded: {successCount}");
Console.WriteLine($"Failed: {failCount}");
Console.WriteLine($"========================================");

Паралельна обробка для кращої продуктивності

Для великих наборів даних використовуйте паралельну обробку, щоб скористатися кількома CPU-корами:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Anonymization;
using System.Collections.Concurrent;

string inputDirectory = @"C:\DicomStudies\Input";
string outputDirectory = @"C:\DicomStudies\Anonymized";

Directory.CreateDirectory(outputDirectory);

string[] dicomFiles = Directory.GetFiles(inputDirectory, "*.dcm", SearchOption.AllDirectories);
Console.WriteLine($"Found {dicomFiles.Length} DICOM files to process.\n");

// Thread-safe counters
int successCount = 0;
int failCount = 0;
ConcurrentBag<string> failedFiles = new();

// Process in parallel
Parallel.ForEach(dicomFiles, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, filePath =>
{
    try
    {
        // Each thread gets its own anonymizer instance
        Anonymizer anonymizer = new();
        
        DicomFile dcm = DicomFile.Open(filePath);
        DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);
        
        string relativePath = Path.GetRelativePath(inputDirectory, filePath);
        string outputPath = Path.Combine(outputDirectory, relativePath);
        
        lock (outputDirectory) // Ensure directory creation is thread-safe
        {
            Directory.CreateDirectory(Path.GetDirectoryName(outputPath)!);
        }
        
        anonymizedDcm.Save(outputPath);
        Interlocked.Increment(ref successCount);
    }
    catch (Exception ex)
    {
        Interlocked.Increment(ref failCount);
        failedFiles.Add($"{filePath}: {ex.Message}");
    }
});

Console.WriteLine($"\nBatch Anonymization Complete");
Console.WriteLine($"Succeeded: {successCount}");
Console.WriteLine($"Failed: {failCount}");

if (failedFiles.Any())
{
    Console.WriteLine($"\nFailed files:");
    foreach (string failure in failedFiles)
    {
        Console.WriteLine($"  - {failure}");
    }
}

Підвищена версія з підписом

Для виробничих середовищ здійснюється відповідний логінг:

using Aspose.Medical.Dicom;
using Aspose.Medical.Dicom.Anonymization;

string inputDirectory = @"C:\DicomStudies\Input";
string outputDirectory = @"C:\DicomStudies\Anonymized";
string logFile = Path.Combine(outputDirectory, "anonymization_log.txt");

Directory.CreateDirectory(outputDirectory);

string[] dicomFiles = Directory.GetFiles(inputDirectory, "*.dcm", SearchOption.AllDirectories);

Anonymizer anonymizer = new();
List<string> logEntries = new();

logEntries.Add($"Anonymization started: {DateTime.Now}");
logEntries.Add($"Input directory: {inputDirectory}");
logEntries.Add($"Output directory: {outputDirectory}");
logEntries.Add($"Total files to process: {dicomFiles.Length}");
logEntries.Add("---");

int successCount = 0;
int failCount = 0;

foreach (string filePath in dicomFiles)
{
    string relativePath = Path.GetRelativePath(inputDirectory, filePath);
    
    try
    {
        DicomFile dcm = DicomFile.Open(filePath);
        DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);
        
        string outputPath = Path.Combine(outputDirectory, relativePath);
        Directory.CreateDirectory(Path.GetDirectoryName(outputPath)!);
        anonymizedDcm.Save(outputPath);
        
        successCount++;
        logEntries.Add($"SUCCESS: {relativePath}");
    }
    catch (Exception ex)
    {
        failCount++;
        logEntries.Add($"FAILED: {relativePath} - {ex.Message}");
    }
}

logEntries.Add("---");
logEntries.Add($"Anonymization completed: {DateTime.Now}");
logEntries.Add($"Succeeded: {successCount}");
logEntries.Add($"Failed: {failCount}");

// Write log file
File.WriteAllLines(logFile, logEntries);

Console.WriteLine($"Processing complete. Log saved to: {logFile}");

Найкращі практики для обробки батарей

  • Продовжуйте копіювати дані: завжди обробляється копия ваших оригінальних даних, а не самих оригій.
  • Лог Всі операції: Зберігайте детальні записи, з яких файли були оброблені і з якими виникли помилки.
  • Тест Перший: Виконайте невеликий зразк перед тим, як обробляти весь набір даних.
  • Monitor Disk Space: Забезпечити достатній простір на диску для вихідних файлів.
  • ** Торгівельні перерви**: розглянемо функціонування пункту перевірки/резуму для дуже великих пакетів.

Troubleshooting

Проблеми пам’яті з великими даними

Для дуже великих файлів або наборів даних, переробляти файли один за одним без зберігання посилань:

foreach (string filePath in dicomFiles)
{
    using (DicomFile dcm = DicomFile.Open(filePath))
    {
        DicomFile anonymizedDcm = anonymizer.Anonymize(dcm);
        anonymizedDcm.Save(outputPath);
    }
    // Files are disposed after each iteration
}

Помилки дозволу

Переконайтеся, що ваша заявка прочитала доступ до вхідного каталогу і написала дохід до вихідних каталогів.

Заключення

Цей навчальний заклад показав, як об’єднати анонімні файли DICOM в C# за допомогою Aspose.Medical. Незалежно від того, чи обробляються сотні або тисячі файлів, підхід об’єднання забезпечує постійну анонімізацію по всьому вашому набору даних, забезпечуючи відстеження прогресу та розв’язання помилок для надійності виробництва.

 Українська