/* -*- mona-c++ -*-
* Copyright (c) Leipzig, Madrid 2004 - 2008
* Max-Planck-Institute for Human Cognitive and Brain Science
* Max-Planck-Institute for Evolutionary Anthropology
* BIT, ETSI Telecomunicacion, UPM
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
// $Id: filter.hh 754 2005-11-25 12:09:56Z write1 $
/*! \brief Declaration of a general filter class.
Decalration of a general filter class.
\todo yet only a gaussian convolution is implemnted ... need to be heavily extended!
\par Example:
This example shows the typical use of the class:
\code
TODO: include a code snipped here
\endcode
\file filter.hh
\author Gert Wollny <wollny@cbs.mpg.de>
*/
#ifndef __MONA_FILTER_HH
#define __MONA_FILTER_HH 1
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
# pragma interface
#include <cstdio>
#include <vector>
// MONA specific
#include <libmona/monaConfig.hh>
#include <libmona/RefBase.hh>
namespace mona {
class T1DFilterKernel: public CRefCountedBase {
protected:
typedef std::vector<float> vec_mask;
T1DFilterKernel(int fsize);
public:
typedef vec_mask::const_iterator const_iterator;
/// returns a constant iterator at the begin if the filter kernel
const_iterator begin()const;
/// returns a constant iterator at the end if the filter kernel
const_iterator end()const;
/// returns the filter with definition parameter
const int get_fsize() const;
/// returns the width of the kernel
const int get_size() const;
float& operator[](int i) {
return m_mask[i];
}
const float operator[](int i)const {
return m_mask[i];
}
private:
int m_fsize;
vec_mask m_mask;
};
/** Class for a one-dimensional Gaussian convolution filter kernel. */
class T1DGaussFilterKernel: public T1DFilterKernel {
public:
/** contructor creates a kernel with the width = 2 * fsize +1
\param fsize is the filter with parameter */
T1DGaussFilterKernel(int fsize);
};
/** a class to execute a folding with a given filter kernel */
template <class T>
class T1DConvolutionFilter {
T1DFilterKernel *m_kernel;
public:
/** Conststructor creates a filter object from a given kernel
\param k the kernel to be used
*/
T1DConvolutionFilter(T1DFilterKernel *k);
/**
release the kernel
*/
~T1DConvolutionFilter();
/** filter a one-dimensional field with the filter object in place.
\param data is a vector of the given data row
*/
void filter_inplace(std::vector<T>& data) const;
struct TAccumulate {
typedef double type;
};
};
/**
Filter a one-dimensional data field with a Gaussian filter
\param data input data field, will be overwritten.
\param fsize filter width parameter -> width = 2*fsize +1
*/
template <class T>
void gauss_1d(std::vector<T>& data, int fsize);
/**
Filter a two-dimensional data field with a Gaussian filter
\param Data input data field, will be overwritten.
Data field class must provide \a get_size returning a C2DBounds with the size of the field,
and functions get_data_line_x, get_data_line_y, put_data_line_x, and put_data_line_y.
\param xFilterSize filter width parameter in x-direction
\param yFilterSize filter width parameter in y-direction
*/
template <class T2DDatafield>
void gauss_2d(T2DDatafield *Data,int xFilterSize, int yFilterSize);
/**
Filter a three-dimensional data field with a Gaussian filter
\param Data input data field, will be overwritten.
Data field class must provide \a get_size returning a C3DBounds with the size of the field,
and functions get_data_line_x, get_data_line_y, get_data_line_z,
put_data_line_x, put_data_line_y, and put_data_line_z.
\param xFilterSize filter width parameter in x-direction
\param yFilterSize filter width parameter in y-direction
\param zFilterSize filter width parameter in z-direction
*/
template <class T3DDatafield>
void gauss_3d(T3DDatafield *Data, int xFilterSize,
int yFilterSize, int zFilterSize);
/*
** Filters a 3DDataset with a Gaussian Filter of Size
** (2*xFilterSize+1) x (2*yFilterSize+1) x (2*zFilterSize+1)
**
**
*/
// Implementation part
// should go to lib/filter,cc, but g++ does not understand export
template <class T>
T1DConvolutionFilter<T>::T1DConvolutionFilter(T1DFilterKernel *k):
m_kernel(k)
{
m_kernel->add_ref();
}
template <class T>
T1DConvolutionFilter<T>::~T1DConvolutionFilter()
{
m_kernel->release();
}
template <class T>
void T1DConvolutionFilter<T>::filter_inplace(std::vector<T>& data) const
{
typedef std::vector<T> vec_t;
vec_t tmp(data);
T1DFilterKernel::const_iterator ek = m_kernel->end();
typename vec_t::iterator trgt = data.begin();
int pos = data.size();
// filter at left boundary
for (int i = 0; i < m_kernel->get_fsize(); ++i, --pos, ++trgt) {
typename TAccumulate::type ht = 0.0;
typename TAccumulate::type hw = 0.0;
T1DFilterKernel::const_iterator ik = m_kernel->begin();
typename vec_t::const_iterator src = tmp.begin();
advance(ik, m_kernel->get_fsize() - i);
while (ik != ek){
hw += *ik;
ht += *src++ * *ik++;
}
*trgt = T(ht / hw);
}
// filter inside
typename vec_t::iterator start = tmp.begin();
while (pos-- > m_kernel->get_fsize()) {
T1DFilterKernel::const_iterator ik = m_kernel->begin();
typename vec_t::iterator help = start;
typename TAccumulate::type ht = 0.0;
while (ik != ek){
ht += *ik++ * *help++;
}
*trgt = (T)ht;
++trgt;
++start;
}
// filter at right boundary
for (int i = 0; i < m_kernel->get_fsize(); ++i, --pos, ++trgt) {
T1DFilterKernel::const_iterator ik = m_kernel->begin();
ek = ik;
advance(ek, 2 * m_kernel->get_fsize() - i);
typename vec_t::const_iterator src = start;
typename TAccumulate::type ht = 0.0;
typename TAccumulate::type hw = 0.0;
while (ik != ek){
hw += *ik;
ht += *src++ * *ik++;
}
*trgt = T(ht / hw);
++start;
}
}
template <class T>
void gauss_1d(std::vector<T>& data, int fsize)
{
if (fsize)
T1DConvolutionFilter<T>(new T1DGaussFilterKernel(fsize)).filter_inplace(data);
}
template <class T2DDatafield>
void gauss_2d(T2DDatafield *Data,int xFilterSize, int yFilterSize)
{
typedef typename T2DDatafield::value_type value_type;
typedef std::vector<value_type> invec_t;
int cachXSize = Data->get_size().x;
int cachYSize = Data->get_size().y;
if (xFilterSize) {
T1DConvolutionFilter<value_type> Filter(new T1DGaussFilterKernel(xFilterSize));
invec_t buffer(cachXSize);
for (int y = 0; y < cachYSize; y++) {
Data->get_data_line_x(y,buffer);
Filter.filter_inplace(buffer);
Data->put_data_line_x(y,buffer);
}
}
if (yFilterSize) {
T1DConvolutionFilter<value_type> Filter(new T1DGaussFilterKernel(yFilterSize));
invec_t buffer(cachYSize);
for (int x = 0; x < cachXSize; x++) {
Data->get_data_line_y(x,buffer);
Filter.filter_inplace(buffer);
Data->put_data_line_y(x,buffer);
}
}
}
template <class T3DDatafield>
void gauss_3d(T3DDatafield *Data,int xFilterSize,
int yFilterSize, int zFilterSize)
{
typedef typename T3DDatafield::value_type value_type;
typedef std::vector<value_type> invec_t;
int cachXSize = Data->get_size().x;
int cachYSize = Data->get_size().y;
int cachZSize = Data->get_size().z;
if (xFilterSize > 0) {
T1DConvolutionFilter<value_type> XFilter(new T1DGaussFilterKernel(xFilterSize));
invec_t buffer(cachXSize);
for (int z = 0; z < cachZSize; z++){
for (int y = 0; y < cachYSize; y++) {
Data->get_data_line_x(y,z,buffer);
XFilter.filter_inplace(buffer);
Data->put_data_line_x(y,z,buffer);
}
}
}
if (yFilterSize > 0 ) {
T1DConvolutionFilter<value_type> YFilter(new T1DGaussFilterKernel(yFilterSize));
invec_t buffer(cachYSize);
for (int z = 0; z < cachZSize; z++){
for (int x = 0; x < cachXSize; x++) {
Data->get_data_line_y(x,z,buffer);
YFilter.filter_inplace(buffer);
Data->put_data_line_y(x,z,buffer);
}
}
}
if (zFilterSize > 0) {
T1DConvolutionFilter<value_type> ZFilter(new T1DGaussFilterKernel(zFilterSize));
invec_t buffer(cachZSize);
for (int y = 0; y < cachYSize; y++){
for (int x = 0; x < cachXSize; x++) {
Data->get_data_line_z(x,y,buffer);
ZFilter.filter_inplace(buffer);
Data->put_data_line_z(x,y,buffer);
}
}
}
}
} // namespace mona
#endif
/* CVS LOG
$Log$
Revision 1.8 2005/06/29 13:22:23 wollny
switch to version 0.7
Revision 1.1.1.1 2005/03/17 13:44:20 gerddie
initial import
Revision 1.7 2004/08/25 09:08:31 wollny
added an emacs style comment to all source files
Revision 1.6 2004/08/24 15:39:51 wollny
use iterators to get/put lines
Revision 1.5 2004/06/21 13:45:47 wollny
filter with proper non-periodic bounds handling
Revision 1.4 2004/06/09 15:35:58 wollny
minor twaks to remove some warnings
Revision 1.3 2004/06/03 09:57:32 wollny
Changed (hopefully) all instancable class names to Cxxxxx
Revision 1.2 2004/02/12 14:00:25 tittge
Major addaptions from libmia0
Revision 1.1.1.1 2004/02/11 18:18:05 tittge
start project
*/