Commit 3bfd90de authored by reichenbach's avatar reichenbach

[ADD] more segmentation algorithms added to WMScalarSegmentation

[FIX] WMSubractScalar does not return any negative values (temporary fix until WMDataTexture3D_2 replaces WMDataTexture3D)
parent 3fd81c0c
......@@ -175,7 +175,6 @@ ENDIF()
IF( ITK_FOUND AND OW_USE_ITK )
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOW_USE_ITK" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOW_USE_ITK" CACHE STRING "" FORCE )
SET( ITK_LIBRARIES "ITKCommon" )
ENDIF( ITK_FOUND AND OW_USE_ITK )
SET( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -DDEBUG -O2" CACHE STRING "" FORCE )
......
......@@ -45,7 +45,7 @@ static WLogger logger;
static bool loggerInitialized = false;
/**
* Test important functionality of WDataHandler class
* Test functionality of WITKConversion class.
*/
class WITKImageConversionTest : public CxxTest::TestSuite
{
......
......@@ -10,8 +10,11 @@ SET( MODULE_NAME "OWmodule_${MODULE_NAME}" ) # prefix all module names w
# Build module lib
ADD_LIBRARY( ${MODULE_NAME} SHARED ${MODULES_SRC} )
TARGET_LINK_LIBRARIES( ${MODULE_NAME} OWkernel )
IF( ITK_FOUND AND OW_USE_ITK )
TARGET_LINK_LIBRARIES( ${MODULE_NAME} OWkernel ${ITK_LIBRARIES})
ELSE()
TARGET_LINK_LIBRARIES( ${MODULE_NAME} OWkernel )
ENDIF()
IF(MSVC_IDE)
SET_TARGET_PROPERTIES( ${MODULE_NAME} PROPERTIES PREFIX "../")
ENDIF(MSVC_IDE)
......
......@@ -90,6 +90,7 @@ void WMScalarSegmentation::properties()
m_algos = boost::shared_ptr< WItemSelection >( new WItemSelection );
m_algos->addItem( "Simple Threshold", "" );
m_algos->addItem( "Watershed", "" );
m_algos->addItem( "Otsu Threshold", "" );
m_algoType = m_properties->addProperty( "Seg Algo", "Choose a segmentation method.", m_algos->getSelectorFirst(), m_propCondition );
......@@ -97,6 +98,10 @@ void WMScalarSegmentation::properties()
m_threshold->setMax( 100.0 );
m_threshold->setMin( 0.0 );
m_level = m_properties->addProperty( "Level", "Watershed level value for segmentation.", 10.0, m_propCondition );
m_level->setMax( 100.0 );
m_level->setMin( 0.0 );
WModule::properties();
}
......@@ -133,24 +138,12 @@ void WMScalarSegmentation::moduleMain()
WAssert( m_dataSet->getValueSet()->order() == 0, "" );
}
//bool propChanged = false;
//if( !m_algoType->changed() )
//{
//WPVGroup::PropertyConstIterator it;
//for( it = m_propGroups[ m_algoIndex ]->begin(); it != m_propGroups[ m_algoIndex ]->end(); ++it )
//{
//propChanged = propChanged || it->changed();
//}
//}
//else
//{
//WItemSelector w = m_algoType.get( true );
//m_algoIndex = w.getItemIndexOfSelected( 0 );
//propChanged = true;
//}
bool propChanged = m_threshold->changed();
if( m_dataSet && ( dataChanged || propChanged ) )
bool algoChanged = m_algoType->changed();
WItemSelector w = m_algoType->get( true );
m_algoIndex = w.getItemIndexOfSelected( 0 );
bool propChanged = m_threshold->changed() || m_level->changed();
if( m_dataSet && ( dataChanged || propChanged || algoChanged ) )
{
// redo calculation
doSegmentation();
......@@ -167,11 +160,22 @@ void WMScalarSegmentation::activate()
void WMScalarSegmentation::doSegmentation()
{
boost::shared_ptr< WValueSetBase > vs;
debugLog() << m_algoIndex;
switch( m_algoIndex )
{
case 0:
vs = m_dataSet->getValueSet()->applyFunction( SimpleSegmentation( m_threshold->get( true ) ) );
break;
#ifdef OW_USE_ITK
case 1:
vs = m_dataSet->getValueSet()->applyFunction( WatershedSegmentation( m_level->get( true ), m_threshold->get( true ), m_dataSet ) );
break;
case 2:
vs = m_dataSet->getValueSet()->applyFunction( OtsuSegmentation( m_dataSet ) );
break;
#endif // OW_USE_ITK
default:
errorLog() << "Invalid algorithm selected." << std::endl;
}
......
......@@ -31,11 +31,26 @@
#include "../../common/WItemSelection.h"
#include "../../common/WItemSelector.h"
#include "../../dataHandler/WITKImageConversion.h"
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
#include "../../kernel/WModuleOutputData.h"
#include "../../dataHandler/WDataSetScalar.h"
#ifdef OW_USE_ITK
#include "itkWatershedImageFilter.h"
#include "itkOtsuThresholdImageFilter.h"
// smoothing filters
#include "itkGradientAnisotropicDiffusionImageFilter.h"
// other
#include "itkCastImageFilter.h"
#include "itkGradientMagnitudeImageFilter.h"
#endif // OW_USE_ITK
/**
* First version of a module that implements 3D-image segmentation algorithms.
*
......@@ -159,6 +174,9 @@ private:
*/
WPropDouble m_threshold;
//! The watershed level.
WPropDouble m_level;
//! A function object that implements a simple threshold segmentation.
class SimpleSegmentation : public boost::static_visitor< boost::shared_ptr< WValueSetBase > >
{
......@@ -186,20 +204,136 @@ private:
//! the threshold
double m_threshold;
};
#ifdef OW_USE_ITK
//!
class WatershedSegmentation : public boost::static_visitor< boost::shared_ptr< WValueSetBase > >
{
public:
/**
* Constructor.
* \param t The threshold for segmentation.
*/
WatershedSegmentation( double level, double t, boost::shared_ptr< WDataSetScalar > ds ) // NOLINT
: m_level( level ),
m_threshold( t ),
m_dataset( ds )
{
}
/**
* Do the segmentation.
*
* \tparam T The integral data type.
* \param valueset The valueset to segment.
* \return A pointer to a new valueset.
*/
template< typename T >
boost::shared_ptr< WValueSetBase > operator() ( WValueSet< T > const* ) const;
private:
//! the level
double m_level;
//! the threshold
double m_threshold;
//! the dataset
boost::shared_ptr< WDataSetScalar > m_dataset;
};
//!
class OtsuSegmentation : public boost::static_visitor< boost::shared_ptr< WValueSetBase > >
{
public:
/**
* Constructor.
* \param t The threshold for segmentation.
*/
OtsuSegmentation( boost::shared_ptr< WDataSetScalar > ds ) // NOLINT
: m_dataset( ds )
{
}
/**
* Do the segmentation.
*
* \tparam T The integral data type.
* \param valueset The valueset to segment.
* \return A pointer to a new valueset.
*/
template< typename T >
boost::shared_ptr< WValueSetBase > operator() ( WValueSet< T > const* v ) const;
private:
//! the dataset
boost::shared_ptr< WDataSetScalar > m_dataset;
};
#endif // OW_USE_ITK
};
template< typename T >
boost::shared_ptr< WValueSetBase > WMScalarSegmentation::SimpleSegmentation::operator() ( WValueSet< T > const* valueset ) const
{
std::vector< T > values( valueset->size() );
for( std::size_t k = 0; k < valueset->size(); ++k )
{
values[ k ] = ( static_cast< double >( valueset->getScalar( k ) ) <
m_threshold * ( valueset->getMaximumValue() - valueset->getMinimumValue() ) / 100.0 + valueset->getMinimumValue()
? static_cast< T >( 0 ) : static_cast< T >( 1 ) );
? static_cast< T >( 0 ) : static_cast< T >( 100 ) );
}
return boost::shared_ptr< WValueSet< T > >( new WValueSet< T >( 0, 1, values, DataType< T >::type ) );
}
#ifdef OW_USE_ITK
template< typename T >
boost::shared_ptr< WValueSetBase > WMScalarSegmentation::WatershedSegmentation::operator() ( WValueSet< T > const* ) const
{
typedef itk::Image< T, 3 > ImgType;
typedef itk::Image< double, 3 > RealType;
typedef itk::Image< uint64_t, 3 > LabelType; // this might be a problem on 32-bit systems
typedef itk::Image< float, 3 > FinalType;
typedef itk::GradientAnisotropicDiffusionImageFilter< ImgType, RealType > SmoothingType;
typedef itk::CastImageFilter< LabelType, FinalType > CastFilter;
typedef itk::GradientMagnitudeImageFilter< RealType, RealType > GradFilter;
typedef itk::WatershedImageFilter< RealType > WaterFilter;
typename ImgType::Pointer img = makeImageFromDataSet< T >( m_dataset );
typename SmoothingType::Pointer sm = SmoothingType::New();
typename CastFilter::Pointer cf = CastFilter::New();
typename GradFilter::Pointer gf = GradFilter::New();
typename WaterFilter::Pointer ws = WaterFilter::New();
sm->SetNumberOfIterations( 10 );
sm->SetTimeStep( 0.0625 );
sm->SetConductanceParameter( 2.0 );
sm->SetInput( img );
gf->SetInput( sm->GetOutput() );
ws->SetInput( gf->GetOutput() );
ws->SetLevel( m_level / 100.0 );
ws->SetThreshold( m_threshold / 100.0 );
cf->SetInput( ws->GetOutput() );
cf->Update();
boost::shared_ptr< WDataSetScalar > res = makeDataSetFromImage< float >( cf->GetOutput() );
return res->getValueSet();
}
template< typename T >
boost::shared_ptr< WValueSetBase > WMScalarSegmentation::OtsuSegmentation::operator() ( WValueSet< T > const* v ) const
{
typedef itk::Image< T, 3 > ImgType;
typedef itk::OtsuThresholdImageFilter< ImgType, ImgType > Otsu;
typename ImgType::Pointer img = makeImageFromDataSet< T >( m_dataset );
typename Otsu::Pointer o = Otsu::New();
o->SetInput( img );
o->SetOutsideValue( v->getMaximumValue() );
o->SetInsideValue( v->getMinimumValue() );
o->Update();
boost::shared_ptr< WDataSetScalar > res = makeDataSetFromImage< T >( o->GetOutput() );
return res->getValueSet();
}
#endif // OW_USE_ITK
#endif // WMSCALARSEGMENTATION_H
......@@ -27,6 +27,7 @@
#include <string>
#include <vector>
#include <algorithm>
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
......@@ -143,7 +144,7 @@ void WMSubtractDataSetScalar::subtractTyped()
std::vector< T > values( m_first->getGrid()->size() );
for( std::size_t k = 0; k < m_first->getGrid()->size(); ++k )
{
values[ k ] = firstValueSet->rawData()[ k ] - secondValueSet->rawData()[ k ];
values[ k ] = std::max( 0, firstValueSet->rawData()[ k ] - secondValueSet->rawData()[ k ] );
}
VSPtr vs( new VS( 0, 1, values, DataType< T >::type ) );
m_result = boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, m_first->getGrid() ) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment