template<dip::uint N,
typename TPI,
typename F>
VariadicScanLineFilter class
An implementation of the ScanLinefilter for N input images and 1 output image.
Contents
- Reference
Here, all buffers are of the same data type, and the scalar operation applied to each sample is the lambda function of type F, passed to the constructor. All input and output images must have the same number of tensor elements, and in the same order.
When N
= 1, the resulting object can be passed to the dip::Framework::ScanMonadic
function. When N
= 2,
you can use the dip::Framework::ScanDyadic
function. For any other N
, or when dip::Framework::ScanDyadic
does not do the right thing, use dip::Framework::Scan
.
The following example shows how to make a dyadic operator that performs computations in sfloat
and generates
an output image of that same type.
dip::Image lhs = ...; dip::Image rhs = ...; dip::Image out; dip::dfloat offset = 40; auto sampleOperator = [ = ]( std::array< dip::sfloat const*, 2 > its ) { return ( *its[ 0 ] * 100 ) / ( *its[ 1 ] * 10 ) + offset; }; dip::Framework::VariadicScanLineFilter< 2, dip::sfloat, decltype( sampleOperator ) > scanLineFilter( sampleOperator ); dip::Framework::ScanDyadic( lhs, rhs, out, dip::DT_SFLOAT, dip::DT_SFLOAT, scanLineFilter );
sampleOperator
is a lambda function, which captures offset
by value (note that capturing by reference will
slow down the execution significantly). It has a single input argument, a std::array
of 2 float pointers. The
first pointer will point at a sample in the lhs
input image, and the second to the corresponding sample in the
rhs
input image. The return value of the lambda will be assigned to the corresponding sample in the output image.
Note that to access the sample values, you need to use the syntax *its[ 0 ]
, where the 0
is the index into
the array, yielding a pointer, which is dereferenced by the *
operator to access the sample value.
To use the VariadicScanLineFilter
with dynamic data type dispatch, it is necessary to use an auxiliary function.
Such an auxiliary function also simplifies the use of the class template:
template< typename TPI, typename F > std::unique_ptr< dip::Framework::ScanLineFilter > NewFilter( F func ) { return static_cast< std::unique_ptr< dip::Framework::ScanLineFilter >>( new dip::Framework::VariadicScanLineFilter< 1, TPI, F >( func )); } // ... dip::Image in = ...; dip::Image out; dip::DataType dt = in.DataType(); std::unique_ptr< dip::Framework::ScanLineFilter > scanLineFilter; DIP_OVL_CALL_ASSIGN_REAL( scanLineFilter, NewFilter, ( [ = ]( auto its ) { return ( std::cos( *its[ 0 ] ) * 100 ) + offset; } ), dt ); dip::Framework::ScanMonadic( in, out, dt, dt, in.TensorElements(), *scanLineFilter, dip::Framework::ScanOption::TensorAsSpatialDim );
Notice in this case we used a generic lambda, i.e. its input parameter has type auto
. It will be compiled
differently for each allowed data type. The function template NewFilter
that we defined specifies the N
in
the VariadicScanLineFilter
template, and helps pass on the type of the lambda, which is automatically determined
by the compiler and filled out. That is, the function can be called as NewFilter< dip::sfloat >( sampleOperator )
.
The object is allocated in free memory, and its lifetime is managed by std::unique_ptr
, meaning that there is
no need to explicitly delete the object. Next, we use the DIP_OVL_CALL_ASSIGN_REAL
macro to call different
instantiations of our function, depending on the data type dt
, which we determine dynamically from the input
image. The output is captured in a variable and passed to the scan function.
For values of N
from 1 to 4 there are pre-defined functions just like the NewFilter
function above:
dip::Framework::NewMonadicScanLineFilter
, dip::Framework::NewDyadicScanLineFilter
,
dip::Framework::NewTriadicScanLineFilter
, dip::Framework::NewTetradicScanLineFilter
.
These functions take an optional second input argument cost
, which specifies the cost in cycles to execute
a single call of func
. This cost is used to determine if it’s worthwhile to parallelize the operation, see
Multithreading.
Base classes
-
class dip::
Framework:: ScanLineFilter abstract - Prototype line filter for
dip::Framework::Scan
.