HealthImaging exemplos de uso SDK para C++ - AWS SDKExemplos de código

Há mais AWS SDK exemplos disponíveis no GitHub repositório AWS Doc SDK Examples.

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

HealthImaging exemplos de uso SDK para C++

Os exemplos de código a seguir mostram como realizar ações e implementar cenários comuns usando o AWS SDK for C++ with HealthImaging.

Ações são trechos de código de programas maiores e devem ser executadas em contexto. Embora as ações mostrem como chamar funções de serviço individuais, é possível ver as ações no contexto em seus cenários relacionados.

Os cenários são exemplos de código que mostram como realizar tarefas específicas chamando várias funções dentro de um serviço ou combinadas com outros Serviços da AWS.

Cada exemplo inclui um link para o código-fonte completo, onde você pode encontrar instruções sobre como configurar e executar o código no contexto.

Conceitos básicos

Os exemplos de código a seguir mostram como começar a usar HealthImaging.

SDKpara C++

Código para o CMakeLists arquivo.txtCMake.

# Set the minimum required version of CMake for this project. cmake_minimum_required(VERSION 3.13) # Set the AWS service components used by this project. set(SERVICE_COMPONENTS medical-imaging) # Set this project's name. project("hello_health-imaging") # Set the C++ standard to use to build this target. # At least C++ 11 is required for the AWS SDK for C++. set(CMAKE_CXX_STANDARD 11) # Use the MSVC variable to determine if this is a Windows build. set(WINDOWS_BUILD ${MSVC}) if (WINDOWS_BUILD) # Set the location where CMake can find the installed libraries for the AWS SDK. string(REPLACE ";" "/aws-cpp-sdk-all;" SYSTEM_MODULE_PATH "${CMAKE_SYSTEM_PREFIX_PATH}/aws-cpp-sdk-all") list(APPEND CMAKE_PREFIX_PATH ${SYSTEM_MODULE_PATH}) endif () # Find the AWS SDK for C++ package. find_package(AWSSDK REQUIRED COMPONENTS ${SERVICE_COMPONENTS}) if (WINDOWS_BUILD AND AWSSDK_INSTALL_AS_SHARED_LIBS) # Copy relevant AWS SDK for C++ libraries into the current binary directory for running and debugging. # set(BIN_SUB_DIR "/Debug") # If you are building from the command line, you may need to uncomment this # and set the proper subdirectory to the executable location. AWSSDK_CPY_DYN_LIBS(SERVICE_COMPONENTS "" ${CMAKE_CURRENT_BINARY_DIR}${BIN_SUB_DIR}) endif () add_executable(${PROJECT_NAME} hello_health_imaging.cpp) target_link_libraries(${PROJECT_NAME} ${AWSSDK_LINK_LIBRARIES})

Código para o arquivo de origem hello_health_imaging.cpp.

#include <aws/core/Aws.h> #include <aws/medical-imaging/MedicalImagingClient.h> #include <aws/medical-imaging/model/ListDatastoresRequest.h> #include <iostream> /* * A "Hello HealthImaging" starter application which initializes an AWS HealthImaging (HealthImaging) client * and lists the HealthImaging data stores in the current account. * * main function * * Usage: 'hello_health-imaging' * */ #include <aws/core/auth/AWSCredentialsProviderChain.h> #include <aws/core/platform/Environment.h> int main(int argc, char **argv) { (void) argc; (void) argv; Aws::SDKOptions options; // Optional: change the log level for debugging. // options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Debug; Aws::InitAPI(options); // Should only be called once. { Aws::Client::ClientConfiguration clientConfig; // Optional: Set to the AWS Region (overrides config file). // clientConfig.region = "us-east-1"; Aws::MedicalImaging::MedicalImagingClient medicalImagingClient(clientConfig); Aws::MedicalImaging::Model::ListDatastoresRequest listDatastoresRequest; Aws::Vector<Aws::MedicalImaging::Model::DatastoreSummary> allDataStoreSummaries; Aws::String nextToken; // Used for paginated results. do { if (!nextToken.empty()) { listDatastoresRequest.SetNextToken(nextToken); } Aws::MedicalImaging::Model::ListDatastoresOutcome listDatastoresOutcome = medicalImagingClient.ListDatastores(listDatastoresRequest); if (listDatastoresOutcome.IsSuccess()) { const Aws::Vector<Aws::MedicalImaging::Model::DatastoreSummary> &dataStoreSummaries = listDatastoresOutcome.GetResult().GetDatastoreSummaries(); allDataStoreSummaries.insert(allDataStoreSummaries.cend(), dataStoreSummaries.cbegin(), dataStoreSummaries.cend()); nextToken = listDatastoresOutcome.GetResult().GetNextToken(); } else { std::cerr << "ListDatastores error: " << listDatastoresOutcome.GetError().GetMessage() << std::endl; break; } } while (!nextToken.empty()); std::cout << allDataStoreSummaries.size() << " HealthImaging data " << ((allDataStoreSummaries.size() == 1) ? "store was retrieved." : "stores were retrieved.") << std::endl; for (auto const &dataStoreSummary: allDataStoreSummaries) { std::cout << " Datastore: " << dataStoreSummary.GetDatastoreName() << std::endl; std::cout << " Datastore ID: " << dataStoreSummary.GetDatastoreId() << std::endl; } } Aws::ShutdownAPI(options); // Should only be called once. return 0; }
  • Para API obter detalhes, consulte ListDatastoresem AWS SDK for C++ APIReferência.

nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

Ações

O código de exemplo a seguir mostra como usar DeleteImageSet.

