Skip to content

Commit

Permalink
WIP: meeting commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jadh4v committed Jun 28, 2024
1 parent 7309b67 commit 7ca1ce7
Show file tree
Hide file tree
Showing 29 changed files with 995 additions and 89 deletions.
2 changes: 1 addition & 1 deletion packages/dicom/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ set(CMAKE_CXX_STANDARD 20)

enable_testing()

add_subdirectory(gdcm)
#add_subdirectory(gdcm)
add_subdirectory(dcmtk)
11 changes: 8 additions & 3 deletions packages/dicom/dcmtk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)

list(APPEND DCMQI_INCLUDE_DIRS "${dcmqi_lib_SOURCE_DIR}/include" "${dcmqi_lib_SOURCE_DIR}/jsoncpp" "${dcmqi_lib_BINARY_DIR}/include")
include_directories(${DCMQI_INCLUDE_DIRS})
#include_directories("${dcmqi_lib_SOURCE_DIR}/jsoncpp")
#include_directories("${dcmqi_lib_BINARY_DIR}/include")

add_executable(structured-report-to-text structured-report-to-text.cxx)
target_link_libraries(structured-report-to-text PUBLIC ${ITK_LIBRARIES})
Expand All @@ -58,4 +56,11 @@ target_link_libraries(read-dicom-encapsulated-pdf PUBLIC ${ITK_LIBRARIES})
add_executable(read-segmentation read-segmentation.cxx)
target_link_libraries(read-segmentation PUBLIC ${ITK_LIBRARIES} dcmqi)

# add_test(NAME read-segmentation-help COMMAND read-segmentation --help)
add_executable(read-overlapping-segmentation read-overlapping-segmentation.cxx)
target_link_libraries(read-overlapping-segmentation PUBLIC ${ITK_LIBRARIES} dcmqi)

add_executable(write-segmentation write-segmentation.cxx)
target_link_libraries(write-segmentation PUBLIC ${ITK_LIBRARIES} dcmqi)

add_executable(write-overlapping-segmentation write-overlapping-segmentation.cxx)
target_link_libraries(write-overlapping-segmentation PUBLIC ${ITK_LIBRARIES} dcmqi)
127 changes: 127 additions & 0 deletions packages/dicom/dcmtk/read-overlapping-segmentation.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*=========================================================================
* Copyright NumFOCUS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/

// DCMQI includes
// #undef HAVE_SSTREAM // Avoid redefinition warning
#include "dcmqi/Dicom2ItkConverter.h"
#include "dcmqi/internal/VersionConfigure.h"

// DCMTK includes
#include "dcmtk/oflog/configrt.h"

// ITK includes
#include "itkComposeImageFilter.h"
#include "itkVectorImage.h"

// ITK-wasm includes
#include "itkPipeline.h"
#include "itkOutputImage.h"
#include "itkOutputTextStream.h"

typedef dcmqi::Helper helper;
constexpr unsigned int Dimension = 3;
using PixelType = short;
using ScalarImageType = itk::Image<PixelType, Dimension>;
using VectorImageType = itk::VectorImage<PixelType, Dimension>;

int runPipeline(
itk::wasm::Pipeline & pipeline,
const std::string & inputSEGFileName,
itk::wasm::OutputImage<VectorImageType>& outputImage,
itk::wasm::OutputTextStream& outputMetaInfoJSON,
const bool mergeSegments)
{
#if !defined(NDEBUG) || defined(_DEBUG)
// Display DCMTK debug, warning, and error logs in the console
dcmtk::log4cplus::BasicConfigurator::doConfigure();
#endif

if(helper::isUndefinedOrPathDoesNotExist(inputSEGFileName, "Input DICOM file"))
{
return EXIT_FAILURE;
}

DcmRLEDecoderRegistration::registerCodecs();

DcmFileFormat sliceFF;
// std::cout << "Loading DICOM SEG file " << inputSEGFileName << std::endl;
CHECK_COND(sliceFF.loadFile(inputSEGFileName.c_str()));
DcmDataset* dataset = sliceFF.getDataset();

try
{
dcmqi::Dicom2ItkConverter converter;
std::string metaInfo;
OFCondition result = converter.dcmSegmentation2itkimage(dataset, metaInfo, mergeSegments);
if (result.bad())
{
std::cerr << "ERROR: Failed to convert DICOM SEG to ITK image: " << result.text() << std::endl;
return EXIT_FAILURE;
}

using ImageToVectorImageFilterType = itk::ComposeImageFilter<ScalarImageType>;
auto imageToVectorImageFilter = ImageToVectorImageFilterType::New();
int inputNumber = 0;
for (auto itkImage = converter.begin(); itkImage != nullptr; itkImage = converter.next())
{
imageToVectorImageFilter->SetInput(inputNumber++, itkImage);
}
imageToVectorImageFilter->Update();
VectorImageType::Pointer vectorImage = imageToVectorImageFilter->GetOutput();
if (!vectorImage)
{
std::cerr << "Failed to create VectorImage." << std::endl;
return EXIT_FAILURE;
}

outputImage.Set(vectorImage);
outputMetaInfoJSON.Get() << metaInfo.c_str();
return EXIT_SUCCESS;
}
catch (int e)
{
std::cerr << "Fatal error encountered." << std::endl;
return EXIT_FAILURE;
}
return EXIT_FAILURE;
}

