Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modified compatible with the experimental DCMTK #492

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 51 additions & 10 deletions include/dcmqi/OverlapUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "dcmtk/ofstd/oftypes.h"
#include "dcmtk/ofstd/ofvector.h"
#include <set>
#include <map>

class DcmSegmentation;

Expand Down Expand Up @@ -91,7 +92,10 @@ class OverlapUtil

/// Lists frames for each segment where segment with index i is represented by the vector at index i,
/// and index 0 is unused. I.e. index i is segment number, value is vector of physical frame numbers.
typedef OFVector<OFVector<Uint32>> FramesForSegment;
typedef std::map<Uint32, std::set<Uint32>> FramesForSegment;

// Set of segments present on each frame.
typedef OFVector<std::set<Uint32>> SegmentsForFrame;

/// Implements comparision operator to be used for sorting of frame positions,
/// making the sorting order depend on the coordinate given in the constructor
Expand All @@ -116,7 +120,7 @@ class OverlapUtil

/// Matrix of N x N segment numbers, where N is the number of segments.
/// Value is 1 at x,y if x and y overlap, 0 if they don't overlap, and -1 if not initialized.
typedef OFVector<OFVector<Sint8>> OverlapMatrix;
typedef std::map<Uint32, std::map<Uint32, Sint8>> OverlapMatrix;

/// Group of non-overlapping segments (each represented by its segment number)
typedef OFVector<OFVector<Uint32>> SegmentGroups;
Expand All @@ -134,7 +138,7 @@ class OverlapUtil
, m_frameNumber(f)
{
}
/// Segment number as used in DICOM segmentation object (1-n)
/// Segment number as used in DICOM segmentation object
Uint16 m_segmentNumber;
/// Logical frame number (number of frame in DistinctFramePositions vector)
Uint16 m_frameNumber;
Expand Down Expand Up @@ -187,11 +191,18 @@ class OverlapUtil
OFCondition getSegmentsByPosition(SegmentsByPosition& result);

/** Get phyiscal frames for a specific segment by its segment number
* @param segmentNumber Segment number to get frames for (1..n)
* @param frames Resulting vector of physical frame numbers (first frame is frame 0)
* @param segmentNumber Segment number for which to get frames
* @param frames Resulting vector of physical frame numbers
* @return EC_Normal if successful, error otherwise
*/
OFCondition getFramesForSegment(const Uint32 segmentNumber, OFVector<Uint32>& frames);
OFCondition getFramesForSegment(const Uint32 segmentNumber, std::set<Uint32>& frames);

/** Get the all the segments present on a specified frame
* @param frameNumber The frame number for which to get segments
* @param segments Resulting set of segment numbers
* @return EC_Normal if successful, error otherwise
*/
OFCondition getSegmentsForFrame(const Uint32 frameNumber, std::set<Uint32>& segments);

/** Returns computed overlap matrix
* @param matrix Resulting overlap matrix
Expand Down Expand Up @@ -234,6 +245,22 @@ class OverlapUtil

protected:

/** Get the list of segments within a label map segmentation frame.
* Does not cache the result. To be used exclusively on a label map frame.
* @param frameNumber The frame number for which to get labels
* @param segments The resulting set of segments on the frame
* @return EC_Normal if successful, error otherwise
*/
OFCondition getSegmentsForLabelMapFrame(const Uint32 frameNumber, std::set<Uint32>& segments);

/** Get the segment number for a binary or fractional segmentation frame.
* Does not cache the result. To be used exclusively on a binary or fractional
* segmentation frame.
* @param frameNumber The frame number for which to get labels
* @param segment The resulting segments on the frame
* @return EC_Normal if successful, error otherwise
*/
OFCondition getSegmentForFrame(const Uint32 frameNumber, Uint32& segment);

/** Group physical frame positions into logical positions. This is done by sorting
* frames after *that* position coordinate that in its mean position difference is
Expand Down Expand Up @@ -277,6 +304,17 @@ class OverlapUtil
*/
OFCondition checkFramesOverlap(const Uint32& f1, const Uint32& f2, OFBool& overlap);

/** Checks to see if a segment on a first frame overlaps with a different segment
* on a second frame
* @param sf1 Segment number on frame number to check
* @param sf2 Segment number on frame number to check
* @param overlap Resulting overlap (overlaps if OFTrue, otherwise not)
* @return EC_Normal if successful, error otherwise
*/
OFCondition checkFramesOverlapLabelMap(const SegNumAndFrameNum& sf1,
const SegNumAndFrameNum& sf2,
OFBool& overlap);

/** Checks whether the given two frames overlap by using comparing their pixel data
* by bitwise "and". This is very efficient, however, only works and is called (right now),
* if row*cols % 8 = 0, so we can easily extract frames as binary bitsets without unpacking them.
Expand All @@ -292,8 +330,8 @@ class OverlapUtil
*/
OFCondition checkFramesOverlapBinary(const Uint32& f1,
const Uint32& f2,
const DcmIODTypes::Frame* f1_data,
const DcmIODTypes::Frame* f2_data,
DcmIODTypes::Frame<Uint8>* f1_data,
DcmIODTypes::Frame<Uint8>* f2_data,
const Uint16& rows,
const Uint16 cols,
OFBool& overlap);
Expand All @@ -312,8 +350,8 @@ class OverlapUtil
*/
OFCondition checkFramesOverlapUnpacked(const Uint32& f1,
const Uint32& f2,
const DcmIODTypes::Frame* f1_data,
const DcmIODTypes::Frame* f2_data,
DcmIODTypes::Frame<Uint8>* f1_data,
DcmIODTypes::Frame<Uint8>* f2_data,
const Uint16& rows,
const Uint16 cols,
OFBool& overlap);
Expand All @@ -340,6 +378,9 @@ class OverlapUtil
/// segment.
FramesForSegment m_framesForSegment;