SDKpara C++
//! Routine which deletes an AWS HealthImaging image set. /*! \param dataStoreID: The HealthImaging data store ID. \param imageSetID: The image set ID. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::deleteImageSet( const Aws::String &dataStoreID, const Aws::String &imageSetID, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::DeleteImageSetRequest request; request.SetDatastoreId(dataStoreID); request.SetImageSetId(imageSetID); Aws::MedicalImaging::Model::DeleteImageSetOutcome outcome = client.DeleteImageSet( request); if (outcome.IsSuccess()) { std::cout << "Successfully deleted image set " << imageSetID << " from data store " << dataStoreID << std::endl; } else { std::cerr << "Error deleting image set " << imageSetID << " from data store " << dataStoreID << ": " << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); }
  • Para API obter detalhes, consulte DeleteImageSetem AWS SDK for C++ APIReferência.

nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

O código de exemplo a seguir mostra como usar GetDICOMImportJob.

SDKpara C++
//! Routine which gets a HealthImaging DICOM import job's properties. /*! \param dataStoreID: The HealthImaging data store ID. \param importJobID: The DICOM import job ID \param clientConfig: Aws client configuration. \return GetDICOMImportJobOutcome: The import job outcome. */ Aws::MedicalImaging::Model::GetDICOMImportJobOutcome AwsDoc::Medical_Imaging::getDICOMImportJob(const Aws::String &dataStoreID, const Aws::String &importJobID, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::GetDICOMImportJobRequest request; request.SetDatastoreId(dataStoreID); request.SetJobId(importJobID); Aws::MedicalImaging::Model::GetDICOMImportJobOutcome outcome = client.GetDICOMImportJob( request); if (!outcome.IsSuccess()) { std::cerr << "GetDICOMImportJob error: " << outcome.GetError().GetMessage() << std::endl; } return outcome; }
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

O código de exemplo a seguir mostra como usar GetImageFrame.

SDKpara C++
//! Routine which downloads an AWS HealthImaging image frame. /*! \param dataStoreID: The HealthImaging data store ID. \param imageSetID: The image set ID. \param frameID: The image frame ID. \param jphFile: File to store the downloaded frame. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::getImageFrame(const Aws::String &dataStoreID, const Aws::String &imageSetID, const Aws::String &frameID, const Aws::String &jphFile, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::GetImageFrameRequest request; request.SetDatastoreId(dataStoreID); request.SetImageSetId(imageSetID); Aws::MedicalImaging::Model::ImageFrameInformation imageFrameInformation; imageFrameInformation.SetImageFrameId(frameID); request.SetImageFrameInformation(imageFrameInformation); Aws::MedicalImaging::Model::GetImageFrameOutcome outcome = client.GetImageFrame( request); if (outcome.IsSuccess()) { std::cout << "Successfully retrieved image frame." << std::endl; auto &buffer = outcome.GetResult().GetImageFrameBlob(); std::ofstream outfile(jphFile, std::ios::binary); outfile << buffer.rdbuf(); } else { std::cout << "Error retrieving image frame." << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); }
  • Para API obter detalhes, consulte GetImageFrameem AWS SDK for C++ APIReferência.

nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

O código de exemplo a seguir mostra como usar GetImageSetMetadata.

SDKpara C++

Função de utilitário para obter metadados do conjunto de imagens.

//! Routine which gets a HealthImaging image set's metadata. /*! \param dataStoreID: The HealthImaging data store ID. \param imageSetID: The HealthImaging image set ID. \param versionID: The HealthImaging image set version ID, ignored if empty. \param outputFilePath: The path where the metadata will be stored as gzipped json. \param clientConfig: Aws client configuration. \\return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::getImageSetMetadata(const Aws::String &dataStoreID, const Aws::String &imageSetID, const Aws::String &versionID, const Aws::String &outputFilePath, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::Model::GetImageSetMetadataRequest request; request.SetDatastoreId(dataStoreID); request.SetImageSetId(imageSetID); if (!versionID.empty()) { request.SetVersionId(versionID); } Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::GetImageSetMetadataOutcome outcome = client.GetImageSetMetadata( request); if (outcome.IsSuccess()) { std::ofstream file(outputFilePath, std::ios::binary); auto &metadata = outcome.GetResult().GetImageSetMetadataBlob(); file << metadata.rdbuf(); } else { std::cerr << "Failed to get image set metadata: " << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); }

Obter metadados do conjunto de imagens sem versão.

if (AwsDoc::Medical_Imaging::getImageSetMetadata(dataStoreID, imageSetID, "", outputFilePath, clientConfig)) { std::cout << "Successfully retrieved image set metadata." << std::endl; std::cout << "Metadata stored in: " << outputFilePath << std::endl; }

Obter metadados do conjunto de imagens com versão.

if (AwsDoc::Medical_Imaging::getImageSetMetadata(dataStoreID, imageSetID, versionID, outputFilePath, clientConfig)) { std::cout << "Successfully retrieved image set metadata." << std::endl; std::cout << "Metadata stored in: " << outputFilePath << std::endl; }
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

O código de exemplo a seguir mostra como usar SearchImageSets.

SDKpara C++

A função de utilitário para pesquisar conjuntos de imagens.

//! Routine which searches for image sets based on defined input attributes. /*! \param dataStoreID: The HealthImaging data store ID. \param searchCriteria: A search criteria instance. \param imageSetResults: Vector to receive the image set IDs. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::searchImageSets(const Aws::String &dataStoreID, const Aws::MedicalImaging::Model::SearchCriteria &searchCriteria, Aws::Vector<Aws::String> &imageSetResults, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::SearchImageSetsRequest request; request.SetDatastoreId(dataStoreID); request.SetSearchCriteria(searchCriteria); Aws::String nextToken; // Used for paginated results. bool result = true; do { if (!nextToken.empty()) { request.SetNextToken(nextToken); } Aws::MedicalImaging::Model::SearchImageSetsOutcome outcome = client.SearchImageSets( request); if (outcome.IsSuccess()) { for (auto &imageSetMetadataSummary: outcome.GetResult().GetImageSetsMetadataSummaries()) { imageSetResults.push_back(imageSetMetadataSummary.GetImageSetId()); } nextToken = outcome.GetResult().GetNextToken(); } else { std::cout << "Error: " << outcome.GetError().GetMessage() << std::endl; result = false; } } while (!nextToken.empty()); return result; }

