39 #ifndef OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED 40 #define OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED 42 #include <tbb/parallel_for.h> 43 #include <boost/bind.hpp> 44 #include <boost/function.hpp> 45 #include <boost/type_traits/is_floating_point.hpp> 63 template<
typename GridT,
64 typename MaskT =
typename GridT::template ValueConverter<float>::Type,
65 typename InterruptT = util::NullInterrupter>
72 typedef typename TreeType::LeafNodeType
LeafType;
78 BOOST_STATIC_ASSERT(boost::is_floating_point<AlphaType>::value);
83 Filter(GridT& grid, InterruptT* interrupt = NULL)
86 , mInterrupter(interrupt)
101 , mInterrupter(other.mInterrupter)
103 , mGrainSize(other.mGrainSize)
104 , mMinMask(other.mMinMask)
105 , mMaxMask(other.mMaxMask)
106 , mInvertMask(other.mInvertMask)
146 void mean(
int width = 1,
int iterations = 1,
const MaskType* mask = NULL);
155 void gaussian(
int width = 1,
int iterations = 1,
const MaskType* mask = NULL);
163 void median(
int width = 1,
int iterations = 1,
const MaskType* mask = NULL);
168 void offset(ValueType offset,
const MaskType* mask = NULL);
176 if (mTask) mTask(const_cast<Filter*>(
this), range);
181 typedef typename TreeType::LeafNodeType LeafT;
182 typedef typename LeafT::ValueOnIter VoxelIterT;
183 typedef typename LeafT::ValueOnCIter VoxelCIterT;
185 typedef typename RangeType::Iterator LeafIterT;
188 void cook(LeafManagerType& leafs);
190 template<
size_t Axis>
192 Avg(
const GridT* grid,
Int32 w): acc(grid->tree()), width(w), frac(1.f/float(2*w+1)) {}
193 inline ValueType operator()(
Coord xyz);
194 typename GridT::ConstAccessor acc;
200 template <
typename AvgT>
201 void doBox(
const RangeType& r,
Int32 w);
202 void doBoxX(
const RangeType& r,
Int32 w) { this->doBox<Avg<0> >(r,w); }
203 void doBoxZ(
const RangeType& r,
Int32 w) { this->doBox<Avg<1> >(r,w); }
204 void doBoxY(
const RangeType& r,
Int32 w) { this->doBox<Avg<2> >(r,w); }
205 void doMedian(
const RangeType&,
int);
206 void doOffset(
const RangeType&, ValueType);
211 typename boost::function<void (Filter*, const RangeType&)> mTask;
212 InterruptT* mInterrupter;
213 const MaskType* mMask;
215 AlphaType mMinMask, mMaxMask;
223 namespace filter_internal {
225 template<
typename T>
static inline void accum(T& sum, T addend) { sum += addend; }
227 inline void accum(
bool& sum,
bool addend) { sum = sum || addend; }
231 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
232 template<
size_t Axis>
233 inline typename GridT::ValueType
234 Filter<GridT, MaskT, InterruptT>::Avg<Axis>::operator()(
Coord xyz)
236 ValueType sum = zeroVal<ValueType>();
239 return static_cast<ValueType
>(sum * frac);
246 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
252 if (mInterrupter) mInterrupter->start(
"Applying mean filter");
259 mTask = boost::bind(&Filter::doBoxX, _1, _2, w);
262 mTask = boost::bind(&Filter::doBoxY, _1, _2, w);
265 mTask = boost::bind(&Filter::doBoxZ, _1, _2, w);
269 if (mInterrupter) mInterrupter->end();
273 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
279 if (mInterrupter) mInterrupter->start(
"Applying Gaussian filter");
285 for (
int i=0;
i<iterations; ++
i) {
287 mTask = boost::bind(&Filter::doBoxX, _1, _2, w);
290 mTask = boost::bind(&Filter::doBoxY, _1, _2, w);
293 mTask = boost::bind(&Filter::doBoxZ, _1, _2, w);
298 if (mInterrupter) mInterrupter->end();
302 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
308 if (mInterrupter) mInterrupter->start(
"Applying median filter");
312 mTask = boost::bind(&Filter::doMedian, _1, _2,
std::max(1, width));
315 if (mInterrupter) mInterrupter->end();
319 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
325 if (mInterrupter) mInterrupter->start(
"Applying offset");
329 mTask = boost::bind(&Filter::doOffset, _1, _2, value);
332 if (mInterrupter) mInterrupter->end();
341 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
346 tbb::parallel_for(leafs.leafRange(mGrainSize), *
this);
348 (*this)(leafs.leafRange());
350 leafs.swapLeafBuffer(1, mGrainSize==0);
355 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
356 template <
typename AvgT>
358 Filter<GridT, MaskT, InterruptT>::doBox(
const RangeType& range,
Int32 w)
363 typename AlphaMaskT::FloatType a, b;
364 AlphaMaskT alpha(*mGrid, *mMask, mMinMask, mMaxMask, mInvertMask);
365 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
366 BufferT& buffer = leafIter.buffer(1);
367 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
368 const Coord xyz = iter.getCoord();
369 if (alpha(xyz, a, b)) {
370 buffer.setValue(iter.pos(), ValueType(b*(*iter) + a*avg(xyz)));
375 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
376 BufferT& buffer = leafIter.buffer(1);
377 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
378 buffer.setValue(iter.pos(), avg(iter.getCoord()));
386 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
388 Filter<GridT, MaskT, InterruptT>::doMedian(
const RangeType& range,
int width)
391 typename math::DenseStencil<GridType> stencil(*mGrid, width);
393 typename AlphaMaskT::FloatType a, b;
394 AlphaMaskT alpha(*mGrid, *mMask, mMinMask, mMaxMask, mInvertMask);
395 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
396 BufferT& buffer = leafIter.buffer(1);
397 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
398 if (alpha(iter.getCoord(), a, b)) {
399 stencil.moveTo(iter);
400 buffer.setValue(iter.pos(), ValueType(b*(*iter) + a*stencil.median()));
405 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
406 BufferT& buffer = leafIter.buffer(1);
407 for (VoxelCIterT iter = leafIter->cbeginValueOn(); iter; ++iter) {
408 stencil.moveTo(iter);
409 buffer.setValue(iter.pos(), stencil.median());
417 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
419 Filter<GridT, MaskT, InterruptT>::doOffset(
const RangeType& range, ValueType offset)
423 typename AlphaMaskT::FloatType a, b;
424 AlphaMaskT alpha(*mGrid, *mMask, mMinMask, mMaxMask, mInvertMask);
425 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
426 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
427 if (alpha(iter.getCoord(), a, b)) iter.setValue(ValueType(*iter + a*offset));
431 for (LeafIterT leafIter=range.begin(); leafIter; ++leafIter) {
432 for (VoxelIterT iter = leafIter->beginValueOn(); iter; ++iter) {
433 iter.setValue(*iter + offset);
440 template<
typename Gr
idT,
typename MaskT,
typename InterruptT>
445 tbb::task::self().cancel_group_execution();
455 #endif // OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
Definition: LeafManager.h:127
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
#define OPENVDB_VERSION_NAME
Definition: version.h:43
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:121
Definition: Exceptions.h:39
Definition: Exceptions.h:92
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
int32_t Int32
Definition: Types.h:59
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Axis
Definition: Math.h:852
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...