diff --git a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp index 12bed51bf8..3f5ec28f5c 100644 --- a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp +++ b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.cpp @@ -1,504 +1,358 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCorrectorAlgorithm.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkImageDataItem.h" #include "mitkContourUtils.h" #include "mitkLegacyAdaptors.h" #include + +#include "itkImageDuplicator.h" +#include "itkImageRegionIterator.h" + + mitk::CorrectorAlgorithm::CorrectorAlgorithm() :ImageToImageFilter() { } mitk::CorrectorAlgorithm::~CorrectorAlgorithm() { } void mitk::CorrectorAlgorithm::GenerateData() { Image::Pointer inputImage = const_cast(ImageToImageFilter::GetInput(0)); if (inputImage.IsNull() || inputImage->GetDimension() != 2) { itkExceptionMacro("CorrectorAlgorithm needs a 2D image as input."); } if (m_Contour.IsNull()) { itkExceptionMacro("CorrectorAlgorithm needs a Contour object as input."); } // copy the input (since m_WorkingImage will be changed later) m_WorkingImage = inputImage; TimeGeometry::Pointer originalGeometry = NULL; if (inputImage->GetTimeGeometry() ) { originalGeometry = inputImage->GetTimeGeometry()->Clone(); m_WorkingImage->SetTimeGeometry( originalGeometry ); } else { itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy."); } Image::Pointer temporarySlice; // Convert to ipMITKSegmentationTYPE (because TobiasHeimannCorrectionAlgorithm relys on that data type) { itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingImage, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); //correctPixelTypeImage->SetDirection(imageDirection); temporarySlice = this->GetOutput(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); + m_FillColor = 1; + m_EraseColor = 0; + ImprovedHeimannCorrectionAlgorithm(correctPixelTypeImage); CastToMitkImage( correctPixelTypeImage, temporarySlice ); } - - - mitkIpPicDescriptor* temporarySlicePic = mitkIpPicNew(); - CastToIpPicDescriptor( temporarySlice, temporarySlicePic ); - TobiasHeimannCorrectionAlgorithm( temporarySlicePic ); - temporarySlice->SetTimeGeometry(originalGeometry); - } -void mitk::CorrectorAlgorithm::TobiasHeimannCorrectionAlgorithm(mitkIpPicDescriptor* pic) +void mitk::CorrectorAlgorithm::ImprovedHeimannCorrectionAlgorithm(itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic) { /*! Some documentation (not by the original author) TobiasHeimannCorrectionAlgorithm will be called, when the user has finished drawing a freehand line. There should be different results, depending on the line's properties: 1. Without any prior segmentation, the start point and the end point of the drawn line will be connected to a contour and the area enclosed by the contour will be marked as segmentation. 2. When the whole line is inside a segmentation, start and end point will be connected to a contour and the area of this contour will be subtracted from the segmentation. 3. When the line starts inside a segmentation and ends outside with only a single transition from segmentation to no-segmentation, nothing will happen. 4. When there are multiple transitions between inside-segmentation and outside-segmentation, the line will be divided in so called segments. Each segment is either fully inside or fully outside a segmentation. When it is inside a segmentation, its enclosed area will be subtracted from the segmentation. When the segment is outside a segmentation, its enclosed area it will be added to the segmentation. The algorithm is described in full length in Tobias Heimann's diploma thesis (MBI Technical Report 145, p. 37 - 40). */ - int oaSize = 1000000; // if we need a fixed number, then let it be big - int* _ofsArray = new int[ oaSize ]; - for (int i=0; i segData; - segData.reserve( 16 ); - - ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice( m_WorkingImage, m_Contour, true, false ); - if (projectedContour.IsNull()) + if (projectedContour.IsNull() || + projectedContour->GetNumberOfVertices() < 2 ) { - delete[] _ofsArray; return; } - if (projectedContour->GetNumberOfVertices() < 2) - { - delete[] _ofsArray; - return; - } - - // convert the projected contour into a ipSegmentation format - mitkIpInt4_t* _points = new mitkIpInt4_t[2 * projectedContour->GetNumberOfVertices()]; - ContourModel::VertexIterator iter = projectedContour->Begin(); - ContourModel::VertexIterator end = projectedContour->End(); - unsigned int index(0); - - while( iter != end) - { - _points[ 2 * index + 0 ] = static_cast( (*iter)->Coordinates[0] + 0.5 ); - _points[ 2 * index + 1 ] = static_cast( (*iter)->Coordinates[1] + 0.5 ); - ++index; - iter++; - } - - // store ofsets of the drawn line in array - int _ofsNum = 0; - unsigned int num = projectedContour->GetNumberOfVertices(); - int lastOfs = -1; - for (unsigned int i=0; i=pic->n[0]) x = pic->n[0]-0.5; - if (y<0) y=0.5; - else if (y>=pic->n[1]) y = pic->n[1]-0.5; - // ok, now store safe ofs - int ofs = (int)(x) + pic->n[0]*((int)(y)); - x += dx; - y += dy; - if (ofs != lastOfs) - { - _ofsArray[_ofsNum++] = ofs; - lastOfs = ofs; - } - } - } - - if (_ofsNum == 0) - { - // contour was completely outside the binary image - delete[] _ofsArray; - delete[] _points; + // Read the first point of the contour + ContourModel::VertexIterator contourIter = projectedContour->Begin(); + if (contourIter == projectedContour->End()) return; - } + itk::Index<2> previousIndex; + previousIndex[0] = (*contourIter)->Coordinates[0]; + previousIndex[1] = (*contourIter)->Coordinates[1]; + ++contourIter; - ipMITKSegmentationTYPE* picdata = static_cast(pic->data); + int currentColor = ( pic->GetPixel(previousIndex) == m_FillColor); + TSegData currentSegment; + int countOfSegments = 1; - // divide line in logical segments: - int numSegments = 0; - ipMITKSegmentationTYPE state = *(picdata + _ofsArray[0]); - int ofsP = 1; - int modifyStart, modifyEnd; // start of first and end of last segment - bool nextSegment; - segData.clear(); - do - { - nextSegment = false; - while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++; - if (ofsP<_ofsNum) - { - int lineStart = ofsP-1; - if (numSegments==0) modifyStart = ofsP; - state = *(picdata + _ofsArray[ofsP]); - while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++; - if (ofsP<_ofsNum) - { - int lineEnd = ofsP; - modifyEnd = lineEnd; - nextSegment = true; - // now we've got a valid segment from lineStart to lineEnd - TSegData thisSegData; - thisSegData.lineStart = lineStart; - thisSegData.lineEnd = lineEnd; - thisSegData.modified = modifySegment( lineStart, lineEnd, state, pic, _ofsArray ); - segData.push_back( thisSegData ); - numSegments++; - } - } - } while (nextSegment); - for (int segNr=0; segNr < numSegments; segNr++) + bool firstSegment = true; + ContourModel::VertexIterator contourEnd = projectedContour->End(); + for (; contourIter != contourEnd; ++contourIter) { - // draw line if modified: - if ( segData[segNr].modified ) + // Get current point + itk::Index<2> currentIndex; + currentIndex[0] = (*contourIter)->Coordinates[0] +0.5; + currentIndex[1] = (*contourIter)->Coordinates[1] +0.5; + + // Calculate length and slope + double slopeX = currentIndex[0] - previousIndex[0]; + double slopeY = currentIndex[1] - previousIndex[1]; + double length = std::sqrt(slopeX * slopeX + slopeY * slopeY); + double deltaX = slopeX / length; + double deltaY = slopeY / length; + + for (double i = 0; i < length; i+=1) { - for (int i=segData[segNr].lineStart+1; i temporaryIndex; + temporaryIndex[0] = previousIndex[0] + deltaX * i; + temporaryIndex[1] = previousIndex[1] + deltaY * i; + if ( ! pic->GetLargestPossibleRegion().IsInside(temporaryIndex)) + continue; + if ( (pic->GetPixel(temporaryIndex) == m_FillColor) != currentColor) { - *(picdata + _ofsArray[i]) = 1; + currentSegment.points.push_back(temporaryIndex); + if ( ! firstSegment) + { + ModifySegment( currentSegment, pic); + } else + { + firstSegment = false; + } + currentSegment = TSegData(); + ++countOfSegments; + currentColor = (pic->GetPixel(temporaryIndex) == m_FillColor); } + currentSegment.points.push_back(temporaryIndex); } + previousIndex = currentIndex; } - if (numSegments == 0) + // Check if only on Segment + if (firstSegment) { - if (num <= 1) - { // only a single pixel. _ofsArray[_ofsNum-1] in else statement would crash, so don't do anything - // no movement: delete operation + itk::Index<2> firstPoint = currentSegment.points.front(); + itk::Index<2> lastPoint = currentSegment.points.back(); - // This behaviour would probably confuse users when they use the correction - // tool to change a segmentation and it deletes much more than selected + double slopeX = firstPoint[0] - lastPoint[0]; + double slopeY = firstPoint[1] - lastPoint[1]; + double length = std::sqrt(slopeX * slopeX + slopeY * slopeY); + double deltaX = slopeX / length; + double deltaY = slopeY / length; - // if (state == 1) ipMITKSegmentationReplaceRegion4N( pic, _ofsArray[0], 0 ); - } - else if ( *(picdata + _ofsArray[_ofsNum-1]) == *(picdata + _ofsArray[0])) + for (double i = 0; i < length; i+=1) { - // start point and end point both inside or both outside any segmentation - // normal paint operation - mitkIpInt4_t* p = new mitkIpInt4_t[2 * num]; - for (unsigned int i = 0; i < num; i++) - { - p[2 * i] = (mitkIpInt4_t) _points [2 * i]; - p[2 * i + 1] = (mitkIpInt4_t) _points [2 * i + 1]; - } - - if (state == 0) ipMITKSegmentationCombineRegion (pic, p, num, 0, IPSEGMENTATION_OR, 1); - else ipMITKSegmentationCombineRegion (pic, p, num, 0, IPSEGMENTATION_AND, 0); - - delete[] p; + itk::Index<2> temporaryIndex; + temporaryIndex[0] = lastPoint[0] + deltaX * i; + temporaryIndex[1] = lastPoint[1] + deltaY * i; + currentSegment.points.push_back(temporaryIndex); } + ModifySegment(currentSegment, pic); + // Fill this segment as usual } +} - int numberOfContourPoints( 0 ); - int oneContourOffset( 0 ); - int newBufferSize( 0 ); +static void ColorSegment(const mitk::CorrectorAlgorithm::TSegData &segment, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic, int fillColor, int eraseColor) +{ + int colorMode = (pic->GetPixel(segment.points[0]) == fillColor); + int color = 0; + if (colorMode) + color = eraseColor; + else + color = fillColor; - int imageSize = pic->n[0]*pic->n[1]; - for (oneContourOffset = 0; oneContourOffset < imageSize; oneContourOffset++) - if ( ((ipMITKSegmentationTYPE*) pic->data)[oneContourOffset]> 0) break; + std::vector< itk::Index<2> >::const_iterator indexIterator; + std::vector< itk::Index<2> >::const_iterator indexEnd; - float* contourPoints = ipMITKSegmentationGetContour8N( pic, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc + indexIterator = segment.points.begin(); + indexEnd = segment.points.end(); - if (contourPoints) + for (; indexIterator != indexEnd; ++indexIterator) { - - // copy point from float* to mitk::ContourModel - ContourModel::Pointer contourInImageIndexCoordinates = mitk::ContourModel::New(); - contourInImageIndexCoordinates->Initialize(); - Point3D newPoint; - for (int index = 0; index < numberOfContourPoints; ++index) - { - newPoint[0] = contourPoints[ 2 * index + 0 ]; - newPoint[1] = contourPoints[ 2 * index + 1]; - newPoint[2] = 0; - - contourInImageIndexCoordinates->AddVertex( newPoint ); - } - - free(contourPoints); - - mitk::ContourModelUtils::FillContourInSlice( contourInImageIndexCoordinates, m_WorkingImage ); + pic->SetPixel(*indexIterator, color); } - - delete[] _ofsArray; - delete[] _points; } -bool mitk::CorrectorAlgorithm::modifySegment( int lineStart, int lineEnd, ipMITKSegmentationTYPE state, mitkIpPicDescriptor *pic, int* _ofsArray ) +static itk::Index<2> GetFirstPoint(const mitk::CorrectorAlgorithm::TSegData &segment, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic, int fillColor) { - // offsets for pixels right, top, left, bottom - int nbDelta4[4]; - nbDelta4[0]=1; nbDelta4[1]=pic->n[0]; nbDelta4[1]*=-1; // necessary because of unsigned declaration of pic->n - nbDelta4[2]=-1; nbDelta4[3]=pic->n[0]; + int colorMode = (pic->GetPixel(segment.points[0]) == fillColor); - // offsets for pixels right, top-right, top, top-left left, bottom-left, bottom, bottom-right - int nbDelta8[8]; - nbDelta8[0] = 1; nbDelta8[1] = nbDelta4[1]+1; nbDelta8[2] = nbDelta4[1]; nbDelta8[3] = nbDelta4[1]-1; - nbDelta8[4] = -1; nbDelta8[5] = nbDelta4[3]-1; nbDelta8[6] = nbDelta4[3]; nbDelta8[7] = nbDelta4[3]+1; + std::vector< itk::Index<2> >::const_iterator indexIterator; + std::vector< itk::Index<2> >::const_iterator indexEnd; - ipMITKSegmentationTYPE* picdata = static_cast(pic->data); - - ipMITKSegmentationTYPE saveStart = *(picdata + _ofsArray[lineStart]); - ipMITKSegmentationTYPE saveEnd = *(picdata + _ofsArray[lineEnd]); - ipMITKSegmentationTYPE newState = ((!state)&1) + 2; // probably equal to: ipMITKSegmentationTYPE newState = 3 - state; - - // make two copies of pic: - mitkIpPicDescriptor *seg1 = mitkIpPicClone( pic ); - mitkIpPicDescriptor *seg2 = mitkIpPicClone( pic ); - - int i; - - // mark line in original - for (i=lineStart; i<=lineEnd; i++) { - *(picdata + _ofsArray[i]) = 3; - } + indexIterator = segment.points.begin(); + indexEnd = segment.points.end(); - // mark the first side in copy 1: - bool firstPix = true; - bool modified; - int line = pic->n[0]; // #pixels in line - int maxOfs = (int)(line * pic->n[1]); // #pixels in slice - - for (i=lineStart+1; i= maxOfs // below last line - ) continue; - ipMITKSegmentationTYPE nbVal = *(picdata + nbOfs); - ipMITKSegmentationTYPE destVal = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs); - if (nbVal!=3 && destVal!=newState) { // get only neigbhours that are not part of the line itself - if (firstPix) { - *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState; // this one is used to mark the side! - firstPix = false; - modified = true; - } - else { - int tnb = 0; - while ( tnb < 4 - && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs) - && *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs + nbDelta4[tnb]) != newState - ) - tnb++; - - if (tnb < 4 && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs) ) { - *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState; // we've got a buddy close - modified = true; - } - } + for (; indexIterator != indexEnd; ++indexIterator) + { + itk::Index<2> index; + for (int xOffset = -1 ; xOffset < 2; ++xOffset) + { + for (int yOffset = -1 ; yOffset < 2; ++yOffset) + { + index[0] = (*indexIterator)[0] - xOffset; + index[1] = (*indexIterator)[1] - yOffset; + if ((pic->GetPixel(index) == fillColor) != colorMode) + { + return index; } } - } while (modified); - } - - // mark the other side in copy 2: - for (i=lineStart+1; i= maxOfs // below last line - ) continue; - ipMITKSegmentationTYPE lineVal = *(picdata + nbOfs); - ipMITKSegmentationTYPE side1Val = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs); - if (lineVal != 3 && side1Val != newState) { - *(((ipMITKSegmentationTYPE*)seg2->data) + nbOfs) = newState; - } - } - } - - // take care of line ends for multiple segments: - *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineStart]) = newState; - *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineEnd]) = newState; - *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineStart]) = newState; - *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineEnd]) = newState; - - - // replace regions: - newState = (!state)&1; - int sizeRegion1 = 0, sizeRegion2 = 0; - for (i=lineStart+1; idata) + _ofsArray[i]) != newState) { - sizeRegion1 += ipMITKSegmentationReplaceRegion4N( seg1, _ofsArray[i], newState ); - } - if (*(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[i]) != newState) { - sizeRegion2 += ipMITKSegmentationReplaceRegion4N( seg2, _ofsArray[i], newState ); } } + throw(std::exception("No initial starting point found")); +} - // combine image: - //printf( "Size Region1 = %8i Size Region2 = %8i\n", sizeRegion1, sizeRegion2 ); - int sizeDif; - ipMITKSegmentationTYPE *current, *segSrc; - if (sizeRegion1 < sizeRegion2) { - segSrc = (ipMITKSegmentationTYPE*)seg1->data; - sizeDif = sizeRegion2 - sizeRegion1; - } - else { - segSrc = (ipMITKSegmentationTYPE*)seg2->data; - sizeDif = sizeRegion1 - sizeRegion2; +static int FillRegion(const itk::Index<2> startIndex, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic, int fillColor, int eraseColor) +{ + int numberOfPixel = 0; + int mode = (pic->GetPixel(startIndex) == fillColor); + int drawColor = fillColor; + if (mode) + { + drawColor = eraseColor; } - modified = false; - if (sizeDif > 2*(lineEnd-lineStart)) { - // decision is safe enough: - ipMITKSegmentationTYPE *end = picdata + (pic->n[0]*pic->n[1]); - for (current = picdata; current > workPoints; + workPoints.push_back(startIndex); + while (workPoints.size() > 0) + { + itk::Index<2> currentIndex = workPoints.back(); + workPoints.pop_back(); + if ((pic->GetPixel(currentIndex) == fillColor) == mode) + ++numberOfPixel; + pic->SetPixel(currentIndex, drawColor); + + currentIndex[0] -= 1; + if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == fillColor) == mode) + workPoints.push_back(currentIndex); + currentIndex[0] += 2; + if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == fillColor) == mode) + workPoints.push_back(currentIndex); + currentIndex[0] -= 1; + currentIndex[1] -= 1; + if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == fillColor) == mode) + workPoints.push_back(currentIndex); + currentIndex[1] += 2; + if (pic->GetLargestPossibleRegion().IsInside(currentIndex) && (pic->GetPixel(currentIndex) == fillColor) == mode) + workPoints.push_back(currentIndex); } + return numberOfPixel; +} - // restore line: - for (int i=lineStart+1; i::Pointer CloneImage(itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic) +{ + typedef itk::Image< ipMITKSegmentationTYPE, 2 > ItkImageType; - mitkIpPicFree( seg1 ); - mitkIpPicFree( seg2 ); + typedef itk::ImageDuplicator< ItkImageType > DuplicatorType; + DuplicatorType::Pointer duplicator = DuplicatorType::New(); + duplicator->SetInputImage(pic); + duplicator->Update(); - return modified; + return duplicator->GetOutput(); } -void mitk::CorrectorAlgorithm::CalculateDifferenceImage( Image* modifiedImage, Image* originalImage ) +static void OverwriteImage(itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer source, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer target) { - /* - * modifiedImage has ipMITKSegmentationTYPE - * originalImage may be any type - * - * --> we calculate a diff image using ITK, switching for the correct type of originalImage - */ - m_DifferenceImage = NULL; - Image::Pointer tmpPtr = originalImage; - AccessFixedDimensionByItk_1( tmpPtr, ItkCalculateDifferenceImage, 2, modifiedImage ); + typedef itk::Image< ipMITKSegmentationTYPE, 2 > ItkImageType; + typedef itk::ImageRegionIterator ImageIteratorType; + + ImageIteratorType sourceIter(source, source->GetLargestPossibleRegion()); + ImageIteratorType targetIter(target, target->GetLargestPossibleRegion()); + while ( ! sourceIter.IsAtEnd()) + { + targetIter.Set(sourceIter.Get()); + ++sourceIter; + ++targetIter; + } } -template -void mitk::CorrectorAlgorithm::ItkCalculateDifferenceImage( itk::Image* originalImage, Image* modifiedMITKImage ) +bool mitk::CorrectorAlgorithm::ModifySegment(const TSegData &segment, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic) { - typedef itk::Image ModifiedImageType; - typedef itk::Image DiffImageType; - typedef itk::ImageRegionConstIterator< itk::Image > OriginalSliceIteratorType; - typedef itk::ImageRegionConstIterator< ModifiedImageType > ModifiedSliceIteratorType; - typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; - - typename ModifiedImageType::Pointer modifiedImage; - CastToItkImage( modifiedMITKImage, modifiedImage ); - - // create new image as a copy of the input - // this new image is the output of this filter class - typename DiffImageType::Pointer diffImage; - m_DifferenceImage = Image::New(); - PixelType pixelType( mitk::MakeScalarPixelType() ); - m_DifferenceImage->Initialize( pixelType, 2, modifiedMITKImage->GetDimensions() ); - CastToItkImage( m_DifferenceImage, diffImage ); - - // iterators over both input images (original and modified) and the output image (diff) - ModifiedSliceIteratorType modifiedIterator( modifiedImage, diffImage->GetLargestPossibleRegion() ); - OriginalSliceIteratorType originalIterator( originalImage, diffImage->GetLargestPossibleRegion() ); - DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); - - modifiedIterator.GoToBegin(); - originalIterator.GoToBegin(); - diffIterator.GoToBegin(); - - while ( !diffIterator.IsAtEnd() ) + typedef itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer ItkImagePointerType; + // Find the current ColorMode: + ColorSegment(segment, pic, m_FillColor, m_EraseColor); + + // Kein erster Punkt + // Erster Punkt finden + ItkImagePointerType firstSideImage = CloneImage(pic); + itk::Index<2> firstPoint = GetFirstPoint(segment, firstSideImage, m_FillColor); + int firstSidePixel = FillRegion(firstPoint, firstSideImage, m_FillColor, m_EraseColor); + + ItkImagePointerType secondSideImage = CloneImage(pic); + // TODO Problem: Was ist wenn keine Zweite Seite vorhanden? + try { - short signed int difference = static_cast( static_cast(modifiedIterator.Get()) - - static_cast(originalIterator.Get())); // not good for bigger values ?! - diffIterator.Set( difference ); + itk::Index<2> secondPoint = GetFirstPoint(segment, firstSideImage, m_FillColor); + int secondSidePixel = FillRegion(secondPoint, secondSideImage, m_FillColor, m_EraseColor); - ++modifiedIterator; - ++originalIterator; - ++diffIterator; + if (firstSidePixel < secondSidePixel) + { + OverwriteImage(firstSideImage, pic); + } else + { + OverwriteImage(secondSideImage, pic); + } } -} - + catch (std::exception e) + { + e.what(); + } + return true; +} \ No newline at end of file diff --git a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.h b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.h index b2665b81e1..24e5c26c8b 100644 --- a/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.h +++ b/Modules/Segmentation/Algorithms/mitkCorrectorAlgorithm.h @@ -1,99 +1,98 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkCorrectorAlgorithmhIncluded #define mitkCorrectorAlgorithmhIncluded #include "mitkImageToImageFilter.h" #include #include "mitkContourModel.h" #include "ipSegmentation.h" #include namespace mitk { - /** * This class encapsulates an algorithm, which takes a 2D binary image and a contour. * The algorithm tests if the line begins and ends inside or outside a segmentation * and whether areas should be added to or subtracted from the segmentation shape. * * This class has two outputs: * \li a difference image from GetDifferenceImage() * \li the modified input image from GetOutput() * * The difference image is an image of the same dimensions as the input. Each pixel has * one of three values -1, 0, +1 meaning * \li -1 this pixel was foreground in the input image and should be removed from the segmentation * \li 0 this pixel needs no change * \li +1 this pixel was background in the input image and should be added to the segmentation * * The output image is a combination of the original input with the generated difference image. * * \sa CorrectorTool2D */ class MitkSegmentation_EXPORT CorrectorAlgorithm : public ImageToImageFilter { public: mitkClassMacro(CorrectorAlgorithm, ImageToImageFilter); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief User drawn contour */ void SetContour( ContourModel* contour){this->m_Contour = contour;} /** * \brief Calculated difference image. */ //itkGetObjectMacro(DifferenceImage, Image); - protected: // used by TobiasHeimannCorrectionAlgorithm typedef struct { int lineStart; int lineEnd; bool modified; + + std::vector< itk::Index<2> > points; } TSegData; + protected: + CorrectorAlgorithm(); virtual ~CorrectorAlgorithm(); // does the actual processing virtual void GenerateData(); - void TobiasHeimannCorrectionAlgorithm(mitkIpPicDescriptor* pic); - bool modifySegment( int lineStart, int lineEnd, ipMITKSegmentationTYPE state, mitkIpPicDescriptor *pic, int* _ofsArray ); - - void CalculateDifferenceImage( Image* modifiedImage, Image* originalImage ); - template - void ItkCalculateDifferenceImage( itk::Image* originalImage, Image* modifiedMITKImage ); + void ImprovedHeimannCorrectionAlgorithm(itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic); + bool ModifySegment(const TSegData &segment, itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic); Image::Pointer m_WorkingImage; ContourModel::Pointer m_Contour; Image::Pointer m_DifferenceImage; -}; + int m_FillColor; + int m_EraseColor; +}; } #endif -