User Documentation
RAVL, Recognition And Vision Library
Ravl - Core - Data Processing - Single Items

Processing single data items

The first issue to be addressed is how to express data flow operations in C++. We could use functions calls to execute the operations in a pipe line, but this quickly becomes unwieldy, and unclear especially if the functions have more than one argument.

results = Normalise(Smooth(Read("")));

A clearer version of this can be written using a simple template function on the >> operator. Processing a single piece of data through a pipe line can be achieved quite easily. The simplest kind of processing can be done with a few templates, the first of which is defined as follows.

template <class InT,class OutT>
OutT operator>>(const InT & in,OutT (*func)(const InT &))
{ return func(in); }

An example of the use of this template follows. The Read(...) function is assumed to return the data we wish to process; this data is processed by the Normalise and Smooth functions and the result of the computation is stored in `results'.

results = Read("") >> Normalise >> Smooth;

To complete the path we can add a template operator to copy the output into a result variable. So we can complete the pipe in a way consistent with the rest of the notation. This may seem unnecessary, but it keeps the syntax consistent with operations that will be introduced in the next section. The definition of the new templated >> operator is given below.

template <class InT,class OutT>
OutT operator>>(const InT &in,OutT &out)
{ return out = in; }

This allows us to write the previous example as follows.

Read("") >> Normalise >> Smooth >> results;

The data flow is now completely left to right. This will be kept true in all the following examples and in the diagrams that will be introduced later. Often we want to setup parameters for a process, or a process has state which is preserved between operations. For this it is more convenient to use a class to represent the processing operation.

To allow a set of templates to be written which will handle these processes automatically it is assumed that each class used for processing data has a method Apply which transforms the input data to the output. To allow full template instantiation on parameters of the pipe operator >> it is easier if all such processes are derived from a single templated base class. In the RAVL system this class is called DPProcessC<InT,OutT> and has an abstract virtual apply method called OutT Apply(const InT &dat).

Again we can add a template function which will call the apply operator in the appropriate place in a stream.

template <class InT,class OutT>
OutT operator>>(const InT &in,const DPProcessC<InT,OutT> & proc)
{ return const_cast<DPProcessC<InT,OutT> &> proc.Apply(in); }

A typical application for this kind of process is convolution, where we wish to specify a kernel.

Read("file") >> ConvolveC(kernel) >> Normalise >> result;

So far the examples given are all semantic sugar. They allow a few operations written in a slightly simpler way, but do not provide any real extra functionality. In RAVL these piping elements are declared within a namespace RavlComposeSingleN.

Normal functions:

 operator >>(const InT &,OutT (*func)(const InT &) ) Pass data through a function.
 operator >>(const InT &,const DPProcessC &) Process a single piece of data.
 operator >>(const DataT &,DataT &) Propergate data to output variable.
 operator >>(DPIPortC &,DataT &) Read a data item from a port.
 operator >>(const DataT &,const DPOPortC &) Output data to an oport.
 operator -=(DPIPortC &,DataT &) Remove an item from an input port.
 operator +=(DPOPortC &,const DataT &) Add data into port.
Maintainer:Charles Galambos, Documentation by CxxDoc: Tue Aug 13 10:00:52 2002