diff --git a/include/dcmqi/OverlapUtil.h b/include/dcmqi/OverlapUtil.h index dcc37a59..a4b58edc 100644 --- a/include/dcmqi/OverlapUtil.h +++ b/include/dcmqi/OverlapUtil.h @@ -93,6 +93,9 @@ class OverlapUtil /// and index 0 is unused. I.e. index i is segment number, value is vector of physical frame numbers. typedef OFVector> FramesForSegment; + // Lists of segments for each frame. Used for Label Maps where each frame can have multiple segments. + typedef OFVector> SegmentsForFrame; + /// Implements comparision operator to be used for sorting of frame positions, /// making the sorting order depend on the coordinate given in the constructor struct ComparePositions @@ -193,6 +196,11 @@ class OverlapUtil */ OFCondition getFramesForSegment(const Uint32 segmentNumber, OFVector& frames); + /** + * TODO + */ + OFCondition getSegmentsForFrame(const Uint32 frameNumber, std::set& segments); + /** Returns computed overlap matrix * @param matrix Resulting overlap matrix * @return EC_Normal if successful, error otherwise @@ -277,6 +285,16 @@ class OverlapUtil */ OFCondition checkFramesOverlap(const Uint32& f1, const Uint32& f2, OFBool& overlap); + /** + * @param sf1 TODO + * @param sf1 TODO + * @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. @@ -340,6 +358,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 diff --git a/libsrc/OverlapUtil.cpp b/libsrc/OverlapUtil.cpp index 1fd94cc0..3ffb507b 100644 --- a/libsrc/OverlapUtil.cpp +++ b/libsrc/OverlapUtil.cpp @@ -49,6 +49,7 @@ OverlapUtil::OverlapUtil() : m_imageOrientation() , m_framePositions() , m_framesForSegment() + , m_segmentsForFrame() , m_logicalFramePositions() , m_segmentsByPosition() , m_segmentOverlapMatrix(0) @@ -126,35 +127,109 @@ OFCondition OverlapUtil::getFramesForSegment(const Uint32 segmentNumber, OFVecto // in the vector m_segmentsForFrame for (Uint32 f = 0; f < numFrames; f++) { - FGBase* group = NULL; - FGSegmentation* segFG = NULL; - group = fg.get(f, DcmFGTypes::EFG_SEGMENTATION); - segFG = OFstatic_cast(FGSegmentation*, group); - if (segFG) + OFCondition result; + std::set segments; + result = getSegmentsForFrame(f, segments); + if (result.good()) { - Uint16 segNum = 0; - OFCondition cond = segFG->getReferencedSegmentNumber(segNum); - if (cond.good() && segNum > 0) + if(segments.find(segmentNumber) != segments.end()) { + m_framesForSegment[segmentNumber - 1].push_back(f); // physical frame number for segment + } + } + else + { + DCMSEG_ERROR("getFramesForSegment(): Cannot get segments for frame " << f); + return EC_IllegalCall; + } + } + } + frames = m_framesForSegment[segmentNumber - 1]; + return EC_Normal; +} + +OFCondition OverlapUtil::getSegmentsForFrame(const Uint32 frameNumber, std::set& segments) +{ + if (!m_seg) + { + DCMSEG_ERROR("getSegmentsForFrame(): No segmentation object set"); + return EC_IllegalCall; + } + if (frameNumber > m_seg->getNumberOfFrames() - 1) + { + DCMSEG_ERROR("getSegmentsForFrame(): Frame number " << frameNumber << " is out of range"); + return EC_IllegalParameter; + } + if (m_segmentsForFrame.empty()) + { + FGInterface& fg = m_seg->getFunctionalGroups(); + size_t tempNum = m_seg->getNumberOfFrames(); + if (tempNum > 4294967295) + { + DCMSEG_ERROR("getSegmentsForFrame(): Number of frames " << tempNum << " exceeds maximum number of possible frames (2^32-1)"); + return EC_IllegalParameter; + } + Uint32 numFrames = static_cast(m_seg->getNumberOfFrames()); + for (Uint32 f = 0; f < numFrames; f++) { + m_segmentsForFrame.push_back(std::set()); + if (m_seg->getSegmentationType() == (DcmSegTypes::E_SegmentationType) 3) // LABELMAP + { + const DcmIODTypes::Frame* f_data = m_seg->getFrame(f); + Uint16 rows, cols; + rows = cols = 0; + DcmIODImage>* ip = static_cast>*>(m_seg); + ip->getImagePixel().getRows(rows); + ip->getImagePixel().getColumns(cols); + if (!f_data) { - m_framesForSegment[segNum - 1].push_back(f); // physical frame number for segment + DCMSEG_ERROR("getSegmentsForFrame(): Cannot access label map frame " << f); + return EC_IllegalCall; } - else if (segNum == 0) + + for (size_t n = 0; n < f_data->length; ++n) { - DCMSEG_WARN("getFramesForSegment(): Referenced Segment Number is 0 (not permitted) for frame #" - << f << ", ignoring"); - return EC_InvalidValue; + Uint8 segmentNumber = f_data->pixData[n]; + if ((segmentNumber == 0) || (segmentNumber > m_seg->getNumberOfSegments())) + { + DCMSEG_ERROR("getSegmentsForFrame(): Segment number " << segmentNumber << " is out of range"); + return EC_IllegalParameter; + } + m_segmentsForFrame[f].insert(segmentNumber); } - else + return EC_Normal; + } + else + { + FGBase* group = NULL; + FGSegmentation* segFG = NULL; + group = fg.get(f, DcmFGTypes::EFG_SEGMENTATION); + segFG = OFstatic_cast(FGSegmentation*, group); + if (segFG) { - DCMSEG_ERROR( - "getFramesForSegment(): Referenced Segment Number not found (not permitted) for frame #" - << f << ", cannot add segment"); - return EC_TagNotFound; + Uint16 segNum = 0; + OFCondition cond = segFG->getReferencedSegmentNumber(segNum); + if (cond.good() && segNum > 0) + { + m_segmentsForFrame[f].insert(segNum); // physical frame number for segment + } + else if (segNum == 0) + { + DCMSEG_WARN("getSegmentsForFrame(): Referenced Segment Number is 0 (not permitted) for frame #" + << f << ", ignoring"); + return EC_InvalidValue; + } + else + { + DCMSEG_ERROR( + "getSegmentsForFrame(): Referenced Segment Number not found (not permitted) for frame #" + << f << ", cannot add segment"); + return EC_TagNotFound; + } } } } } - frames = m_framesForSegment[segmentNumber - 1]; + + segments = m_segmentsForFrame[frameNumber]; return EC_Normal; } @@ -296,53 +371,25 @@ OFCondition OverlapUtil::getSegmentsByPosition(SegmentsByPosition& result) m_segmentsByPosition.resize(m_logicalFramePositions.size()); for (size_t l = 0; l < m_logicalFramePositions.size(); ++l) { - OFVector segments; for (size_t f = 0; f < m_logicalFramePositions[l].size(); ++f) { + std::set segmentsInFrame; Uint32 frameNumber = m_logicalFramePositions[l][f]; - OFVector segs; - FGBase* group = NULL; - FGSegmentation* segFG = NULL; - group = m_seg->getFunctionalGroups().get(frameNumber, DcmFGTypes::EFG_SEGMENTATION); - segFG = OFstatic_cast(FGSegmentation*, group); - if (segFG) + if (getSegmentsForFrame(frameNumber, segmentsInFrame).good()) { - Uint16 segNum = 0; - cond = segFG->getReferencedSegmentNumber(segNum); - if (cond.good() && segNum > 0 && (segNum <= numSegments)) - { - m_segmentsByPosition[l].insert(SegNumAndFrameNum(segNum, frameNumber)); - } - else if (segNum == 0) - { - DCMSEG_ERROR( - "getSegmentsByPosition(): Referenced Segment Number is 0 (not permitted), cannot add segment"); - cond = EC_InvalidValue; - break; - } - else if (segNum > numSegments) + for (std::set::iterator it = segmentsInFrame.begin(); + it != segmentsInFrame.end(); + ++it) { - DCMSEG_ERROR("getSegmentsByPosition(): Found Referenced Segment Number " - << segNum << " but only " << numSegments - << " segments are present, cannot add segment"); - DCMSEG_ERROR( - "getSegmentsByPosition(): Segments are not numbered consecutively, cannot add segment"); - cond = EC_InvalidValue; - break; + m_segmentsByPosition[l].insert(SegNumAndFrameNum(*it, frameNumber)); } else { - DCMSEG_ERROR("getSegmentsByPosition(): Referenced Segment Number not found (not permitted) , " - "cannot add segment"); - cond = EC_TagNotFound; - break; + DCMSEG_ERROR("getSegmentsByPosition(): Cannot get segments for frame " << frameNumber); + return EC_IllegalCall; } } } - if (cond.bad()) - { - break; - } } // print segments per logical frame if debug log level is enabled if (cond.good() && DCM_dcmsegLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) @@ -408,7 +455,7 @@ OFCondition OverlapUtil::getNonOverlappingSegments(SegmentGroups& segmentGroups) // Go through all segments and check if they overlap with any of the already // grouped segments. If not, add them to the same group. If yes, create a new group // and add them there. - m_nonOverlappingSegments.push_back(OFVector()); + m_nonOverlappingSegments.push_back(push_back); for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i) { // Loop over all groups and check whether the current segment overlaps with any of them @@ -564,7 +611,14 @@ OFCondition OverlapUtil::buildOverlapMatrix() // Compare pixels of the frames referenced by each segments. // If they overlap, mark as overlapping OFBool overlap = OFFalse; - checkFramesOverlap(it->m_frameNumber, it2->m_frameNumber, overlap); + if (m_seg->getSegmentationType() == (DcmSegTypes::E_SegmentationType) 3) // LABELMAP + { + checkFramesOverlapLabelMap(*it, *it2, overlap); + } + else + { + checkFramesOverlap(it->m_frameNumber, it2->m_frameNumber, overlap); + } // Enter result into overlap matrix m_segmentOverlapMatrix[(*it).m_segmentNumber - 1][(*it2).m_segmentNumber - 1] = overlap ? 1 : 0; @@ -595,6 +649,57 @@ OFCondition OverlapUtil::buildOverlapMatrix() return EC_Normal; } +OFCondition OverlapUtil::checkFramesOverlapLabelMap(const SegNumAndFrameNum& sf1, + const SegNumAndFrameNum& sf2, + OFBool& overlap) +{ + if (sf1.m_frameNumber == sf2.m_frameNumber && sf1.m_segmentNumber == sf2.m_segmentNumber) + { + // The same frame and segment should not be considered overlapping at all + overlap = OFFalse; + return EC_Normal; + } + + overlap = OFFalse; + const Uint32& f1 = sf1.m_frameNumber; + const Uint32& f2 = sf2.m_frameNumber; + OFCondition result; + const DcmIODTypes::Frame* f1_data = m_seg->getFrame(sf1.m_frameNumber); + const DcmIODTypes::Frame* f2_data = m_seg->getFrame(sf2.m_frameNumber); + Uint16 rows, cols; + rows = cols = 0; + DcmIODImage>* ip = static_cast>*>(m_seg); + ip->getImagePixel().getRows(rows); + ip->getImagePixel().getColumns(cols); + + DCMSEG_DEBUG("checkFramesOverlapLabelMap(): Comparing frame " << f1 << ", segment " << sf1.m_segmentNumber << ", and frame " + << f2 << ", segment " << sf2.m_segmentNumber + << ", for overlap"); + if (!f1_data || !f2_data) + { + DCMSEG_ERROR("checkFramesOverlapLabelMap(): Cannot access label map frames " << f1 << " and " << f2 << " for comparison"); + return EC_IllegalCall; + } + if (f1_data->length != f2_data->length) + { + DCMSEG_ERROR("checkFramesOverlapLabelMap(): Frames " << f1 << " and " << f2 + << " have different length, cannot compare"); + return EC_IllegalCall; + } + + for (size_t n = 0; n < f1_data->length; ++n) + { + if (f1_data->pixData[n] == sf1.m_segmentNumber && f2_data->pixData[n] == sf2.m_segmentNumber) + { + DCMSEG_DEBUG("checkFramesOverlapLabelMap(): Frame " << f1 << ", segment " << sf1.m_segmentNumber << ", and frame " + << f2 << ", segment " << sf2.m_segmentNumber << ", do overlap at index " << n); + overlap = OFTrue; + break; + } + } + return EC_Normal; +} + OFCondition OverlapUtil::checkFramesOverlap(const Uint32& f1, const Uint32& f2, OFBool& overlap) { if (f1 == f2) @@ -608,7 +713,7 @@ OFCondition OverlapUtil::checkFramesOverlap(const Uint32& f1, const Uint32& f2, const DcmIODTypes::Frame* f1_data = m_seg->getFrame(f1); const DcmIODTypes::Frame* f2_data = m_seg->getFrame(f2); Uint16 rows, cols; - rows = cols = 0; + rows = cols = 0; DcmIODImage>* ip = static_cast>*>(m_seg); ip->getImagePixel().getRows(rows); ip->getImagePixel().getColumns(cols);