35 #ifndef OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
36 #define OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED
38 #include <tbb/parallel_reduce.h>
39 #include <tbb/parallel_for.h>
40 #include <boost/bind.hpp>
41 #include <boost/function.hpp>
42 #include <boost/scoped_ptr.hpp>
43 #include <openvdb/openvdb.h>
44 #include <openvdb/Types.h>
45 #include <openvdb/math/Math.h>
46 #include <openvdb/math/Stencils.h>
47 #include <openvdb/math/Transform.h>
48 #include <openvdb/tree/LeafManager.h>
49 #include <openvdb/util/NullInterrupter.h>
50 #include <openvdb/Grid.h>
59 template<
typename Gr
idT,
typename InterruptT = util::NullInterrupter>
65 typedef typename TreeType::LeafNodeType
LeafType;
72 explicit Filter(GridT& grid, InterruptT* interrupt = NULL) :
73 mIsMaster(true), mGrid(grid), mTask(0),
79 mIsMaster(false), mGrid(other.mGrid), mTask(other.mTask),
85 if ( mIsMaster )
delete mLeafs;
89 void mean(
int width = 1,
bool serial =
false);
95 void gaussian(
int width = 1,
bool serial =
false);
100 void median(
int width = 1,
bool serial =
false);
103 void offset(
float offset,
bool serial =
false);
110 if (mTask) mTask(const_cast<Filter*>(
this), r);
115 typedef typename boost::function<void (Filter*, const RangeType&)> FuncType;
117 void cook(
bool serial,
bool swapBuffers);
120 void doBoxX(
const RangeType&,
Int32);
121 void doBoxY(
const RangeType&,
Int32);
122 void doBoxZ(
const RangeType&,
Int32);
123 void doMedian(
const RangeType&,
int);
124 void doOffset(
const RangeType&,
float);
125 void startInterrupter(
const char* msg);
126 void endInterrupter();
127 void checkInterrupter();
129 const bool mIsMaster;
133 InterruptT* mInterrupter;
139 template<
typename Gr
idT,
typename InterruptT>
143 this->startInterrupter(
"Applying mean filter");
146 mLeafs->rebuildAuxBuffers(1, serial);
148 mTask = boost::bind(&Filter::doBoxX, _1, _2, width);
149 this->cook(serial,
true);
151 mTask = boost::bind(&Filter::doBoxY, _1, _2, width);
152 this->cook(serial,
true);
154 mTask = boost::bind(&Filter::doBoxZ, _1, _2, width);
155 this->cook(serial,
true);
156 this->endInterrupter();
159 template<
typename Gr
idT,
typename InterruptT>
163 this->startInterrupter(
"Applying gaussian filter");
166 mLeafs->rebuildAuxBuffers(1, serial);
168 for (
int n=0; n<4; ++n) {
169 mTask = boost::bind(&Filter::doBoxX, _1, _2, width);
170 this->cook(serial,
true);
172 mTask = boost::bind(&Filter::doBoxY, _1, _2, width);
173 this->cook(serial,
true);
175 mTask = boost::bind(&Filter::doBoxZ, _1, _2, width);
176 this->cook(serial,
true);
178 this->endInterrupter();
182 template<
typename Gr
idT,
typename InterruptT>
186 this->startInterrupter(
"Applying median filter");
187 mLeafs->rebuildAuxBuffers(1, serial);
188 mTask = boost::bind(&Filter::doMedian, _1, _2,
std::max(1, width));
189 this->cook(serial,
true);
190 this->endInterrupter();
193 template<
typename Gr
idT,
typename InterruptT>
197 this->startInterrupter(
"Applying offset");
198 mLeafs->removeAuxBuffers();
199 mTask = boost::bind(&Filter::doOffset, _1, _2, value);
200 this->cook(serial,
false);
201 this->endInterrupter();
209 template<
typename Gr
idT,
typename InterruptT>
214 (*this)(
mLeafs->getRange());
216 tbb::parallel_for(
mLeafs->getRange(), *
this);
218 if (swapBuffers)
mLeafs->swapLeafBuffer(1, serial);
222 template<
typename Gr
idT,
typename InterruptT>
224 Filter<GridT, InterruptT>::doBoxX(
const RangeType& range,
Int32 w)
226 this->checkInterrupter();
227 const ValueType frac = ValueType(1)/ValueType(2*w+1);
228 typename GridT::ConstAccessor acc = mGrid.getConstAccessor();
229 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
230 const LeafType& leaf =
mLeafs->leaf(n);
231 BufferType& buffer =
mLeafs->getBuffer(n, 1);
232 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
233 ValueType sum = zeroVal<ValueType>();
235 for (
Int32 x = xyz.x()-w, xLast = xyz.x()+w; x <= xLast; ++x) {
236 sum += acc.getValue(xyz.setX(x));
238 buffer.setValue(iter.pos(), sum*frac);
244 template<
typename Gr
idT,
typename InterruptT>
246 Filter<GridT, InterruptT>::doBoxY(
const RangeType& range,
Int32 w)
248 this->checkInterrupter();
249 const ValueType frac = ValueType(1)/ValueType(2*w+1);
250 typename GridT::ConstAccessor acc = mGrid.getConstAccessor();
251 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
252 const LeafType& leaf =
mLeafs->leaf(n);
253 BufferType& buffer =
mLeafs->getBuffer(n, 1);
254 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
255 ValueType sum = zeroVal<ValueType>();
257 for (
Int32 y = xyz.y()-w, yLast = xyz.y()+w; y <= yLast; ++y) {
258 sum += acc.getValue(xyz.setY(y));
260 buffer.setValue(iter.pos(), sum*frac);
266 template<
typename Gr
idT,
typename InterruptT>
268 Filter<GridT, InterruptT>::doBoxZ(
const RangeType& range,
Int32 w)
270 this->checkInterrupter();
271 const ValueType frac = ValueType(1)/ValueType(2*w+1);
272 typename GridT::ConstAccessor acc = mGrid.getConstAccessor();
273 for (
size_t n=range.begin(), nLast = range.end(); n != nLast; ++n) {
274 const LeafType& leaf =
mLeafs->leaf(n);
275 BufferType& buffer =
mLeafs->getBuffer(n, 1);
276 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
277 ValueType sum = zeroVal<ValueType>();
279 for (
Int32 z = xyz.z()-w, zLast = xyz.z()+w; z <= zLast; ++z) {
280 sum += acc.getValue(xyz.setZ(z));
282 buffer.setValue(iter.pos(), sum*frac);
288 template<
typename Gr
idT,
typename InterruptT>
290 Filter<GridT, InterruptT>::doMedian(
const RangeType& range,
int width)
292 this->checkInterrupter();
293 typename math::DenseStencil<GridType> stencil(mGrid, width);
294 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
295 const LeafType& leaf =
mLeafs->leaf(n);
296 BufferType& buffer =
mLeafs->getBuffer(n, 1);
297 for (
typename LeafType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter) {
298 stencil.moveTo(iter);
299 buffer.setValue(iter.pos(), stencil.median());
305 template<
typename Gr
idT,
typename InterruptT>
307 Filter<GridT, InterruptT>::doOffset(
const RangeType& range,
float floatVal)
309 const ValueType value =
static_cast<ValueType
>(floatVal);
310 for (
size_t n=range.begin(), e=range.end(); n != e; ++n)
mLeafs->leaf(n).addValue(value);
313 template<
typename Gr
idT,
typename InterruptT>
315 Filter<GridT, InterruptT>::startInterrupter(
const char* msg)
317 if (mInterrupter) mInterrupter->start(msg);
320 template<
typename Gr
idT,
typename InterruptT>
322 Filter<GridT, InterruptT>::endInterrupter()
324 if (mInterrupter) mInterrupter->end();
327 template<
typename Gr
idT,
typename InterruptT>
329 Filter<GridT, InterruptT>::checkInterrupter()
338 #endif // OPENVDB_TOOLS_FILTER_HAS_BEEN_INCLUDED