00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkCorrectorAlgorithm.h"
00019 #include "mitkImageCast.h"
00020 #include "mitkContourUtils.h"
00021
00022 mitk::CorrectorAlgorithm::CorrectorAlgorithm()
00023 :ImageToImageFilter()
00024 {
00025 }
00026
00027 mitk::CorrectorAlgorithm::~CorrectorAlgorithm()
00028 {
00029 }
00030
00031
00032 void mitk::CorrectorAlgorithm::GenerateData()
00033 {
00034 Image::Pointer inputImage = const_cast<Image*>(ImageToImageFilter::GetInput(0));
00035
00036 if (inputImage.IsNull() || inputImage->GetDimension() != 2)
00037 {
00038 itkExceptionMacro("CorrectorAlgorithm needs a 2D image as input.");
00039 }
00040
00041 if (m_Contour.IsNull())
00042 {
00043 itkExceptionMacro("CorrectorAlgorithm needs a Contour object as input.");
00044 }
00045
00046
00047 m_WorkingImage = Image::New();
00048 m_WorkingImage->Initialize( inputImage );
00049 m_WorkingImage->SetVolume( inputImage.GetPointer()->GetData() );
00050
00051 if (inputImage->GetTimeSlicedGeometry() )
00052 {
00053 AffineGeometryFrame3D::Pointer originalGeometryAGF = inputImage->GetTimeSlicedGeometry()->Clone();
00054 TimeSlicedGeometry::Pointer originalGeometry = dynamic_cast<TimeSlicedGeometry*>( originalGeometryAGF.GetPointer() );
00055 m_WorkingImage->SetGeometry( originalGeometry );
00056 }
00057 else
00058 {
00059 itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy.");
00060 }
00061
00062
00063
00064 itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
00065 CastToItkImage( m_WorkingImage, correctPixelTypeImage );
00066 assert (correctPixelTypeImage.IsNotNull() );
00067
00068
00069
00070
00071
00072
00073 itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
00074 imageDirection.SetIdentity();
00075 correctPixelTypeImage->SetDirection(imageDirection);
00076
00077 Image::Pointer temporarySlice = this->GetOutput();
00078
00079 CastToMitkImage( correctPixelTypeImage, temporarySlice );
00080
00081 TobiasHeimannCorrectionAlgorithm( temporarySlice->GetSliceData()->GetPicDescriptor() );
00082
00083
00084
00085 CalculateDifferenceImage( temporarySlice, inputImage );
00086 if ( m_DifferenceImage.IsNotNull() && inputImage->GetTimeSlicedGeometry() )
00087 {
00088 AffineGeometryFrame3D::Pointer originalGeometryAGF = inputImage->GetTimeSlicedGeometry()->Clone();
00089 TimeSlicedGeometry::Pointer originalGeometry = dynamic_cast<TimeSlicedGeometry*>( originalGeometryAGF.GetPointer() );
00090 m_DifferenceImage->SetGeometry( originalGeometry );
00091 }
00092 else
00093 {
00094 itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy.");
00095 }
00096 }
00097
00098 void mitk::CorrectorAlgorithm::TobiasHeimannCorrectionAlgorithm(mitkIpPicDescriptor* pic)
00099 {
00126 int oaSize = 1000000;
00127 int* _ofsArray = new int[ oaSize ];
00128 for (int i=0; i<oaSize; i++) _ofsArray[i] = 0;
00129
00130 std::vector<TSegData> segData;
00131 segData.reserve( 16 );
00132
00133 Contour* contour3D = const_cast<Contour*>(m_Contour.GetPointer());
00134 ContourUtils::Pointer contourUtils = ContourUtils::New();
00135 Contour::Pointer projectedContour = contourUtils->ProjectContourTo2DSlice( m_WorkingImage, contour3D, true, false );
00136
00137 if (projectedContour.IsNull())
00138 {
00139 delete[] _ofsArray;
00140 return;
00141 }
00142
00143 if (projectedContour->GetNumberOfPoints() < 2)
00144 {
00145 delete[] _ofsArray;
00146 return;
00147 }
00148
00149
00150 mitkIpInt4_t* _points = new mitkIpInt4_t[2 * projectedContour->GetNumberOfPoints()];
00151 const Contour::PathType::VertexListType* pointsIn2D = projectedContour->GetContourPath()->GetVertexList();
00152 unsigned int index(0);
00153 for ( Contour::PathType::VertexListType::const_iterator iter = pointsIn2D->begin();
00154 iter != pointsIn2D->end();
00155 ++iter, ++index )
00156 {
00157 _points[ 2 * index + 0 ] = static_cast<mitkIpInt4_t>( (*iter)[0] + 1.0 );
00158 _points[ 2 * index + 1 ] = static_cast<mitkIpInt4_t>( (*iter)[1] + 1.0 );
00159 }
00160
00161
00162 int _ofsNum = 0;
00163 unsigned int num = projectedContour->GetNumberOfPoints();
00164 int lastOfs = -1;
00165 for (unsigned int i=0; i<num-1; i++)
00166 {
00167 float x = _points [2*i] + 0.5;
00168 float y = _points [2*i+1] + 0.5;
00169 float difX = _points [2*i+2] - x + 0.5;
00170 float difY = _points [2*i+3] - y + 0.5;
00171 float length = sqrt( difX*difX + difY*difY );
00172 float dx = difX / length;
00173 float dy = difY / length;
00174 for (int p=0; ((float)p)<length; p++)
00175 {
00176
00177 if (x<0) x=0.5;
00178 else if (x>=pic->n[0]) x = pic->n[0]-0.5;
00179 if (y<0) y=0.5;
00180 else if (y>=pic->n[1]) y = pic->n[1]-0.5;
00181
00182 int ofs = (int)(x) + pic->n[0]*((int)(y));
00183 x += dx;
00184 y += dy;
00185 if (ofs != lastOfs)
00186 {
00187 _ofsArray[_ofsNum++] = ofs;
00188 lastOfs = ofs;
00189 }
00190 }
00191 }
00192
00193 if (_ofsNum == 0)
00194 {
00195
00196 delete[] _ofsArray;
00197 delete[] _points;
00198 return;
00199 }
00200
00201 ipMITKSegmentationTYPE* picdata = static_cast<ipMITKSegmentationTYPE*>(pic->data);
00202
00203
00204 int numSegments = 0;
00205 ipMITKSegmentationTYPE state = *(picdata + _ofsArray[0]);
00206 int ofsP = 1;
00207 int modifyStart, modifyEnd;
00208 bool nextSegment;
00209 segData.clear();
00210 do
00211 {
00212 nextSegment = false;
00213 while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++;
00214 if (ofsP<_ofsNum)
00215 {
00216 int lineStart = ofsP-1;
00217 if (numSegments==0) modifyStart = ofsP;
00218 state = *(picdata + _ofsArray[ofsP]);
00219 while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++;
00220 if (ofsP<_ofsNum)
00221 {
00222 int lineEnd = ofsP;
00223 modifyEnd = lineEnd;
00224 nextSegment = true;
00225
00226 TSegData thisSegData;
00227 thisSegData.lineStart = lineStart;
00228 thisSegData.lineEnd = lineEnd;
00229 thisSegData.modified = modifySegment( lineStart, lineEnd, state, pic, _ofsArray );
00230 segData.push_back( thisSegData );
00231 numSegments++;
00232 }
00233 }
00234 } while (nextSegment);
00235
00236 for (int segNr=0; segNr < numSegments; segNr++)
00237 {
00238
00239 if ( segData[segNr].modified )
00240 {
00241 for (int i=segData[segNr].lineStart+1; i<segData[segNr].lineEnd; i++)
00242 {
00243 *(picdata + _ofsArray[i]) = 1;
00244 }
00245 }
00246 }
00247
00248 if (numSegments == 0)
00249 {
00250 if (num <= 1)
00251 {
00252
00253
00254
00255
00256
00257
00258 }
00259 else if ( *(picdata + _ofsArray[_ofsNum-1]) == *(picdata + _ofsArray[0]))
00260 {
00261
00262
00263 mitkIpInt4_t* p = new mitkIpInt4_t[2 * num];
00264 for (unsigned int i = 0; i < num; i++)
00265 {
00266 p[2 * i] = (mitkIpInt4_t) _points [2 * i];
00267 p[2 * i + 1] = (mitkIpInt4_t) _points [2 * i + 1];
00268 }
00269
00270 if (state == 0) ipMITKSegmentationCombineRegion (pic, p, num, 0, IPSEGMENTATION_OR, 1);
00271 else ipMITKSegmentationCombineRegion (pic, p, num, 0, IPSEGMENTATION_AND, 0);
00272
00273 delete[] p;
00274 }
00275 }
00276
00277 int numberOfContourPoints( 0 );
00278 int oneContourOffset( 0 );
00279 int newBufferSize( 0 );
00280
00281 int imageSize = pic->n[0]*pic->n[1];
00282 for (oneContourOffset = 0; oneContourOffset < imageSize; oneContourOffset++)
00283 if ( ((ipMITKSegmentationTYPE*) pic->data)[oneContourOffset]> 0) break;
00284
00285 float* contourPoints = ipMITKSegmentationGetContour8N( pic, oneContourOffset, numberOfContourPoints, newBufferSize );
00286
00287 if (contourPoints)
00288 {
00289
00290
00291 Contour::Pointer contourInImageIndexCoordinates = Contour::New();
00292 contourInImageIndexCoordinates->Initialize();
00293 Point3D newPoint;
00294 for (int index = 0; index < numberOfContourPoints; ++index)
00295 {
00296 newPoint[0] = contourPoints[ 2 * index + 0 ];
00297 newPoint[1] = contourPoints[ 2 * index + 1];
00298 newPoint[2] = 0;
00299
00300 contourInImageIndexCoordinates->AddVertex( newPoint );
00301 }
00302
00303 free(contourPoints);
00304
00305 ContourUtils::Pointer contourUtils = ContourUtils::New();
00306 contourUtils->FillContourInSlice( contourInImageIndexCoordinates, m_WorkingImage );
00307 }
00308
00309 delete[] _ofsArray;
00310 delete[] _points;
00311 }
00312
00313 bool mitk::CorrectorAlgorithm::modifySegment( int lineStart, int lineEnd, ipMITKSegmentationTYPE state, mitkIpPicDescriptor *pic, int* _ofsArray )
00314 {
00315
00316 int nbDelta4[4];
00317 nbDelta4[0]=1; nbDelta4[1]=pic->n[0]; nbDelta4[1]*=-1;
00318 nbDelta4[2]=-1; nbDelta4[3]=pic->n[0];
00319
00320
00321 int nbDelta8[8];
00322 nbDelta8[0] = 1; nbDelta8[1] = nbDelta4[1]+1; nbDelta8[2] = nbDelta4[1]; nbDelta8[3] = nbDelta4[1]-1;
00323 nbDelta8[4] = -1; nbDelta8[5] = nbDelta4[3]-1; nbDelta8[6] = nbDelta4[3]; nbDelta8[7] = nbDelta4[3]+1;
00324
00325 ipMITKSegmentationTYPE* picdata = static_cast<ipMITKSegmentationTYPE*>(pic->data);
00326
00327 ipMITKSegmentationTYPE saveStart = *(picdata + _ofsArray[lineStart]);
00328 ipMITKSegmentationTYPE saveEnd = *(picdata + _ofsArray[lineEnd]);
00329 ipMITKSegmentationTYPE newState = ((!state)&1) + 2;
00330
00331
00332 mitkIpPicDescriptor *seg1 = mitkIpPicClone( pic );
00333 mitkIpPicDescriptor *seg2 = mitkIpPicClone( pic );
00334
00335 int i;
00336
00337
00338 for (i=lineStart; i<=lineEnd; i++) {
00339 *(picdata + _ofsArray[i]) = 3;
00340 }
00341
00342
00343 bool firstPix = true;
00344 bool modified;
00345 int line = pic->n[0];
00346 int maxOfs = (int)(line * pic->n[1]);
00347
00348 for (i=lineStart+1; i<lineEnd; i++) {
00349 do {
00350 modified = false;
00351 for (int nb=0; nb<8; nb++) {
00352 int nbOfs = _ofsArray[i] + nbDelta8[nb];
00353 if ( nbOfs < 0
00354 || nbOfs >= maxOfs
00355 ) continue;
00356 ipMITKSegmentationTYPE nbVal = *(picdata + nbOfs);
00357 ipMITKSegmentationTYPE destVal = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs);
00358 if (nbVal!=3 && destVal!=newState) {
00359 if (firstPix) {
00360 *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState;
00361 firstPix = false;
00362 modified = true;
00363 }
00364 else {
00365 int tnb = 0;
00366 while ( tnb < 4
00367 && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs)
00368 && *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs + nbDelta4[tnb]) != newState
00369 )
00370 tnb++;
00371
00372 if (tnb < 4 && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs) ) {
00373 *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState;
00374 modified = true;
00375 }
00376 }
00377 }
00378 }
00379 } while (modified);
00380 }
00381
00382
00383 for (i=lineStart+1; i<lineEnd; i++) {
00384 for (int nb=0; nb<4; nb++) {
00385 int nbOfs = _ofsArray[i] + nbDelta4[nb];
00386 if ( nbOfs < 0
00387 || nbOfs >= maxOfs
00388 ) continue;
00389 ipMITKSegmentationTYPE lineVal = *(picdata + nbOfs);
00390 ipMITKSegmentationTYPE side1Val = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs);
00391 if (lineVal != 3 && side1Val != newState) {
00392 *(((ipMITKSegmentationTYPE*)seg2->data) + nbOfs) = newState;
00393 }
00394 }
00395 }
00396
00397
00398 *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineStart]) = newState;
00399 *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineEnd]) = newState;
00400 *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineStart]) = newState;
00401 *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineEnd]) = newState;
00402
00403
00404
00405 newState = (!state)&1;
00406 int sizeRegion1 = 0, sizeRegion2 = 0;
00407 for (i=lineStart+1; i<lineEnd; i++) {
00408 if (*(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[i]) != newState) {
00409 sizeRegion1 += ipMITKSegmentationReplaceRegion4N( seg1, _ofsArray[i], newState );
00410 }
00411 if (*(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[i]) != newState) {
00412 sizeRegion2 += ipMITKSegmentationReplaceRegion4N( seg2, _ofsArray[i], newState );
00413 }
00414 }
00415
00416
00417
00418 int sizeDif;
00419 ipMITKSegmentationTYPE *current, *segSrc;
00420 if (sizeRegion1 < sizeRegion2) {
00421 segSrc = (ipMITKSegmentationTYPE*)seg1->data;
00422 sizeDif = sizeRegion2 - sizeRegion1;
00423 }
00424 else {
00425 segSrc = (ipMITKSegmentationTYPE*)seg2->data;
00426 sizeDif = sizeRegion1 - sizeRegion2;
00427 }
00428
00429 modified = false;
00430 if (sizeDif > 2*(lineEnd-lineStart)) {
00431
00432 ipMITKSegmentationTYPE *end = picdata + (pic->n[0]*pic->n[1]);
00433 for (current = picdata; current<end; current++) {
00434 if (*segSrc == newState) *current = newState;
00435 segSrc++;
00436 }
00437 modified = true;
00438 }
00439
00440
00441 for (int i=lineStart+1; i<lineEnd; i++) {
00442 *(picdata + _ofsArray[i]) = state;
00443 }
00444
00445 *(picdata + _ofsArray[lineStart]) = saveStart;
00446 *(picdata + _ofsArray[lineEnd]) = saveEnd;
00447
00448 mitkIpPicFree( seg1 );
00449 mitkIpPicFree( seg2 );
00450
00451 return modified;
00452 }
00453
00454 void mitk::CorrectorAlgorithm::CalculateDifferenceImage( Image* modifiedImage, Image* originalImage )
00455 {
00456
00457
00458
00459
00460
00461
00462 m_DifferenceImage = NULL;
00463 Image::Pointer tmpPtr = originalImage;
00464 AccessFixedDimensionByItk_1( tmpPtr, ItkCalculateDifferenceImage, 2, modifiedImage );
00465 }
00466
00467 template<typename TPixel, unsigned int VImageDimension>
00468 void mitk::CorrectorAlgorithm::ItkCalculateDifferenceImage( itk::Image<TPixel, VImageDimension>* originalImage, Image* modifiedMITKImage )
00469 {
00470 typedef itk::Image<ipMITKSegmentationTYPE, VImageDimension> ModifiedImageType;
00471 typedef itk::Image<short signed int, VImageDimension> DiffImageType;
00472 typedef itk::ImageRegionConstIterator< itk::Image<TPixel,VImageDimension> > OriginalSliceIteratorType;
00473 typedef itk::ImageRegionConstIterator< ModifiedImageType > ModifiedSliceIteratorType;
00474 typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType;
00475
00476 typename ModifiedImageType::Pointer modifiedImage;
00477 CastToItkImage( modifiedMITKImage, modifiedImage );
00478
00479
00480
00481 typename DiffImageType::Pointer diffImage;
00482 m_DifferenceImage = Image::New();
00483 PixelType pixelType( typeid(short signed int) );
00484 m_DifferenceImage->Initialize( pixelType, 2, modifiedMITKImage->GetDimensions() );
00485 CastToItkImage( m_DifferenceImage, diffImage );
00486
00487
00488 ModifiedSliceIteratorType modifiedIterator( modifiedImage, diffImage->GetLargestPossibleRegion() );
00489 OriginalSliceIteratorType originalIterator( originalImage, diffImage->GetLargestPossibleRegion() );
00490 DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() );
00491
00492 modifiedIterator.GoToBegin();
00493 originalIterator.GoToBegin();
00494 diffIterator.GoToBegin();
00495
00496 while ( !diffIterator.IsAtEnd() )
00497 {
00498 short signed int difference = static_cast<short signed int>( static_cast<signed int>(modifiedIterator.Get()) -
00499 static_cast<signed int>(originalIterator.Get()));
00500 diffIterator.Set( difference );
00501
00502 ++modifiedIterator;
00503 ++originalIterator;
00504 ++diffIterator;
00505 }
00506 }
00507