Caso de uso #1: EQUAL operador.

Aws::Vector<Aws::String> imageIDsForPatientID; Aws::MedicalImaging::Model::SearchCriteria searchCriteriaEqualsPatientID; Aws::Vector<Aws::MedicalImaging::Model::SearchFilter> patientIDSearchFilters = { Aws::MedicalImaging::Model::SearchFilter().WithOperator(Aws::MedicalImaging::Model::Operator::EQUAL) .WithValues({Aws::MedicalImaging::Model::SearchByAttributeValue().WithDICOMPatientId(patientID)}) }; searchCriteriaEqualsPatientID.SetFilters(patientIDSearchFilters); bool result = AwsDoc::Medical_Imaging::searchImageSets(dataStoreID, searchCriteriaEqualsPatientID, imageIDsForPatientID, clientConfig); if (result) { std::cout << imageIDsForPatientID.size() << " image sets found for the patient with ID '" << patientID << "'." << std::endl; for (auto &imageSetResult : imageIDsForPatientID) { std::cout << " Image set with ID '" << imageSetResult << std::endl; } }

Caso de uso #2: BETWEEN operador usando DICOMStudyDate DICOMStudyTime e.

Aws::MedicalImaging::Model::SearchByAttributeValue useCase2StartDate; useCase2StartDate.SetDICOMStudyDateAndTime(Aws::MedicalImaging::Model::DICOMStudyDateAndTime() .WithDICOMStudyDate("19990101") .WithDICOMStudyTime("000000.000")); Aws::MedicalImaging::Model::SearchByAttributeValue useCase2EndDate; useCase2EndDate.SetDICOMStudyDateAndTime(Aws::MedicalImaging::Model::DICOMStudyDateAndTime() .WithDICOMStudyDate(Aws::Utils::DateTime(std::chrono::system_clock::now()).ToLocalTimeString("%Y%m%d")) .WithDICOMStudyTime("000000.000")); Aws::MedicalImaging::Model::SearchFilter useCase2SearchFilter; useCase2SearchFilter.SetValues({useCase2StartDate, useCase2EndDate}); useCase2SearchFilter.SetOperator(Aws::MedicalImaging::Model::Operator::BETWEEN); Aws::MedicalImaging::Model::SearchCriteria useCase2SearchCriteria; useCase2SearchCriteria.SetFilters({useCase2SearchFilter}); Aws::Vector<Aws::String> usesCase2Results; result = AwsDoc::Medical_Imaging::searchImageSets(dataStoreID, useCase2SearchCriteria, usesCase2Results, clientConfig); if (result) { std::cout << usesCase2Results.size() << " image sets found for between 1999/01/01 and present." << std::endl; for (auto &imageSetResult : usesCase2Results) { std::cout << " Image set with ID '" << imageSetResult << std::endl; } }

Caso de uso #3: BETWEEN operador usandocreatedAt. Os estudos de tempo foram previamente persistidos.

Aws::MedicalImaging::Model::SearchByAttributeValue useCase3StartDate; useCase3StartDate.SetCreatedAt(Aws::Utils::DateTime("20231130T000000000Z",Aws::Utils::DateFormat::ISO_8601_BASIC)); Aws::MedicalImaging::Model::SearchByAttributeValue useCase3EndDate; useCase3EndDate.SetCreatedAt(Aws::Utils::DateTime(std::chrono::system_clock::now())); Aws::MedicalImaging::Model::SearchFilter useCase3SearchFilter; useCase3SearchFilter.SetValues({useCase3StartDate, useCase3EndDate}); useCase3SearchFilter.SetOperator(Aws::MedicalImaging::Model::Operator::BETWEEN); Aws::MedicalImaging::Model::SearchCriteria useCase3SearchCriteria; useCase3SearchCriteria.SetFilters({useCase3SearchFilter}); Aws::Vector<Aws::String> usesCase3Results; result = AwsDoc::Medical_Imaging::searchImageSets(dataStoreID, useCase3SearchCriteria, usesCase3Results, clientConfig); if (result) { std::cout << usesCase3Results.size() << " image sets found for created between 2023/11/30 and present." << std::endl; for (auto &imageSetResult : usesCase3Results) { std::cout << " Image set with ID '" << imageSetResult << std::endl; } }

Caso de uso #4: EQUAL operador ligado DICOMSeriesInstanceUID e BETWEEN ligado updatedAt e classifique a resposta em ASC ordem no updatedAt campo.