/// Stores which segments are present on each frame.
SegmentsForFrame m_segmentsForFrame;

/// Logical frames, ie. physical frames with the same position are
/// grouped together to a logical frame. For every logical frame, we
/// store the related physical frame numbers. The logical frame number
Expand Down
26 changes: 15 additions & 11 deletions libsrc/Dicom2ItkConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,36 +124,38 @@ itk::SmartPointer<ShortImageType> Dicom2ItkConverter::nextResult()
{
// Iterate over frames for this segment, and copy the data into the ITK image.
// Afterwards, the ITK image will have the complete data belonging to that segment
OverlapUtil::FramesForSegment::value_type framesForSegment;
OverlapUtil::FramesForSegment::mapped_type framesForSegment;
m_overlapUtil.getFramesForSegment(*segNum, framesForSegment);
for (size_t frameIndex = 0; frameIndex < framesForSegment.size(); frameIndex++)
for (std::set<Uint32>::iterator it = framesForSegment.begin();
it != framesForSegment.end();
it++)
{
// Copy the data from the frame into the ITK image
ShortImageType::PointType frameOriginPoint;
ShortImageType::IndexType frameOriginIndex;
result = getITKImageOrigin(framesForSegment[frameIndex], frameOriginPoint);
result = getITKImageOrigin(*it, frameOriginPoint);
if (result.bad())
{
cerr << "ERROR: Failed to get origin for frame " << framesForSegment[frameIndex] << " of segment "
cerr << "ERROR: Failed to get origin for frame " << *it << " of segment "
<< *segNum << endl;
m_groupIterator = m_segmentGroups.end();
return nullptr;
}
if (!itkImage->TransformPhysicalPointToIndex(frameOriginPoint, frameOriginIndex))
{
cerr << "ERROR: Frame " << framesForSegment[frameIndex] << " origin " << frameOriginPoint
cerr << "ERROR: Frame " << *it << " origin " << frameOriginPoint
<< " is outside image geometry!" << frameOriginIndex << endl;
cerr << "Image size: " << itkImage->GetBufferedRegion().GetSize() << endl;
m_groupIterator = m_segmentGroups.end();
return nullptr;
}
// Handling differs depending on whether the segmentation is binary or fractional
// (we have to unpack binary frames before copying them into the ITK image)
const DcmIODTypes::Frame* rawFrame = m_segDoc->getFrame(framesForSegment[frameIndex]);
const DcmIODTypes::Frame* unpackedFrame = NULL;
DcmIODTypes::FrameBase* rawFrame = const_cast<DcmIODTypes::FrameBase*>(m_segDoc->getFrame(*it));
DcmIODTypes::FrameBase* unpackedFrame = NULL;
if (m_segDoc->getSegmentationType() == DcmSegTypes::ST_BINARY)
{
unpackedFrame = DcmSegUtils::unpackBinaryFrame(rawFrame,
unpackedFrame = DcmSegUtils::unpackBinaryFrame(dynamic_cast<const DcmIODTypes::Frame<Uint8>*>(rawFrame),
m_imageSize[1], // Rows
m_imageSize[0]); // Cols
}
Expand Down Expand Up @@ -212,15 +214,18 @@ itk::SmartPointer<ShortImageType> Dicom2ItkConverter::nextResult()
/* WIP */
}

bool labelMapSegmentation = m_segDoc->getSegmentationType() == DcmSegTypes::ST_LABELMAP;
for (unsigned row = 0; row < m_imageSize[1]; row++)
{
for (unsigned col = 0; col < m_imageSize[0]; col++)
{
ShortImageType::PixelType pixel;
Uint16 uint16Pixel;
unsigned bitCnt = row * m_imageSize[0] + col;
pixel = unpackedFrame->pixData[bitCnt];
unpackedFrame->getUint16AtIndex(uint16Pixel, bitCnt);
pixel = uint16Pixel;
ShortImageType::IndexType index;
if (pixel != 0)
if (labelMapSegmentation ? pixel == *segNum : pixel != 0)
{
index[0] = col;
index[1] = row;
Expand Down Expand Up @@ -371,7 +376,6 @@ OFCondition Dicom2ItkConverter::getNonOverlappingSegmentGroups(const bool mergeS
cout << "Will not merge segments: Splitting segments into " << segmentGroups.size() << " groups" << endl;
}
return result;
;
}

// -------------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions libsrc/Itk2DicomConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

// DCMTK includes
#include <dcmtk/dcmsr/codes/dcm.h>
#include <dcmtk/dcmfg/fgfracon.h>



Expand Down
Loading
Loading