Commit 7f1259d0 authored by reichenbach's avatar reichenbach

[ADD] a new way to apply functions to valuesets without actually knowing the...

[ADD] a new way to apply functions to valuesets without actually knowing the integral type stored in the valueset
makes for shorter implementations and fewer shared_dynamic_casts
[CHANGE] changed the scalar segmentation module to make use of the new mechanism
parent 6780dce2
......@@ -86,6 +86,16 @@ struct DataType< uint8_t >
static dataType const type = W_DT_UINT8;
};
/**
* Specialization for a specific datatype.
*/
template<>
struct DataType< char >
{
//! the dataType flag
static dataType const type = W_DT_UINT8;
};
/**
* Specialization for a specific datatype.
*/
......
......@@ -246,7 +246,6 @@ public:
}
protected:
/**
* The smallest value in m_data.
*/
......@@ -262,6 +261,16 @@ private:
* Stores the values of type T as simple array which never should be modified.
*/
const std::vector< T > m_data; // WARNING: don't remove constness since &m_data[0] won't work anymore!
/**
* Get a variant reference to this valueset (the reference is stored in the variant).
* \note Use this as a temporary object inside a function or something like that.
* \return var A variant reference.
*/
virtual WValueSetVariant const getVariant() const
{
return WValueSetVariant( this );
}
};
template< typename T > wmath::WVector3D WValueSet< T >::getVector3D( size_t index ) const
......
......@@ -27,9 +27,29 @@
#include <cstddef>
#include <cmath>
#include <boost/variant.hpp>
#include "WDataHandlerEnums.h"
#include "WExportDataHandler.h"
//! forward declaration
template< typename T >
class WValueSet;
//! declare a boost::variant of all possible valuesets
typedef boost::variant< WValueSet< char > const*,
WValueSet< uint8_t > const*,
WValueSet< int8_t > const*,
WValueSet< uint16_t > const*,
WValueSet< int16_t > const*,
WValueSet< uint32_t > const*,
WValueSet< int32_t > const*,
WValueSet< uint64_t > const*,
WValueSet< int64_t > const*,
WValueSet< float > const*,
WValueSet< double > const* > WValueSetVariant;
/**
* Abstract base class to all WValueSets. This class doesn't provide any genericness.
* \ingroup dataHandler
......@@ -118,6 +138,20 @@ public:
*/
virtual double getMaximumValue() const = 0;
/**
* Apply a function object to this valueset.
*
* \tparam Func_T The type of the function object, should be derived from the boost::static_visitor template.
*
* \param func The function object to apply.
* \return The result of the operation.
*/
template< typename Func_T >
typename Func_T::result_type applyFunction( Func_T const& func )
{
return boost::apply_visitor( func, getVariant() );
}
protected:
/**
* The order of the tensors for this ValueSet
......@@ -135,6 +169,15 @@ protected:
const dataType m_dataType;
private:
/**
* Creates a boost::variant reference.
*
* \return var A pointer to a variant reference to the valueset.
*/
virtual WValueSetVariant const getVariant() const
{
return WValueSetVariant();
}
};
#endif // WVALUESETBASE_H
......@@ -25,6 +25,8 @@
#include <string>
#include <vector>
#include <boost/bind.hpp>
#include "../../kernel/WKernel.h"
#include "../../common/WColor.h"
......@@ -89,14 +91,12 @@ void WMScalarSegmentation::properties()
m_algos = boost::shared_ptr< WItemSelection >( new WItemSelection );
m_algos->addItem( "Simple Threshold", "" );
m_algos->addItem( "Watershed", "" );
m_algoType = m_properties->addProperty( "Seg Algo", "Choose a segmentation method.", m_algos->getSelectorFirst(), m_propCondition );
m_propGroups.resize( 1 );
m_propGroups[ 0 ] = m_properties->addPropertyGroup( "Simple Threshold", "" );
m_threshold = m_propGroups[ 0 ]->addProperty( "Threshold", "Threshold value for segmentation.", 0.8, m_propCondition );
m_threshold->setMax( 255.0 );
m_threshold = m_properties->addProperty( "Threshold", "Threshold value for segmentation.", 10.0, m_propCondition );
m_threshold->setMax( 100.0 );
m_threshold->setMin( 0.0 );
WModule::properties();
......@@ -125,9 +125,14 @@ void WMScalarSegmentation::moduleMain()
bool dataChanged = ( m_dataSet != newDataSet );
bool dataValid = ( newDataSet );
if( dataChanged )
if( dataChanged && dataValid )
{
m_dataSet = newDataSet;
WAssert( m_dataSet, "" );
WAssert( m_dataSet->getValueSet(), "" );
WAssert( m_dataSet->getGrid(), "" );
WAssert( m_dataSet->getValueSet()->dimension() == 1, "" );
WAssert( m_dataSet->getValueSet()->order() == 0, "" );
}
//bool propChanged = false;
......@@ -147,11 +152,10 @@ void WMScalarSegmentation::moduleMain()
//}
bool propChanged = m_threshold->changed();
if ( ( dataChanged && dataValid ) || ( propChanged && dataValid ) )
if( m_dataSet && ( dataChanged || propChanged ) )
{
// redo calculation
m_result = doSegmentation( m_dataSet );
doSegmentation();
m_output->updateData( m_result );
}
}
......@@ -162,44 +166,16 @@ void WMScalarSegmentation::activate()
WModule::activate();
}
boost::shared_ptr< WDataSetScalar > WMScalarSegmentation::doSegmentation( boost::shared_ptr< WDataSetScalar > dataSet )
void WMScalarSegmentation::doSegmentation()
{
boost::shared_ptr< WValueSetBase > vs;
switch( m_algoIndex )
{
case 0:
return segmentationSimple( dataSet, m_threshold->get( true ) );
vs = m_dataSet->getValueSet()->applyFunction( SimpleSegmentation( m_threshold->get( true ) ) );
break;
default:
return boost::shared_ptr< WDataSetScalar >();
errorLog() << "Invalid algorithm selected." << std::endl;
}
}
boost::shared_ptr< WDataSetScalar > WMScalarSegmentation::segmentationSimple( boost::shared_ptr< WDataSetScalar > dataSet, double threshold )
{
debugLog() << "Computing!";
WAssert( m_dataSet, "" );
WAssert( m_dataSet->getValueSet(), "" );
WAssert( m_dataSet->getGrid(), "" );
WAssert( m_dataSet->getValueSet()->dimension() == 1, "" );
WAssert( m_dataSet->getValueSet()->order() == 0, "" );
boost::shared_ptr< WValueSetBase > values = boost::shared_dynamic_cast< WValueSetBase >( dataSet->getValueSet() );
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() );
WAssert( values, "" );
WAssert( grid, "" );
std::vector< float > v( grid->size() );
for( std::size_t k = 0; k < grid->size(); ++k )
{
v[ k ] = ( values->getScalarDouble( k ) < threshold ? 0.0f : 255.0f );
}
boost::shared_ptr< WGridRegular3D > resGrid = boost::shared_ptr< WGridRegular3D >(
new WGridRegular3D( *( grid.get() ) ) );
boost::shared_ptr< WValueSet< float > > resValues = boost::shared_ptr< WValueSet< float > >(
new WValueSet< float >( values->order(), values->dimension(), v, W_DT_FLOAT ) );
boost::shared_ptr< WDataSetScalar > result = boost::shared_ptr< WDataSetScalar >(
new WDataSetScalar( resValues, resGrid ) );
return result;
m_result = boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, m_dataSet->getGrid() ) );
}
......@@ -28,6 +28,8 @@
#include <string>
#include <vector>
#include <boost/function.hpp>
#include "../../common/WItemSelection.h"
#include "../../common/WItemSelector.h"
......@@ -110,21 +112,9 @@ private:
/**
* Do a segmentation depending on the current module property values.
*
* \param dataSet A scalar dataSet to perform the segmentation on.
*
* \return the resulting segmented dataset.
*/
boost::shared_ptr< WDataSetScalar > doSegmentation( boost::shared_ptr< WDataSetScalar > dataSet );
/**
* Do a simple threshold value segmentation.
*
* \param dataSet A scalar dataSet to perform the segmentation on.
* \param threshold the threshold value.
*
* \return the resulting segmented dataset.
*/
boost::shared_ptr< WDataSetScalar > segmentationSimple( boost::shared_ptr< WDataSetScalar > dataSet, double threshold );
void doSegmentation();
/**
* An input connector used to get datasets from other modules.
......@@ -156,11 +146,6 @@ private:
*/
std::size_t m_algoIndex;
/**
* List of property groups.
*/
std::vector< WPropGroup > m_propGroups;
/**
* A list of possible segmentation algorithms.
*/
......@@ -174,8 +159,49 @@ private:
/**
* The threshold property for the simple threshold segmentation.
*/
WPropDouble m_threshold;
WPropDouble m_threshold;
//! A function object that implements a simple threshold segmentation.
class SimpleSegmentation : public boost::static_visitor< boost::shared_ptr< WValueSetBase > >
{
public:
/**
* Constructor.
* \param t The threshold for segmentation.
*/
SimpleSegmentation( double t ) // NOLINT
: m_threshold( t )
{
}
/**
* 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* valueset ) const;
private:
//! the threshold
double m_threshold;
};
};
#endif // WMSCALARSEGMENTATION_H
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 ) );
}
return boost::shared_ptr< WValueSet< T > >( new WValueSet< T >( 0, 1, values, DataType< T >::type ) );
}
#endif // WMSCALARSEGMENTATION_H
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