int main(int argc, char * argv[])
{
itk::wasm::Pipeline pipeline("read-overlapping-segmentation", "Read DICOM segmentation objects", argc, argv);

std::string dicomFileName;
pipeline.add_option("dicom-file", dicomFileName, "Input DICOM file")->required()->check(CLI::ExistingFile)->type_name("INPUT_BINARY_FILE");

itk::wasm::OutputImage<VectorImageType> outputImage;
pipeline.add_option("seg-image", outputImage, "dicom segmentation object as an image")->required()->type_name("OUTPUT_IMAGE");

itk::wasm::OutputTextStream outputMetaInfoJSON;
pipeline.add_option("meta-info", outputMetaInfoJSON, "Output overlay information")->type_name("OUTPUT_JSON");

bool mergeSegments{false};
pipeline.add_flag("--merge-segments", mergeSegments, "Merge segments into a single image");

ITK_WASM_PARSE(pipeline);

// Pipeline code goes here
runPipeline(pipeline, dicomFileName, outputImage, outputMetaInfoJSON, mergeSegments);

return EXIT_SUCCESS;
}

45 changes: 17 additions & 28 deletions packages/dicom/dcmtk/read-segmentation.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ typedef dcmqi::Helper helper;
constexpr unsigned int Dimension = 3;
using PixelType = short;
using ScalarImageType = itk::Image<PixelType, Dimension>;
using VectorImageType = itk::VectorImage<PixelType, Dimension>;

int runPipeline(
itk::wasm::Pipeline & pipeline,
const std::string & inputSEGFileName,
itk::wasm::OutputImage<VectorImageType> outputImage,
itk::wasm::OutputTextStream& outputMetaInfoJSON,
const bool mergeSegments)
itk::wasm::OutputImage<ScalarImageType>& outputImage,
itk::wasm::OutputTextStream& outputMetaInfoJSON)
{
#if !defined(NDEBUG) || defined(_DEBUG)
// Display DCMTK debug, warning, and error logs in the console
Expand All @@ -67,40 +65,34 @@ int runPipeline(
{
dcmqi::Dicom2ItkConverter converter;
std::string metaInfo;
OFCondition result = converter.dcmSegmentation2itkimage(dataset, metaInfo, mergeSegments);
OFCondition result = converter.dcmSegmentation2itkimage(dataset, metaInfo, /*mergeSegments*/true);
if (result.bad())
{
std::cerr << "ERROR: Failed to convert DICOM SEG to ITK image: " << result.text() << std::endl;
return EXIT_FAILURE;
}

using ImageToVectorImageFilterType = itk::ComposeImageFilter<ScalarImageType>;
auto imageToVectorImageFilter = ImageToVectorImageFilterType::New();
int inputNumber = 0;
// DCMQI doesn't provide an easy API to get the count, so we iterate over the outputs to count them.
int outputImageCount = 0;
for (auto itkImage = converter.begin(); itkImage != nullptr; itkImage = converter.next())
{
imageToVectorImageFilter->SetInput(inputNumber++, itkImage);
++outputImageCount;
}
imageToVectorImageFilter->Update();
std::cout << "SDJ total scalar images: " << inputNumber << std::endl;

VectorImageType::Pointer vectorImage = imageToVectorImageFilter->GetOutput();
itk::Index<3> idx0;
idx0.Fill(0);
std::cout << "vectorImage->GetPixel(0) = " << vectorImage->GetPixel(idx0) << std::endl;
if (vectorImage)
if (outputImageCount != 1)
{
outputImage.Set(vectorImage);
outputMetaInfoJSON.Get() << metaInfo.c_str();
return EXIT_SUCCESS;
std::cerr << "Output is not a single scalar image. Try using read-overlap-segmentation instead." << std::endl;
return EXIT_FAILURE;
}

outputImage.Set(converter.begin());
outputMetaInfoJSON.Get() << metaInfo.c_str();
return EXIT_SUCCESS;
}
catch (int e)
{
std::cerr << "Fatal error encountered." << std::endl;
return EXIT_FAILURE;
}

return EXIT_FAILURE;
}

Expand All @@ -111,19 +103,16 @@ int main(int argc, char * argv[])
std::string dicomFileName;
pipeline.add_option("dicom-file", dicomFileName, "Input DICOM file")->required()->check(CLI::ExistingFile)->type_name("INPUT_BINARY_FILE");

itk::wasm::OutputImage<VectorImageType> outputImage;
pipeline.add_option("outputImage", outputImage, "dicom segmentation object as an image")->required()->type_name("OUTPUT_IMAGE");
itk::wasm::OutputImage<ScalarImageType> outputImage;
pipeline.add_option("seg-image", outputImage, "dicom segmentation object as an image")->required()->type_name("OUTPUT_IMAGE");

itk::wasm::OutputTextStream outputMetaInfoJSON;
pipeline.add_option("output-meta-info-json", outputMetaInfoJSON, "Output overlay information")->type_name("OUTPUT_JSON");

bool mergeSegments{false};
pipeline.add_flag("--merge-segments", mergeSegments, "Merge segments into a single image");
pipeline.add_option("meta-info", outputMetaInfoJSON, "Output overlay information")->type_name("OUTPUT_JSON");

ITK_WASM_PARSE(pipeline);

// Pipeline code goes here
runPipeline(pipeline, dicomFileName, outputImage, outputMetaInfoJSON, mergeSegments);
runPipeline(pipeline, dicomFileName, outputImage, outputMetaInfoJSON);

return EXIT_SUCCESS;
}
Expand Down
Loading

0 comments on commit 7ca1ce7

Please sign in to comment.