Aws::MedicalImaging::Model::SearchByAttributeValue useCase4StartDate; useCase4StartDate.SetUpdatedAt(Aws::Utils::DateTime("20231130T000000000Z",Aws::Utils::DateFormat::ISO_8601_BASIC)); Aws::MedicalImaging::Model::SearchByAttributeValue useCase4EndDate; useCase4EndDate.SetUpdatedAt(Aws::Utils::DateTime(std::chrono::system_clock::now())); Aws::MedicalImaging::Model::SearchFilter useCase4SearchFilterBetween; useCase4SearchFilterBetween.SetValues({useCase4StartDate, useCase4EndDate}); useCase4SearchFilterBetween.SetOperator(Aws::MedicalImaging::Model::Operator::BETWEEN); Aws::MedicalImaging::Model::SearchByAttributeValue seriesInstanceUID; seriesInstanceUID.SetDICOMSeriesInstanceUID(dicomSeriesInstanceUID); Aws::MedicalImaging::Model::SearchFilter useCase4SearchFilterEqual; useCase4SearchFilterEqual.SetValues({seriesInstanceUID}); useCase4SearchFilterEqual.SetOperator(Aws::MedicalImaging::Model::Operator::EQUAL); Aws::MedicalImaging::Model::SearchCriteria useCase4SearchCriteria; useCase4SearchCriteria.SetFilters({useCase4SearchFilterBetween, useCase4SearchFilterEqual}); Aws::MedicalImaging::Model::Sort useCase4Sort; useCase4Sort.SetSortField(Aws::MedicalImaging::Model::SortField::updatedAt); useCase4Sort.SetSortOrder(Aws::MedicalImaging::Model::SortOrder::ASC); useCase4SearchCriteria.SetSort(useCase4Sort); Aws::Vector<Aws::String> usesCase4Results; result = AwsDoc::Medical_Imaging::searchImageSets(dataStoreID, useCase4SearchCriteria, usesCase4Results, clientConfig); if (result) { std::cout << usesCase4Results.size() << " image sets found for EQUAL operator " << "on DICOMSeriesInstanceUID and BETWEEN on updatedAt and sort response\n" << "in ASC order on updatedAt field." << std::endl; for (auto &imageSetResult : usesCase4Results) { std::cout << " Image set with ID '" << imageSetResult << std::endl; } }
  • Para API obter detalhes, consulte SearchImageSetsem AWS SDK for C++ APIReferência.

nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

O código de exemplo a seguir mostra como usar StartDICOMImportJob.

SDKpara C++
//! Routine which starts a HealthImaging import job. /*! \param dataStoreID: The HealthImaging data store ID. \param inputBucketName: The name of the Amazon S3 bucket containing the DICOM files. \param inputDirectory: The directory in the S3 bucket containing the DICOM files. \param outputBucketName: The name of the S3 bucket for the output. \param outputDirectory: The directory in the S3 bucket to store the output. \param roleArn: The ARN of the IAM role with permissions for the import. \param importJobId: A string to receive the import job ID. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::startDICOMImportJob( const Aws::String &dataStoreID, const Aws::String &inputBucketName, const Aws::String &inputDirectory, const Aws::String &outputBucketName, const Aws::String &outputDirectory, const Aws::String &roleArn, Aws::String &importJobId, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient medicalImagingClient(clientConfig); Aws::String inputURI = "s3://" + inputBucketName + "/" + inputDirectory + "/"; Aws::String outputURI = "s3://" + outputBucketName + "/" + outputDirectory + "/"; Aws::MedicalImaging::Model::StartDICOMImportJobRequest startDICOMImportJobRequest; startDICOMImportJobRequest.SetDatastoreId(dataStoreID); startDICOMImportJobRequest.SetDataAccessRoleArn(roleArn); startDICOMImportJobRequest.SetInputS3Uri(inputURI); startDICOMImportJobRequest.SetOutputS3Uri(outputURI); Aws::MedicalImaging::Model::StartDICOMImportJobOutcome startDICOMImportJobOutcome = medicalImagingClient.StartDICOMImportJob( startDICOMImportJobRequest); if (startDICOMImportJobOutcome.IsSuccess()) { importJobId = startDICOMImportJobOutcome.GetResult().GetJobId(); } else { std::cerr << "Failed to start DICOM import job because " << startDICOMImportJobOutcome.GetError().GetMessage() << std::endl; } return startDICOMImportJobOutcome.IsSuccess(); }
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

Cenários

O exemplo de código a seguir mostra como importar DICOM arquivos e baixar molduras de imagem em HealthImaging.

A implementação é estruturada como um aplicativo de linha de comando de fluxo de trabalho.

  • Configure recursos para uma DICOM importação.

  • Importe DICOM arquivos para um armazenamento de dados.

  • Recupere o conjunto de imagens IDs para o trabalho de importação.

  • Recupere a moldura da imagem IDs para os conjuntos de imagens.

  • Baixe, decodifique e verifique os quadros de imagem.

  • Limpar recursos.

SDKpara C++

Crie uma AWS CloudFormation pilha com os recursos necessários.

Aws::String inputBucketName; Aws::String outputBucketName; Aws::String dataStoreId; Aws::String roleArn; Aws::String stackName; if (askYesNoQuestion( "Would you like to let this workflow create the resources for you? (y/n) ")) { stackName = askQuestion( "Enter a name for the AWS CloudFormation stack to create. "); Aws::String dataStoreName = askQuestion( "Enter a name for the HealthImaging datastore to create. "); Aws::Map<Aws::String, Aws::String> outputs = createCloudFormationStack( stackName, dataStoreName, clientConfiguration); if (!retrieveOutputs(outputs, dataStoreId, inputBucketName, outputBucketName, roleArn)) { return false; } std::cout << "The following resources have been created." << std::endl; std::cout << "A HealthImaging datastore with ID: " << dataStoreId << "." << std::endl; std::cout << "An Amazon S3 input bucket named: " << inputBucketName << "." << std::endl; std::cout << "An Amazon S3 output bucket named: " << outputBucketName << "." << std::endl; std::cout << "An IAM role with the ARN: " << roleArn << "." << std::endl; askQuestion("Enter return to continue.", alwaysTrueTest); } else { std::cout << "You have chosen to use preexisting resources:" << std::endl; dataStoreId = askQuestion( "Enter the data store ID of the HealthImaging datastore you wish to use: "); inputBucketName = askQuestion( "Enter the name of the S3 input bucket you wish to use: "); outputBucketName = askQuestion( "Enter the name of the S3 output bucket you wish to use: "); roleArn = askQuestion( "Enter the ARN for the IAM role with the proper permissions to import a DICOM series: "); }

