[Insight-users] compare speed of dilate and erode in itk, vtk
and matlab
Miller, James V (Research)
millerjv@crd.ge.com
Thu, 1 May 2003 13:51:10 -0400
I just dug through the Matlab code as far they will let
outsiders dig. Matlab implements the opening and closing
as a sequence of erodes and dilates just like ITK does.
> -----Original Message-----
> From: Luis Ibanez [mailto:luis.ibanez@kitware.com]
> Sent: Thursday, May 01, 2003 11:35 AM
> To: Insight-users@public.kitware.com; novalet@yahoo.com.cn
> Subject: [Insight-users] compare speed of dilate and erode in itk, vtk
> and matlab
>
>
> Hi Chen,
>
> Thanks for letting us know about the results of
> your tests. They are quite interesting indeed.
>
> 1) About the compiler error in VC6:
> Did you installed the Service Pack 5 for VC++ ?
> This is required for building ITK.
> We are not getting this error in our nightly
> builds with VC++ 6.0, so it is definetely
> something with your compiler.
>
> 2) If I may summarize the result of the test,
> when they are comparable the timings are:
>
> - Matlab 19 s
> - VTK 20 s
> - ITK 56 s
>
> Is this right ?
>
> This clearly shows that we may have to
> improve the performance of these filters.
> Probably creating specialized 3D version
> could help. Another option is to provide
> optimal implementations for Openning and
> Closing, right now this is done by a sequence
> of erode+dilate, in practice some performance
> can be improved by doing the opening in a
> single pass.
>
> We will take a look at the options.
>
>
> 3) Just for the record: whenever you need
> timing of ITK methods, you can take advantage
> of the TimeProbe and TimeCollector classes:
>
> http://www.itk.org/Insight/Doxygen/html/classitk_1_1TimeProbe.html
> http://www.itk.org/Insight/Doxygen/html/classitk_1_1TimeProbes
> CollectorBase.html
>
> Their use is quite simple and allows to do
> timing of specific sections of code.
>
>
>
> Regards,
>
>
> Luis
>
>
> ------------------------------
> Chen Fu wrote:
>
> > Hi Lius,
> > Yes, i build ITK and my demo in both "Release" option
> > and "Debug" option in vc6, but not directly select in
> > CMake.
> > To my understand, they are the same. BTW, vc6 report a
> > internal error(should call MS support according to the
> > error info) when compile release option on
> > itkDanielssonDistanceMapImageFilter.txx Line 286, i
> > have to seperate it into two lines to get pass, but in
> > debug option it is not a problem.
> > OutputImageType::PixelType p = static_cast<typename
> > OutputImageType::PixelType>(sqrt( distance ));
> > dt.Set( p );
> > I don't know the reason, any idea?
> >
> > You are right. The "release" is much quicker than
> > "debug" option. But compare to matlab, it is still
> > slower.
> >
> > My code list below, it takes itk release option 56
> > seconds to finish, debug option takes 608 seconds,
> > while vtk(written in tcl script) cost 20 seconds,
> > matlab code cost only 1.6 seconds.
> >
> > I carefully exam the code and at last find out the
> > speed of matlab is benefit from computing on really
> > blackwhite image format which means 8 pixels in one
> > byte. If i replace "BW = im2bw(Ic, graythresh(Ic));"
> > with "BW = Ic", matlab will compute in a gray image
> > mode, that will take 19 seconds to finished.
> >
> >>From these tests, i think the morphology operators in
> > itk deserve more efforts to enhance their performance.
> > Maybe the pure iterator system is expensive for visit
> > every pixel. But i am not familiar enough with source
> > code yet, so can not give any really constructive
> > suggestion, sorry. These tests are just my exercises
> > to use itk and vtk.
> >
> > matlab code:
> > ========================================
> > t0 = clock;
> > I = imread('d:\nova\pearbig.tif');
> > Ic = imcomplement(I);
> > BW = im2bw(Ic, graythresh(Ic));
> > se = strel('disk', 6);
> > BWc = imclose(BW, se);
> > BWco = imopen(BWc, se);
> > mask = BW & BWco;
> > etime(clock, t0)
> > =======================================
> >
> > my itk code:
> > =======================================
> > // itkTester2.cpp : Defines the entry point for the
> > console application.
> > //
> >
> > #include "stdafx.h"
> >
> > #include "itkImage.h"
> > #include "itkImageFileReader.h"
> > #include "itkImageFileWriter.h"
> > #include "itkBinaryThresholdImageFilter.h"
> > #include <itkBinaryDilateImageFilter.h>
> > #include <itkBinaryErodeImageFilter.h>
> > #include <itkBinaryBallStructuringElement.h>
> > #include <time.h>
> >
> > void itkBinaryThresholdImageFilterTest()
> > {
> >
> > // Use a random image source as input
> > typedef unsigned char PixelType;
> > typedef itk::Image< PixelType, 2 > ImageType;
> > typedef itk::ImageFileReader< ImageType >
> > ReaderType;
> > ReaderType::Pointer source = ReaderType::New();
> > source->SetFileName("d:\\pearbig.png");
> >
> > // Declare the type for the binary threshold
> > binaryThreshold
> > typedef itk::BinaryThresholdImageFilter< ImageType,
> > ImageType > FilterType;
> >
> >
> > // Create a binaryThreshold
> >
> > FilterType::Pointer binaryThreshold =
> > FilterType::New();
> >
> > // Setup ivars
> > PixelType lower = 180;
> > PixelType upper = 255;
> > binaryThreshold->SetUpperThreshold( upper );
> > binaryThreshold->SetLowerThreshold( lower );
> >
> > PixelType inside = 0;
> > PixelType outside = 255;
> > binaryThreshold->SetInsideValue( inside );
> > binaryThreshold->SetOutsideValue( outside );
> >
> > // Connect the input images
> > binaryThreshold->SetInput( source->GetOutput() );
> >
> > // Declare the type for the structuring element
> > typedef itk::BinaryBallStructuringElement<unsigned
> > char, 2>
> > KernelType;
> > // Create the structuring element
> > KernelType ball;
> > KernelType::SizeType ballSize;
> > ballSize[0] = 5;
> > ballSize[1] = 5;
> > ball.SetRadius(ballSize);
> > ball.CreateStructuringElement();
> >
> > // Declare the type for the morphology Filter
> > typedef itk::BinaryDilateImageFilter<ImageType,
> > ImageType, KernelType>
> > BinaryDilateType;
> > typedef itk::BinaryErodeImageFilter<ImageType,
> > ImageType, KernelType>
> > BinaryErodeType;
> >
> > //Close = Erode then Dilate
> > BinaryErodeType::Pointer binaryErode =
> > BinaryErodeType::New();
> > binaryErode->SetInput(binaryThreshold->GetOutput() );
> > binaryErode->SetKernel( ball );
> > binaryErode->SetErodeValue( 255 );
> >
> > BinaryDilateType::Pointer binaryDilate =
> > BinaryDilateType::New();
> > binaryDilate->SetInput(binaryErode->GetOutput() );
> > binaryDilate->SetKernel( ball );
> > binaryDilate->SetDilateValue( 255 );
> >
> > //Open = Dilate then Erode
> > BinaryDilateType::Pointer binaryDilate2 =
> > BinaryDilateType::New();
> > binaryDilate2->SetInput(binaryDilate->GetOutput() );
> > binaryDilate2->SetKernel( ball );
> > binaryDilate2->SetDilateValue( 255 );
> >
> > BinaryErodeType::Pointer binaryErode2 =
> > BinaryErodeType::New();
> > binaryErode2->SetInput(binaryDilate2->GetOutput() );
> > binaryErode2->SetKernel( ball );
> > binaryErode2->SetErodeValue( 255 );
> >
> > typedef itk::ImageFileWriter< ImageType >
> > WriterType;
> > WriterType::Pointer writer = WriterType::New();
> > writer->SetFileName("d:\\pearlite2.png");
> > writer->SetInput (binaryErode2->GetOutput() );
> > writer->Update();
> > }
> >
> >
> > void main(int argc, char* argv[])
> > {
> > clock_t a = clock();
> > itkBinaryThresholdImageFilterTest();
> > clock_t b = clock();
> > printf("time %lf\n", 1.0*(b-a)/CLOCKS_PER_SEC);
> > }
> >
> > ======================================
> >
> > vtk tcl script
> >
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > package require vtk
> >
> > vtkPNGReader reader1
> > reader1 SetFileName d:/pearbig.png
> >
> > vtkImageCast cast
> > cast SetOutputScalarTypeToFloat
> > cast SetInput [reader1 GetOutput]
> >
> > vtkImageThreshold thresh
> > thresh SetInput [cast GetOutput]
> > thresh ThresholdByUpper 180
> > thresh SetInValue 0.0000
> > thresh SetOutValue 255.0000
> > thresh ReleaseDataFlagOff
> >
> > vtkImageOpenClose3D my_close
> > my_close SetInput [thresh GetOutput]
> > my_close SetOpenValue 0.0000
> > my_close SetCloseValue 255.0000
> > my_close SetKernelSize 11 11 1
> > my_close ReleaseDataFlagOff
> >
> > vtkImageOpenClose3D my_open
> > my_open SetInput [my_close GetOutput]
> > my_open SetOpenValue 255.0000
> > my_open SetCloseValue 0.0000
> > my_open SetKernelSize 11 11 1
> > my_open ReleaseDataFlagOff
> >
> > vtkImageToImageStencil imageToStencil
> > imageToStencil SetInput [my_open GetOutput]
> > imageToStencil ThresholdBetween 0 127
> > # silly stuff to increase coverage
> > #imageToStencil SetUpperThreshold [imageToStencil
> > GetUpperThreshold]
> > #imageToStencil SetLowerThreshold [imageToStencil
> > GetLowerThreshold]
> >
> > vtkImageStencil stencil
> > stencil SetInput [reader1 GetOutput]
> > stencil SetBackgroundValue 120
> > stencil ReverseStencilOn
> > stencil SetStencil [imageToStencil GetOutput]
> >
> > vtkPNGWriter writer
> > writer SetInput [ stencil GetOutput ]
> > writer SetFileName d:/pearbig2.png
> > writer Write
> >
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >
> > --- Luis Ibanez <luis.ibanez@kitware.com> ???:>
> >
>
> >>Hi Chen,
> >>
> >>The ITK implementation of morphology operations
> >>also decompose the processing of the boundary
> >>regions. This is done by the SmartNeighborhood
> >>iterator.
> >>
> >>So, the difference in preformance is not due to
> >>boundary processing.
> >>
> >>
> >>
> >>About your speed comparison:
> >>
> >>1) In what platform are you compiling ITK ?
> >>
> >>2) Did you enable the "Release" option in
> >> CMake when configuring ITK ?
> >>
> >> Enabling "Release" will add the flags for
> >> code optimization, given that most of ITK
> >> is templated code, there is a dramatic speed
> >> difference between code compiled for debug
> >> and code compiled for release.
> >>
> >>
> >>
> >>Regards,
> >>
> >>
> >> Luis
> >>
> >>
> >>-----------------------
> >>
> >>Chen Fu wrote:
> >>
>
> >>>Hi!
> >>>I recently compare the morphology operation in
>
> >>
> >>vtk,
> >>
>
> >>>itk and matlab. To my surprise, vtk and itk is
>
> >>
> >>much
> >>
>
> >>>slower than matlab.
> >>>I believe the problem is the boundary processing.
>
> >>
> >>In
> >>
>
> >>>vtk and itk code, every pixel must take 8 compares
>
> >>
> >>to
> >>
>
> >>>confirm whether it is inside the image boundary.
>
> >>
> >>But
> >>
>
> >>>in matlab, the boundary is preprocessed by
>
> >>
> >>extending
> >>
>
> >>>the size of image, so get rid of such compares. I
>
> >>
> >>will
> >>
>
> >>>try to do some modify of itk code to enhance its
> >>>performance, but i am not very clearly how to do
> >>>extend the image in itk's pipeline architecture.
> >>>Maybe somebody can give me some hints?
> >>>
> >>>
> >>>=====
> >>>Remote Scensing Satellite Ground Station
> >>>Chinese Academy of Science
> >>>
>
> >>
> >>
>
> >
> >
> > =====
> > Remote Scensing Satellite Ground Station
> > Chinese Academy of Science
> >
> > _________________________________________________________
>
> _______________________________________________
> Insight-users mailing list
> Insight-users@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-users
>