38 #ifndef OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
39 #define OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
41 #include <tbb/parallel_reduce.h>
42 #include <tbb/parallel_for.h>
43 #include <boost/bind.hpp>
44 #include <boost/function.hpp>
45 #include <boost/scoped_ptr.hpp>
46 #include <openvdb/Types.h>
47 #include <openvdb/math/Math.h>
48 #include <openvdb/math/Stencils.h>
49 #include <openvdb/math/Transform.h>
50 #include <openvdb/tree/LeafManager.h>
51 #include <openvdb/util/NullInterrupter.h>
52 #include <openvdb/Grid.h>
61 template<
typename Gr
idT,
typename InterruptT = util::NullInterrupter>
67 typedef typename TreeType::LeafNodeType
LeafType;
76 Filter(GridT& grid, InterruptT* interrupt = NULL) :
77 mGrid(grid), mTask(0), mInterrupter(interrupt)
85 void mean(
int width = 1,
int iterations = 1,
bool serial =
false);
94 void gaussian(
int width = 1,
int iterations = 1,
bool serial =
false);
102 void median(
int width = 1,
int iterations = 1,
bool serial =
false);
107 void offset(
float offset,
bool serial =
false);
115 if (mTask) mTask(const_cast<Filter*>(
this), range);
120 typedef typename boost::function<void (Filter*, const RangeType&)> FuncType;
122 void cook(
bool serial, LeafManagerType& leafs);
124 template <
size_t Axis>
126 Avg(
const GridT& grid,
Int32 w) : acc(grid.tree()), width(w), frac(1/ValueType(2*w+1)) {}
127 ValueType operator()(Coord xyz) {
128 ValueType sum = zeroVal<ValueType>();
130 for (i -= width; i <= j; ++i) sum += acc.getValue(xyz);
133 typename GridT::ConstAccessor acc;
135 const ValueType frac;
139 template <
typename AvgT>
140 void doBox(
const RangeType& r,
Int32 w);
141 void doBoxX(
const RangeType& r,
Int32 w) { this->doBox<Avg<0> >(r,w); }
142 void doBoxZ(
const RangeType& r,
Int32 w) { this->doBox<Avg<1> >(r,w); }
143 void doBoxY(
const RangeType& r,
Int32 w) { this->doBox<Avg<2> >(r,w); }
144 void doMedian(
const RangeType&,
int);
145 void doOffset(
const RangeType&,
float);
151 InterruptT* mInterrupter;
156 template<
typename Gr
idT,
typename InterruptT>
160 if (mInterrupter) mInterrupter->start(
"Applying mean filter");
167 mTask = boost::bind(&Filter::doBoxX, _1, _2, w);
168 this->cook(serial, leafs);
170 mTask = boost::bind(&Filter::doBoxY, _1, _2, w);
171 this->cook(serial, leafs);
173 mTask = boost::bind(&Filter::doBoxZ, _1, _2, w);
174 this->cook(serial, leafs);
177 if (mInterrupter) mInterrupter->end();
180 template<
typename Gr
idT,
typename InterruptT>
184 if (mInterrupter) mInterrupter->start(
"Applying gaussian filter");
190 for (
int i=0; i<iterations; ++i) {
192 mTask = boost::bind(&Filter::doBoxX, _1, _2, w);
193 this->cook(serial, leafs);
195 mTask = boost::bind(&Filter::doBoxY, _1, _2, w);
196 this->cook(serial, leafs);
198 mTask = boost::bind(&Filter::doBoxZ, _1, _2, w);
199 this->cook(serial, leafs);
203 if (mInterrupter) mInterrupter->end();
207 template<
typename Gr
idT,
typename InterruptT>
211 if (mInterrupter) mInterrupter->start(
"Applying median filter");
215 mTask = boost::bind(&Filter::doMedian, _1, _2,
std::max(1, width));
216 for (
int i=0; i<iterations && !this->
wasInterrupted(); ++i) this->cook(serial, leafs);
218 if (mInterrupter) mInterrupter->end();
221 template<
typename Gr
idT,
typename InterruptT>
225 if (mInterrupter) mInterrupter->start(
"Applying offset");
229 mTask = boost::bind(&Filter::doOffset, _1, _2, value);
230 this->cook(serial, leafs);
232 if (mInterrupter) mInterrupter->end();
240 template<
typename Gr
idT,
typename InterruptT>
245 (*this)(leafs.leafRange());
247 tbb::parallel_for(leafs.leafRange(), *
this);
249 leafs.swapLeafBuffer(1, serial);
253 template<
typename Gr
idT,
typename InterruptT>
254 template <
typename AvgT>
256 Filter<GridT, InterruptT>::doBox(
const RangeType& range,
Int32 w)
260 for (
typename RangeType::Iterator lIter=range.begin(); lIter; ++lIter) {
261 BufferType& buffer = lIter.buffer(1);
262 for (
typename LeafType::ValueOnCIter vIter = lIter->cbeginValueOn(); vIter; ++vIter) {
263 buffer.setValue(vIter.pos(), avg(vIter.getCoord()));
269 template<
typename Gr
idT,
typename InterruptT>
271 Filter<GridT, InterruptT>::doMedian(
const RangeType& range,
int width)
274 typename math::DenseStencil<GridType> stencil(mGrid, width);
275 for (
typename RangeType::Iterator lIter=range.begin(); lIter; ++lIter) {
276 BufferType& buffer = lIter.buffer(1);
277 for (
typename LeafType::ValueOnCIter vIter = lIter->cbeginValueOn(); vIter; ++vIter) {
278 stencil.moveTo(vIter);
279 buffer.setValue(vIter.pos(), stencil.median());
285 template<
typename Gr
idT,
typename InterruptT>
287 Filter<GridT, InterruptT>::doOffset(
const RangeType& range,
float floatVal)
289 const ValueType offset =
static_cast<ValueType
>(floatVal);
290 for (
typename RangeType::Iterator leafIter=range.begin(); leafIter; ++leafIter) {
291 for (
typename LeafType::ValueOnIter iter = leafIter->beginValueOn(); iter; ++iter) {
292 iter.setValue(*iter + offset);
297 template<
typename Gr
idT,
typename InterruptT>
302 tbb::task::self().cancel_group_execution();
312 #endif // OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
int32_t Int32
Definition: Types.h:58
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
#define OPENVDB_VERSION_NAME
Definition: version.h:45
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:117
Definition: Exceptions.h:88
Definition: LeafManager.h:122
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
Axis
Definition: Math.h:762
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76