Copie DICOM arquivos para o bucket de importação do Amazon S3.

std::cout << "This workflow uses DICOM files from the National Cancer Institute Imaging Data\n" << "Commons (IDC) Collections." << std::endl; std::cout << "Here is the link to their website." << std::endl; std::cout << "https://registry.opendata.aws/nci-imaging-data-commons/" << std::endl; std::cout << "We will use DICOM files stored in an S3 bucket managed by the IDC." << std::endl; std::cout << "First one of the DICOM folders in the IDC collection must be copied to your\n" "input S3 bucket." << std::endl; std::cout << "You have the choice of one of the following " << IDC_ImageChoices.size() << " folders to copy." << std::endl; int index = 1; for (auto &idcChoice: IDC_ImageChoices) { std::cout << index << " - " << idcChoice.mDescription << std::endl; index++; } int choice = askQuestionForIntRange("Choose DICOM files to import: ", 1, 4); Aws::String fromDirectory = IDC_ImageChoices[choice - 1].mDirectory; Aws::String inputDirectory = "input"; std::cout << "The files in the directory '" << fromDirectory << "' in the bucket '" << IDC_S3_BucketName << "' will be copied " << std::endl; std::cout << "to the folder '" << inputDirectory << "/" << fromDirectory << "' in the bucket '" << inputBucketName << "'." << std::endl; askQuestion("Enter return to start the copy.", alwaysTrueTest); if (!AwsDoc::Medical_Imaging::copySeriesBetweenBuckets( IDC_S3_BucketName, fromDirectory, inputBucketName, inputDirectory, clientConfiguration)) { std::cerr << "This workflow will exit because of an error." << std::endl; cleanup(stackName, dataStoreId, clientConfiguration); return false; }

Importe os DICOM arquivos para o armazenamento de dados do Amazon S3.

bool AwsDoc::Medical_Imaging::startDicomImport(const Aws::String &dataStoreID, const Aws::String &inputBucketName, const Aws::String &inputDirectory, const Aws::String &outputBucketName, const Aws::String &outputDirectory, const Aws::String &roleArn, Aws::String &importJobId, const Aws::Client::ClientConfiguration &clientConfiguration) { bool result = false; if (startDICOMImportJob(dataStoreID, inputBucketName, inputDirectory, outputBucketName, outputDirectory, roleArn, importJobId, clientConfiguration)) { std::cout << "DICOM import job started with job ID " << importJobId << "." << std::endl; result = waitImportJobCompleted(dataStoreID, importJobId, clientConfiguration); if (result) { std::cout << "DICOM import job completed." << std::endl; } } return result; } //! Routine which starts a HealthImaging import job. /*! \param dataStoreID: The HealthImaging data store ID. \param inputBucketName: The name of the Amazon S3 bucket containing the DICOM files. \param inputDirectory: The directory in the S3 bucket containing the DICOM files. \param outputBucketName: The name of the S3 bucket for the output. \param outputDirectory: The directory in the S3 bucket to store the output. \param roleArn: The ARN of the IAM role with permissions for the import. \param importJobId: A string to receive the import job ID. \param clientConfig: Aws client configuration. \return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::startDICOMImportJob( const Aws::String &dataStoreID, const Aws::String &inputBucketName, const Aws::String &inputDirectory, const Aws::String &outputBucketName, const Aws::String &outputDirectory, const Aws::String &roleArn, Aws::String &importJobId, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient medicalImagingClient(clientConfig); Aws::String inputURI = "s3://" + inputBucketName + "/" + inputDirectory + "/"; Aws::String outputURI = "s3://" + outputBucketName + "/" + outputDirectory + "/"; Aws::MedicalImaging::Model::StartDICOMImportJobRequest startDICOMImportJobRequest; startDICOMImportJobRequest.SetDatastoreId(dataStoreID); startDICOMImportJobRequest.SetDataAccessRoleArn(roleArn); startDICOMImportJobRequest.SetInputS3Uri(inputURI); startDICOMImportJobRequest.SetOutputS3Uri(outputURI); Aws::MedicalImaging::Model::StartDICOMImportJobOutcome startDICOMImportJobOutcome = medicalImagingClient.StartDICOMImportJob( startDICOMImportJobRequest); if (startDICOMImportJobOutcome.IsSuccess()) { importJobId = startDICOMImportJobOutcome.GetResult().GetJobId(); } else { std::cerr << "Failed to start DICOM import job because " << startDICOMImportJobOutcome.GetError().GetMessage() << std::endl; } return startDICOMImportJobOutcome.IsSuccess(); } //! Routine which waits for a DICOM import job to complete. /*! * @param dataStoreID: The HealthImaging data store ID. * @param importJobId: The import job ID. * @param clientConfiguration : Aws client configuration. * @return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::waitImportJobCompleted(const Aws::String &datastoreID, const Aws::String &importJobId, const Aws::Client::ClientConfiguration &clientConfiguration) { Aws::MedicalImaging::Model::JobStatus jobStatus = Aws::MedicalImaging::Model::JobStatus::IN_PROGRESS; while (jobStatus == Aws::MedicalImaging::Model::JobStatus::IN_PROGRESS) { std::this_thread::sleep_for(std::chrono::seconds(1)); Aws::MedicalImaging::Model::GetDICOMImportJobOutcome getDicomImportJobOutcome = getDICOMImportJob( datastoreID, importJobId, clientConfiguration); if (getDicomImportJobOutcome.IsSuccess()) { jobStatus = getDicomImportJobOutcome.GetResult().GetJobProperties().GetJobStatus(); std::cout << "DICOM import job status: " << Aws::MedicalImaging::Model::JobStatusMapper::GetNameForJobStatus( jobStatus) << std::endl; } else { std::cerr << "Failed to get import job status because " << getDicomImportJobOutcome.GetError().GetMessage() << std::endl; return false; } } return jobStatus == Aws::MedicalImaging::Model::JobStatus::COMPLETED; } //! Routine which gets a HealthImaging DICOM import job's properties. /*! \param dataStoreID: The HealthImaging data store ID. \param importJobID: The DICOM import job ID \param clientConfig: Aws client configuration. \return GetDICOMImportJobOutcome: The import job outcome. */ Aws::MedicalImaging::Model::GetDICOMImportJobOutcome AwsDoc::Medical_Imaging::getDICOMImportJob(const Aws::String &dataStoreID, const Aws::String &importJobID, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::GetDICOMImportJobRequest request; request.SetDatastoreId(dataStoreID); request.SetJobId(importJobID); Aws::MedicalImaging::Model::GetDICOMImportJobOutcome outcome = client.GetDICOMImportJob( request); if (!outcome.IsSuccess()) { std::cerr << "GetDICOMImportJob error: " << outcome.GetError().GetMessage() << std::endl; } return outcome; }

