00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkRegionGrowingTool.h"
00019 #include "mitkToolManager.h"
00020 #include "mitkOverwriteSliceImageFilter.h"
00021
00022 #include "mitkBaseRenderer.h"
00023 #include "mitkRenderingManager.h"
00024 #include "mitkApplicationCursor.h"
00025
00026 #include "ipSegmentation.h"
00027
00028 #include "mitkRegionGrowingTool.xpm"
00029
00030 namespace mitk {
00031 MITK_TOOL_MACRO(MitkExt_EXPORT, RegionGrowingTool, "Region growing tool");
00032 }
00033
00034 #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
00035
00036 mitk::RegionGrowingTool::RegionGrowingTool()
00037 :FeedbackContourTool("PressMoveRelease"),
00038 m_LowerThreshold(200),
00039 m_UpperThreshold(200),
00040 m_InitialLowerThreshold(200),
00041 m_InitialUpperThreshold(200),
00042 m_ScreenYDifference(0),
00043 m_OriginalPicSlice(NULL),
00044 m_SeedPointMemoryOffset(0),
00045 m_VisibleWindow(0),
00046 m_DefaultWindow(0),
00047 m_MouseDistanceScaleFactor(3.0),
00048 m_LastWorkingSeed(-1),
00049 m_FillFeedbackContour(true)
00050 {
00051 }
00052
00053 mitk::RegionGrowingTool::~RegionGrowingTool()
00054 {
00055 }
00056
00057 const char** mitk::RegionGrowingTool::GetXPM() const
00058 {
00059 return mitkRegionGrowingTool_xpm;
00060 }
00061
00062 const char* mitk::RegionGrowingTool::GetName() const
00063 {
00064 return "Region Growing";
00065 }
00066
00067 void mitk::RegionGrowingTool::Activated()
00068 {
00069 Superclass::Activated();
00070 }
00071
00072 void mitk::RegionGrowingTool::Deactivated()
00073 {
00074 Superclass::Deactivated();
00075 }
00076
00089 bool mitk::RegionGrowingTool::OnMousePressed (Action* action, const StateEvent* stateEvent)
00090 {
00091
00092
00093 MITK_INFO << "OnMousePressed" << std::endl;
00094 if (FeedbackContourTool::OnMousePressed( action, stateEvent ))
00095 {
00096 MITK_INFO << "OnMousePressed: FeedbackContourTool says ok" << std::endl;
00097
00098
00099 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00100 if (positionEvent)
00101 {
00102 MITK_INFO << "OnMousePressed: got positionEvent" << std::endl;
00103
00104 m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent );
00105 m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
00106
00107 if ( m_WorkingSlice.IsNotNull() )
00108 {
00109 MITK_INFO << "OnMousePressed: got working slice" << std::endl;
00110
00111
00112 const Geometry3D* workingSliceGeometry = m_WorkingSlice->GetGeometry();
00113 Point3D mprojectedPointIn2D;
00114 workingSliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D);
00115 itk::Index<2> projectedPointInWorkingSlice2D;
00116 projectedPointInWorkingSlice2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 );
00117 projectedPointInWorkingSlice2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 );
00118
00119 if ( workingSliceGeometry->IsIndexInside( projectedPointInWorkingSlice2D ) )
00120 {
00121 MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << projectedPointInWorkingSlice2D << ") IS in working slice" << std::endl;
00122
00123
00124 itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
00125 CastToItkImage( m_WorkingSlice, correctPixelTypeImage );
00126 assert (correctPixelTypeImage.IsNotNull() );
00127
00128
00129
00130
00131
00132
00133 itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
00134 imageDirection.SetIdentity();
00135 correctPixelTypeImage->SetDirection(imageDirection);
00136
00137 Image::Pointer temporarySlice = Image::New();
00138
00139 CastToMitkImage( correctPixelTypeImage, temporarySlice );
00140
00141 mitkIpPicDescriptor* workingPicSlice = temporarySlice->GetSliceData()->GetPicDescriptor();
00142
00143 int initialWorkingOffset = projectedPointInWorkingSlice2D[1] * workingPicSlice->n[0] + projectedPointInWorkingSlice2D[0];
00144
00145 if ( initialWorkingOffset < static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) &&
00146 initialWorkingOffset >= 0 )
00147 {
00148
00149 bool inside = static_cast<ipMITKSegmentationTYPE*>(workingPicSlice->data)[initialWorkingOffset] != 0;
00150 m_PaintingPixelValue = inside ? 0 : 1;
00151
00152 if ( m_LastWorkingSeed >= static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) ||
00153 m_LastWorkingSeed < 0 )
00154 {
00155 inside = false;
00156 }
00157
00158 if ( m_ReferenceSlice.IsNotNull() )
00159 {
00160 MITK_INFO << "OnMousePressed: got reference slice" << std::endl;
00161
00162 m_OriginalPicSlice = m_ReferenceSlice->GetSliceData()->GetPicDescriptor();
00163
00164
00165 if (inside)
00166 {
00167 OnMousePressedInside(action, stateEvent, workingPicSlice, initialWorkingOffset);
00168 }
00169 else
00170 {
00171 OnMousePressedOutside(action, stateEvent);
00172 }
00173 }
00174 }
00175 }
00176 }
00177 }
00178 }
00179
00180 MITK_INFO << "end OnMousePressed" << std::endl;
00181 return true;
00182 }
00183
00189 bool mitk::RegionGrowingTool::OnMousePressedInside(Action* itkNotUsed( action ), const StateEvent* stateEvent, mitkIpPicDescriptor* workingPicSlice, int initialWorkingOffset)
00190 {
00191 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00192
00193
00194
00195
00196
00197 mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice, m_LastWorkingSeed, NULL );
00198 if (segmentationHistory)
00199 {
00200 tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory, initialWorkingOffset );
00201 mitkIpPicFree( segmentationHistory );
00202 if (cutContour.cutIt)
00203 {
00204
00205 Contour::Pointer contourInImageIndexCoordinates = Contour::New();
00206 contourInImageIndexCoordinates->Initialize();
00207 Point3D newPoint;
00208 for (int index = 0; index < cutContour.deleteSize; ++index)
00209 {
00210 newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ];
00211 newPoint[1] = cutContour.deleteCurve[ 2 * index + 1];
00212 newPoint[2] = 0.0;
00213
00214 contourInImageIndexCoordinates->AddVertex( newPoint + 0.5 );
00215 }
00216
00217 free(cutContour.traceline);
00218 free(cutContour.deleteCurve);
00219 free(cutContour.onGradient);
00220
00221 Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice, contourInImageIndexCoordinates, true );
00222
00223 FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates );
00224 FeedbackContourTool::SetFeedbackContourVisible(true);
00225 mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
00226 m_FillFeedbackContour = true;
00227 }
00228 else
00229 {
00230 m_FillFeedbackContour = false;
00231 }
00232
00233 }
00234 else
00235 {
00236 m_FillFeedbackContour = false;
00237 }
00238
00239 m_ReferenceSlice = NULL;
00240
00241 return true;
00242 }
00243
00250 bool mitk::RegionGrowingTool::OnMousePressedOutside(Action* itkNotUsed( action ), const StateEvent* stateEvent)
00251 {
00252 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00253
00254
00255
00256 const Geometry3D* sliceGeometry = m_ReferenceSlice->GetGeometry();
00257 Point3D mprojectedPointIn2D;
00258 sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D );
00259 itk::Index<2> projectedPointIn2D;
00260 projectedPointIn2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 );
00261 projectedPointIn2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 );
00262
00263 if ( sliceGeometry->IsIndexInside( mprojectedPointIn2D ) )
00264 {
00265 MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << mprojectedPointIn2D << ") IS in reference slice" << std::endl;
00266
00267
00268
00269 m_LastScreenPosition = ApplicationCursor::GetInstance()->GetCursorPosition();
00270 m_ScreenYDifference = 0;
00271
00272 m_SeedPointMemoryOffset = projectedPointIn2D[1] * m_OriginalPicSlice->n[0] + projectedPointIn2D[0];
00273 m_LastWorkingSeed = m_SeedPointMemoryOffset;
00274
00275 if ( m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] ) &&
00276 m_SeedPointMemoryOffset >= 0 )
00277 {
00278
00279
00280
00281 LevelWindow lw(0, 500);
00282 m_ToolManager->GetReferenceData(0)->GetLevelWindow(lw);
00283
00284 m_VisibleWindow = lw.GetWindow();
00285
00286 m_DefaultWindow = lw.GetDefaultWindow();
00287
00288 static bool initializedAlready = false;
00289
00290 if (!initializedAlready)
00291 {
00292 m_InitialLowerThreshold = static_cast<int>(m_VisibleWindow / 10.0);
00293 m_InitialUpperThreshold = static_cast<int>(m_VisibleWindow / 10.0);
00294
00295 initializedAlready = true;
00296 }
00297
00298 m_LowerThreshold = m_InitialLowerThreshold;
00299 m_UpperThreshold = m_InitialUpperThreshold;
00300
00301 DisplayGeometry* displayGeometry = positionEvent->GetSender()->GetDisplayGeometry();
00302 if (displayGeometry)
00303 {
00304 m_MouseDistanceScaleFactor = m_VisibleWindow / ( 3.0 * displayGeometry->GetDisplayHeight() );
00305 }
00306
00307
00308 mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour();
00309 ipMITKSegmentationFree( result);
00310
00311
00312 FeedbackContourTool::SetFeedbackContourVisible(true);
00313 mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
00314
00315 m_FillFeedbackContour = true;
00316 }
00317 }
00318
00319 return true;
00320 }
00321
00327 bool mitk::RegionGrowingTool::OnMouseMoved (Action* action, const StateEvent* stateEvent)
00328 {
00329 if (FeedbackContourTool::OnMouseMoved( action, stateEvent ))
00330 {
00331 if ( m_ReferenceSlice.IsNotNull() && m_OriginalPicSlice )
00332 {
00333 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00334 if (positionEvent)
00335 {
00336 ApplicationCursor* cursor = ApplicationCursor::GetInstance();
00337 if (!cursor) return false;
00338 m_ScreenYDifference += cursor->GetCursorPosition()[1] - m_LastScreenPosition[1];
00339 cursor->SetCursorPosition( m_LastScreenPosition );
00340
00341 m_LowerThreshold = m_InitialLowerThreshold + static_cast<int>( m_ScreenYDifference * m_MouseDistanceScaleFactor );
00342 if (m_LowerThreshold < 1) m_LowerThreshold = 1;
00343 if (m_LowerThreshold > m_VisibleWindow / 2) m_LowerThreshold = m_VisibleWindow / 2;
00344
00345 m_UpperThreshold = m_InitialUpperThreshold + static_cast<int>( m_ScreenYDifference * m_MouseDistanceScaleFactor );
00346 if (m_UpperThreshold < 1) m_UpperThreshold = 1;
00347 if (m_UpperThreshold > m_VisibleWindow / 2) m_UpperThreshold = m_VisibleWindow / 2;
00348
00349
00350
00351
00352 mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour();
00353 ipMITKSegmentationFree( result );
00354
00355
00356 mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow());
00357 }
00358 }
00359 }
00360
00361 return true;
00362 }
00363
00367 bool mitk::RegionGrowingTool::OnMouseReleased(Action* action, const StateEvent* stateEvent)
00368 {
00369 if (FeedbackContourTool::OnMouseReleased( action, stateEvent ))
00370 {
00371
00372 if ( m_WorkingSlice.IsNotNull() && m_OriginalPicSlice )
00373 {
00374 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00375 if (positionEvent)
00376 {
00377
00378 m_InitialLowerThreshold = m_LowerThreshold;
00379 m_InitialUpperThreshold = m_UpperThreshold;
00380
00381 if (m_FillFeedbackContour)
00382 {
00383
00384 Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
00385 if (feedbackContour)
00386 {
00387 Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( m_WorkingSlice, feedbackContour, false, false );
00388
00389 if (projectedContour.IsNotNull())
00390 {
00391 FeedbackContourTool::FillContourInSlice( projectedContour, m_WorkingSlice, m_PaintingPixelValue );
00392
00393
00394 int affectedDimension( -1 );
00395 int affectedSlice( -1 );
00396 const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
00397 FeedbackContourTool::DetermineAffectedImageSlice( dynamic_cast<Image*>( m_ToolManager->GetWorkingData(0)->GetData() ), planeGeometry, affectedDimension, affectedSlice );
00398
00399 MITK_INFO << "OnMouseReleased: writing back to dimension " << affectedDimension << ", slice " << affectedSlice << " in working image" << std::endl;
00400
00401 OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New();
00402 Image::Pointer workingImage = dynamic_cast<Image*>( m_ToolManager->GetWorkingData(0)->GetData() );
00403 slicewriter->SetInput( workingImage );
00404 slicewriter->SetCreateUndoInformation( true );
00405 slicewriter->SetSliceImage( m_WorkingSlice );
00406 slicewriter->SetSliceDimension( affectedDimension );
00407 slicewriter->SetSliceIndex( affectedSlice );
00408 slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( workingImage ) );
00409 slicewriter->Update();
00410 }
00411 }
00412 }
00413
00414 FeedbackContourTool::SetFeedbackContourVisible(false);
00415 mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
00416 }
00417 }
00418 }
00419
00420 m_ReferenceSlice = NULL;
00421 m_WorkingSlice = NULL;
00422 m_OriginalPicSlice = NULL;
00423
00424 return true;
00425 }
00426
00431 mitkIpPicDescriptor* mitk::RegionGrowingTool::PerformRegionGrowingAndUpdateContour()
00432 {
00433
00434 assert (m_OriginalPicSlice);
00435 if (m_OriginalPicSlice->n[0] != 256 || m_OriginalPicSlice->n[1] != 256)
00436 assert( (m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] )) && (m_SeedPointMemoryOffset >= 0) );
00437
00438
00439 float ignored;
00440 int oneContourOffset( 0 );
00441 mitkIpPicDescriptor* regionGrowerResult = ipMITKSegmentationGrowRegion4N( m_OriginalPicSlice,
00442 m_SeedPointMemoryOffset,
00443 true,
00444 m_LowerThreshold,
00445 m_UpperThreshold,
00446 0,
00447 NULL,
00448 oneContourOffset,
00449 ignored
00450 );
00451
00452 if (!regionGrowerResult || oneContourOffset == -1)
00453 {
00454 Contour::Pointer dummyContour = Contour::New();
00455 dummyContour->Initialize();
00456 FeedbackContourTool::SetFeedbackContour( *dummyContour );
00457
00458 if (regionGrowerResult) ipMITKSegmentationFree(regionGrowerResult);
00459 return NULL;
00460 }
00461
00462
00463 bool smoothResult( true );
00464 mitkIpPicDescriptor* smoothedRegionGrowerResult;
00465 if (smoothResult)
00466 {
00467
00468 smoothedRegionGrowerResult = SmoothIPPicBinaryImage( regionGrowerResult, oneContourOffset );
00469
00470 ipMITKSegmentationFree( regionGrowerResult );
00471 }
00472 else
00473 {
00474 smoothedRegionGrowerResult = regionGrowerResult;
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 int numberOfContourPoints( 0 );
00484 int newBufferSize( 0 );
00485 float* contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize );
00486 if (contourPoints)
00487 {
00488 while ( !ipMITKSegmentationIsInsideContour( contourPoints,
00489 numberOfContourPoints,
00490 m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0],
00491 m_SeedPointMemoryOffset / smoothedRegionGrowerResult->n[0]
00492 ) )
00493 {
00494
00495 ipMITKSegmentationReplaceRegion4N( smoothedRegionGrowerResult, oneContourOffset, 0 );
00496
00497
00498 int rowLength = smoothedRegionGrowerResult->n[0];
00499 oneContourOffset = m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0]
00500 + rowLength*(smoothedRegionGrowerResult->n[1]-1);
00501
00502 while ( oneContourOffset >=0
00503 && (*(static_cast<ipMITKSegmentationTYPE*>(smoothedRegionGrowerResult->data) + oneContourOffset) == 0) )
00504 {
00505 oneContourOffset -= rowLength;
00506 }
00507
00508 if ( oneContourOffset < 0 )
00509 {
00510 break;
00511 }
00512
00513 free(contourPoints);
00514 contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize );
00515 }
00516
00517
00518 Contour::Pointer contourInImageIndexCoordinates = Contour::New();
00519 contourInImageIndexCoordinates->Initialize();
00520 Point3D newPoint;
00521 for (int index = 0; index < numberOfContourPoints; ++index)
00522 {
00523 newPoint[0] = contourPoints[ 2 * index + 0 ];
00524 newPoint[1] = contourPoints[ 2 * index + 1];
00525 newPoint[2] = 0;
00526
00527 contourInImageIndexCoordinates->AddVertex( newPoint );
00528 }
00529
00530 free(contourPoints);
00531
00532 Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_ReferenceSlice, contourInImageIndexCoordinates, true );
00533
00534 FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates );
00535 }
00536
00537
00538 return smoothedRegionGrowerResult;
00539 }
00540
00552 void mitk::RegionGrowingTool::SmoothIPPicBinaryImageHelperForRows( mitkIpPicDescriptor* sourceImage, mitkIpPicDescriptor* dest, int &contourOfs, int* maskOffsets, int maskSize, int startOffset, int endOffset )
00553 {
00554
00555 ipMITKSegmentationTYPE* current;
00556 ipMITKSegmentationTYPE* source = ((ipMITKSegmentationTYPE*)sourceImage->data) + startOffset;
00557 ipMITKSegmentationTYPE* end = ((ipMITKSegmentationTYPE*)dest->data) + endOffset;
00558 int ofs = startOffset;
00559 int minority = (maskSize - 1) / 2;
00560
00561 for (current = ((ipMITKSegmentationTYPE*)dest->data) + startOffset; current<end; current++)
00562 {
00563 mitkIpInt1_t sum( 0 );
00564 for (int i = 0; i < maskSize; ++i)
00565 {
00566 sum += *(source+maskOffsets[i]);
00567 }
00568
00569 if (sum > minority)
00570 {
00571 *current = 1;
00572 contourOfs = ofs;
00573 }
00574 else
00575 {
00576 *current = 0;
00577 }
00578
00579 ++source;
00580 ++ofs;
00581 }
00582 }
00583
00587 mitkIpPicDescriptor* mitk::RegionGrowingTool::SmoothIPPicBinaryImage( mitkIpPicDescriptor* image, int &contourOfs, mitkIpPicDescriptor* dest )
00588 {
00589 if (!image) return NULL;
00590
00591
00592 #define MSK_SIZE5x5 21
00593 #define MSK_SIZE3x3 5
00594 #define MSK_SIZE3x1 3
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 int mask5x5[MSK_SIZE5x5][2]
00606 = {
00607 {-1,-2}, {0,-2}, {1,-2},
00608 {-2,-1}, {-1,-1}, {0,-1}, {1,-1}, {2,-1},
00609 {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0},
00610 {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1},
00611 {-1, 2}, {0, 2}, {1, 2}
00612 };
00613
00614 int mask3x3[MSK_SIZE3x3][2]
00615 = {
00616 {0,-1},
00617 {-1, 0}, {0, 0}, {1, 0},
00618 {0, 1}
00619 };
00620
00621 int mask3x1[MSK_SIZE3x1][2]
00622 = {
00623 {-1, 0}, {0, 0}, {1, 0}
00624 };
00625
00626
00627
00628
00629
00630
00631 int maskOffset5x5[MSK_SIZE5x5];
00632 int line = image->n[0];
00633 for (int i=0; i<MSK_SIZE5x5; i++)
00634 {
00635 maskOffset5x5[i] = mask5x5[i][0] + line * mask5x5[i][1];
00636 }
00637
00638 int maskOffset3x3[MSK_SIZE3x3];
00639 for (int i=0; i<MSK_SIZE3x3; i++)
00640 {
00641 maskOffset3x3[i] = mask3x3[i][0] + line * mask3x3[i][1];
00642 }
00643
00644 int maskOffset3x1[MSK_SIZE3x1];
00645 for (int i=0; i<MSK_SIZE3x1; i++)
00646 {
00647 maskOffset3x1[i] = mask3x1[i][0] + line * mask3x1[i][1];
00648 }
00649
00650
00651 if (!dest)
00652 {
00653
00654 dest = ipMITKSegmentationNew( image );
00655 }
00656
00657 int spareOut3Rows = 3*image->n[0];
00658 int spareOut1Rows = 1*image->n[0];
00659
00660 if ( image->n[1] > 0 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, 1, dest->n[0] );
00661 if ( image->n[1] > 3 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, spareOut1Rows, dest->n[0]*3 );
00662 if ( image->n[1] > 6 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset5x5, MSK_SIZE5x5, spareOut3Rows, dest->n[0]*dest->n[1] - spareOut3Rows );
00663 if ( image->n[1] > 8 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, dest->n[0]*dest->n[1] -spareOut3Rows, dest->n[0]*dest->n[1] - spareOut1Rows );
00664 if ( image->n[1] > 10) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, dest->n[0]*dest->n[1] -spareOut1Rows, dest->n[0]*dest->n[1] - 1 );
00665
00666
00667 if ( *((ipMITKSegmentationTYPE*)(dest->data)+1) == 1 )
00668 {
00669 *((ipMITKSegmentationTYPE*)(dest->data)+0) = 1;
00670 }
00671
00672 if (dest->n[0] * dest->n[1] > 2)
00673 {
00674
00675 if ( *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-2) == 1 )
00676 {
00677 *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-1) = 1;
00678 }
00679 }
00680
00681 return dest;
00682 }
00683
00684