Obtenha conjuntos de imagens criados pelo trabalho DICOM de importação.

bool AwsDoc::Medical_Imaging::getImageSetsForDicomImportJob(const Aws::String &datastoreID, const Aws::String &importJobId, Aws::Vector<Aws::String> &imageSets, const Aws::Client::ClientConfiguration &clientConfiguration) { Aws::MedicalImaging::Model::GetDICOMImportJobOutcome getDicomImportJobOutcome = getDICOMImportJob( datastoreID, importJobId, clientConfiguration); bool result = false; if (getDicomImportJobOutcome.IsSuccess()) { auto outputURI = getDicomImportJobOutcome.GetResult().GetJobProperties().GetOutputS3Uri(); Aws::Http::URI uri(outputURI); const Aws::String &bucket = uri.GetAuthority(); Aws::String key = uri.GetPath(); Aws::S3::S3Client s3Client(clientConfiguration); Aws::S3::Model::GetObjectRequest objectRequest; objectRequest.SetBucket(bucket); objectRequest.SetKey(key + "/" + IMPORT_JOB_MANIFEST_FILE_NAME); auto getObjectOutcome = s3Client.GetObject(objectRequest); if (getObjectOutcome.IsSuccess()) { auto &data = getObjectOutcome.GetResult().GetBody(); std::stringstream stringStream; stringStream << data.rdbuf(); try { // Use JMESPath to extract the image set IDs. // https://jmespath.org/specification.html std::string jmesPathExpression = "jobSummary.imageSetsSummary[].imageSetId"; jsoncons::json doc = jsoncons::json::parse(stringStream.str()); jsoncons::json imageSetsJson = jsoncons::jmespath::search(doc, jmesPathExpression);\ for (auto &imageSet: imageSetsJson.array_range()) { imageSets.push_back(imageSet.as_string()); } result = true; } catch (const std::exception &e) { std::cerr << e.what() << '\n'; } } else { std::cerr << "Failed to get object because " << getObjectOutcome.GetError().GetMessage() << std::endl; } } else { std::cerr << "Failed to get import job status because " << getDicomImportJobOutcome.GetError().GetMessage() << std::endl; } return result; }

Obtenha informações sobre os quadros de imagem de conjuntos de imagens.

bool AwsDoc::Medical_Imaging::getImageFramesForImageSet(const Aws::String &dataStoreID, const Aws::String &imageSetID, const Aws::String &outDirectory, Aws::Vector<ImageFrameInfo> &imageFrames, const Aws::Client::ClientConfiguration &clientConfiguration) { Aws::String fileName = outDirectory + "/" + imageSetID + "_metadata.json.gzip"; bool result = false; if (getImageSetMetadata(dataStoreID, imageSetID, "", // Empty string for version ID. fileName, clientConfiguration)) { try { std::string metadataGZip; { std::ifstream inFileStream(fileName.c_str(), std::ios::binary); if (!inFileStream) { throw std::runtime_error("Failed to open file " + fileName); } std::stringstream stringStream; stringStream << inFileStream.rdbuf(); metadataGZip = stringStream.str(); } std::string metadataJson = gzip::decompress(metadataGZip.data(), metadataGZip.size()); // Use JMESPath to extract the image set IDs. // https://jmespath.org/specification.html jsoncons::json doc = jsoncons::json::parse(metadataJson); std::string jmesPathExpression = "Study.Series.*.Instances[].*[]"; jsoncons::json instances = jsoncons::jmespath::search(doc, jmesPathExpression); for (auto &instance: instances.array_range()) { jmesPathExpression = "DICOM.RescaleSlope"; std::string rescaleSlope = jsoncons::jmespath::search(instance, jmesPathExpression).to_string(); jmesPathExpression = "DICOM.RescaleIntercept"; std::string rescaleIntercept = jsoncons::jmespath::search(instance, jmesPathExpression).to_string(); jmesPathExpression = "ImageFrames[][]"; jsoncons::json imageFramesJson = jsoncons::jmespath::search(instance, jmesPathExpression); for (auto &imageFrame: imageFramesJson.array_range()) { ImageFrameInfo imageFrameIDs; imageFrameIDs.mImageSetId = imageSetID; imageFrameIDs.mImageFrameId = imageFrame.find( "ID")->value().as_string(); imageFrameIDs.mRescaleIntercept = rescaleIntercept; imageFrameIDs.mRescaleSlope = rescaleSlope; imageFrameIDs.MinPixelValue = imageFrame.find( "MinPixelValue")->value().as_string(); imageFrameIDs.MaxPixelValue = imageFrame.find( "MaxPixelValue")->value().as_string(); jmesPathExpression = "max_by(PixelDataChecksumFromBaseToFullResolution, &Width).Checksum"; jsoncons::json checksumJson = jsoncons::jmespath::search(imageFrame, jmesPathExpression); imageFrameIDs.mFullResolutionChecksum = checksumJson.as_integer<uint32_t>(); imageFrames.emplace_back(imageFrameIDs); } } result = true; } catch (const std::exception &e) { std::cerr << "getImageFramesForImageSet failed because " << e.what() << std::endl; } } return result; } //! Routine which gets a HealthImaging image set's metadata. /*! \param dataStoreID: The HealthImaging data store ID. \param imageSetID: The HealthImaging image set ID. \param versionID: The HealthImaging image set version ID, ignored if empty. \param outputFilePath: The path where the metadata will be stored as gzipped json. \param clientConfig: Aws client configuration. \\return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::getImageSetMetadata(const Aws::String &dataStoreID, const Aws::String &imageSetID, const Aws::String &versionID, const Aws::String &outputFilePath, const Aws::Client::ClientConfiguration &clientConfig) { Aws::MedicalImaging::Model::GetImageSetMetadataRequest request; request.SetDatastoreId(dataStoreID); request.SetImageSetId(imageSetID); if (!versionID.empty()) { request.SetVersionId(versionID); } Aws::MedicalImaging::MedicalImagingClient client(clientConfig); Aws::MedicalImaging::Model::GetImageSetMetadataOutcome outcome = client.GetImageSetMetadata( request); if (outcome.IsSuccess()) { std::ofstream file(outputFilePath, std::ios::binary); auto &metadata = outcome.GetResult().GetImageSetMetadataBlob(); file << metadata.rdbuf(); } else { std::cerr << "Failed to get image set metadata: " << outcome.GetError().GetMessage() << std::endl; } return outcome.IsSuccess(); }

Baixe, decodifique e verifique os quadros de imagem.

bool AwsDoc::Medical_Imaging::downloadDecodeAndCheckImageFrames( const Aws::String &dataStoreID, const Aws::Vector<ImageFrameInfo> &imageFrames, const Aws::String &outDirectory, const Aws::Client::ClientConfiguration &clientConfiguration) { Aws::Client::ClientConfiguration clientConfiguration1(clientConfiguration); clientConfiguration1.executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>( "executor", 25); Aws::MedicalImaging::MedicalImagingClient medicalImagingClient( clientConfiguration1); Aws::Utils::Threading::Semaphore semaphore(0, 1); std::atomic<size_t> count(imageFrames.size()); bool result = true; for (auto &imageFrame: imageFrames) { Aws::MedicalImaging::Model::GetImageFrameRequest getImageFrameRequest; getImageFrameRequest.SetDatastoreId(dataStoreID); getImageFrameRequest.SetImageSetId(imageFrame.mImageSetId); Aws::MedicalImaging::Model::ImageFrameInformation imageFrameInformation; imageFrameInformation.SetImageFrameId(imageFrame.mImageFrameId); getImageFrameRequest.SetImageFrameInformation(imageFrameInformation); auto getImageFrameAsyncLambda = [&semaphore, &result, &count, imageFrame, outDirectory]( const Aws::MedicalImaging::MedicalImagingClient *client, const Aws::MedicalImaging::Model::GetImageFrameRequest &request, Aws::MedicalImaging::Model::GetImageFrameOutcome outcome, const std::shared_ptr<const Aws::Client::AsyncCallerContext> &context) { if (!handleGetImageFrameResult(outcome, outDirectory, imageFrame)) { std::cerr << "Failed to download and convert image frame: " << imageFrame.mImageFrameId << " from image set: " << imageFrame.mImageSetId << std::endl; result = false; } count--; if (count <= 0) { semaphore.ReleaseAll(); } }; // End of 'getImageFrameAsyncLambda' lambda. medicalImagingClient.GetImageFrameAsync(getImageFrameRequest, getImageFrameAsyncLambda); } if (count > 0) { semaphore.WaitOne(); } if (result) { std::cout << imageFrames.size() << " image files were downloaded." << std::endl; } return result; } bool AwsDoc::Medical_Imaging::decodeJPHFileAndValidateWithChecksum( const Aws::String &jphFile, uint32_t crc32Checksum) { opj_image_t *outputImage = jphImageToOpjBitmap(jphFile); if (!outputImage) { return false; } bool result = true; if (!verifyChecksumForImage(outputImage, crc32Checksum)) { std::cerr << "The checksum for the image does not match the expected value." << std::endl; std::cerr << "File :" << jphFile << std::endl; result = false; } opj_image_destroy(outputImage); return result; } opj_image * AwsDoc::Medical_Imaging::jphImageToOpjBitmap(const Aws::String &jphFile) { opj_stream_t *inFileStream = nullptr; opj_codec_t *decompressorCodec = nullptr; opj_image_t *outputImage = nullptr; try { std::shared_ptr<opj_dparameters> decodeParameters = std::make_shared<opj_dparameters>(); memset(decodeParameters.get(), 0, sizeof(opj_dparameters)); opj_set_default_decoder_parameters(decodeParameters.get()); decodeParameters->decod_format = 1; // JP2 image format. decodeParameters->cod_format = 2; // BMP image format. std::strncpy(decodeParameters->infile, jphFile.c_str(), OPJ_PATH_LEN); inFileStream = opj_stream_create_default_file_stream( decodeParameters->infile, true); if (!inFileStream) { throw std::runtime_error( "Unable to create input file stream for file '" + jphFile + "'."); } decompressorCodec = opj_create_decompress(OPJ_CODEC_JP2); if (!decompressorCodec) { throw std::runtime_error("Failed to create decompression codec."); } int decodeMessageLevel = 1; if (!setupCodecLogging(decompressorCodec, &decodeMessageLevel)) { std::cerr << "Failed to setup codec logging." << std::endl; } if (!opj_setup_decoder(decompressorCodec, decodeParameters.get())) { throw std::runtime_error("Failed to setup decompression codec."); } if (!opj_codec_set_threads(decompressorCodec, 4)) { throw std::runtime_error("Failed to set decompression codec threads."); } if (!opj_read_header(inFileStream, decompressorCodec, &outputImage)) { throw std::runtime_error("Failed to read header."); } if (!opj_decode(decompressorCodec, inFileStream, outputImage)) { throw std::runtime_error("Failed to decode."); } if (DEBUGGING) { std::cout << "image width : " << outputImage->x1 - outputImage->x0 << std::endl; std::cout << "image height : " << outputImage->y1 - outputImage->y0 << std::endl; std::cout << "number of channels: " << outputImage->numcomps << std::endl; std::cout << "colorspace : " << outputImage->color_space << std::endl; } } catch (const std::exception &e) { std::cerr << e.what() << std::endl; if (outputImage) { opj_image_destroy(outputImage); outputImage = nullptr; } } if (inFileStream) { opj_stream_destroy(inFileStream); } if (decompressorCodec) { opj_destroy_codec(decompressorCodec); } return outputImage; } //! Template function which converts a planar image bitmap to an interleaved image bitmap and //! then verifies the checksum of the bitmap. /*! * @param image: The OpenJPEG image struct. * @param crc32Checksum: The CRC32 checksum. * @return bool: Function succeeded. */ template<class myType> bool verifyChecksumForImageForType(opj_image_t *image, uint32_t crc32Checksum) { uint32_t width = image->x1 - image->x0; uint32_t height = image->y1 - image->y0; uint32_t numOfChannels = image->numcomps; // Buffer for interleaved bitmap. std::vector<myType> buffer(width * height * numOfChannels); // Convert planar bitmap to interleaved bitmap. for (uint32_t channel = 0; channel < numOfChannels; channel++) { for (uint32_t row = 0; row < height; row++) { uint32_t fromRowStart = row / image->comps[channel].dy * width / image->comps[channel].dx; uint32_t toIndex = (row * width) * numOfChannels + channel; for (uint32_t col = 0; col < width; col++) { uint32_t fromIndex = fromRowStart + col / image->comps[channel].dx; buffer[toIndex] = static_cast<myType>(image->comps[channel].data[fromIndex]); toIndex += numOfChannels; } } } // Verify checksum. boost::crc_32_type crc32; crc32.process_bytes(reinterpret_cast<char *>(buffer.data()), buffer.size() * sizeof(myType)); bool result = crc32.checksum() == crc32Checksum; if (!result) { std::cerr << "verifyChecksumForImage, checksum mismatch, expected - " << crc32Checksum << ", actual - " << crc32.checksum() << std::endl; } return result; } //! Routine which verifies the checksum of an OpenJPEG image struct. /*! * @param image: The OpenJPEG image struct. * @param crc32Checksum: The CRC32 checksum. * @return bool: Function succeeded. */ bool AwsDoc::Medical_Imaging::verifyChecksumForImage(opj_image_t *image, uint32_t crc32Checksum) { uint32_t channels = image->numcomps; bool result = false; if (0 < channels) { // Assume the precision is the same for all channels. uint32_t precision = image->comps[0].prec; bool signedData = image->comps[0].sgnd; uint32_t bytes = (precision + 7) / 8; if (signedData) { switch (bytes) { case 1 : result = verifyChecksumForImageForType<int8_t>(image, crc32Checksum); break; case 2 : result = verifyChecksumForImageForType<int16_t>(image, crc32Checksum); break; case 4 : result = verifyChecksumForImageForType<int32_t>(image, crc32Checksum); break; default: std::cerr << "verifyChecksumForImage, unsupported data type, signed bytes - " << bytes << std::endl; break; } } else { switch (bytes) { case 1 : result = verifyChecksumForImageForType<uint8_t>(image, crc32Checksum); break; case 2 : result = verifyChecksumForImageForType<uint16_t>(image, crc32Checksum); break; case 4 : result = verifyChecksumForImageForType<uint32_t>(image, crc32Checksum); break; default: std::cerr << "verifyChecksumForImage, unsupported data type, unsigned bytes - " << bytes << std::endl; break; } } if (!result) { std::cerr << "verifyChecksumForImage, error bytes " << bytes << " signed " << signedData << std::endl; } } else { std::cerr << "'verifyChecksumForImage', no channels in the image." << std::endl; } return result; }

Limpar recursos.

bool AwsDoc::Medical_Imaging::cleanup(const Aws::String &stackName, const Aws::String &dataStoreId, const Aws::Client::ClientConfiguration &clientConfiguration) { bool result = true; if (!stackName.empty() && askYesNoQuestion( "Would you like to delete the stack " + stackName + "? (y/n)")) { std::cout << "Deleting the image sets in the stack." << std::endl; result &= emptyDatastore(dataStoreId, clientConfiguration); printAsterisksLine(); std::cout << "Deleting the stack." << std::endl; result &= deleteStack(stackName, clientConfiguration); } return result; } bool AwsDoc::Medical_Imaging::emptyDatastore(const Aws::String &datastoreID, const Aws::Client::ClientConfiguration &clientConfiguration) { Aws::MedicalImaging::Model::SearchCriteria emptyCriteria; Aws::Vector<Aws::String> imageSetIDs; bool result = false; if (searchImageSets(datastoreID, emptyCriteria, imageSetIDs, clientConfiguration)) { result = true; for (auto &imageSetID: imageSetIDs) { result &= deleteImageSet(datastoreID, imageSetID, clientConfiguration); } } return result; }
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.