37#ifndef VIGRA_MULTI_BLOCKWISE_HXX
38#define VIGRA_MULTI_BLOCKWISE_HXX
42#include "multi_blocking.hxx"
43#include "multi_convolution.hxx"
44#include "multi_tensorutilities.hxx"
45#include "threadpool.hxx"
46#include "array_vector.hxx"
55:
public ParallelOptions
77 Shape readBlockShape()
const
91 if(blockShape_.size() > 1)
93 vigra_precondition(blockShape_.size() == (
size_t)N,
94 "BlockwiseOptions::getBlockShapeN(): dimension mismatch between N and stored block shape.");
97 else if(blockShape_.size() == 1)
103 return detail::ChunkShape<N>::defaultShape();
126 template <
class T,
int N>
145 void setNumThreads(
const int n)
159template<
unsigned int N>
160class BlockwiseConvolutionOptions
161:
public BlockwiseOptions
162,
public ConvolutionOptions<N>{
164 BlockwiseConvolutionOptions()
165 : BlockwiseOptions(),
166 ConvolutionOptions<N>()
180 class T_IN,
class ST_IN,
181 class T_OUT,
class ST_OUT,
182 class FILTER_FUNCTOR,
185 void blockwiseCallerNoRoiApi(
188 FILTER_FUNCTOR & functor,
190 const typename vigra::MultiBlocking<DIM, C>::Shape & borderWidth,
194 typedef typename MultiBlocking<DIM, C>::BlockWithBorder BlockWithBorder;
196 auto beginIter = blocking.blockWithBorderBegin(borderWidth);
197 auto endIter = blocking.blockWithBorderEnd(borderWidth);
201 [&](
const int ,
const BlockWithBorder bwb)
204 vigra::MultiArrayView<DIM, T_IN, ST_IN> sourceSub = source.subarray(bwb.border().begin(),
207 vigra::MultiArray<DIM, T_OUT> destSub(sourceSub.shape());
209 functor(sourceSub, destSub);
211 vigra::MultiArrayView<DIM, T_OUT, ST_OUT> destSubCore = destSub.subarray(bwb.localCore().begin(),
212 bwb.localCore().end());
214 dest.subarray(bwb.core().begin()-blocking.roiBegin(),
215 bwb.core().end() -blocking.roiBegin() ) = destSubCore;
229 class T_IN,
class ST_IN,
230 class T_OUT,
class ST_OUT,
231 class FILTER_FUNCTOR,
234 void blockwiseCaller(
237 FILTER_FUNCTOR & functor,
239 const typename vigra::MultiBlocking<DIM, C>::Shape & borderWidth,
240 const BlockwiseConvolutionOptions<DIM> & options
243 typedef typename MultiBlocking<DIM, C>::BlockWithBorder BlockWithBorder;
245 typedef typename MultiBlocking<DIM, C>::Block Block;
248 auto beginIter = blocking.blockWithBorderBegin(borderWidth);
249 auto endIter = blocking.blockWithBorderEnd(borderWidth);
253 [&](
const int ,
const BlockWithBorder bwb)
256 vigra::MultiArrayView<DIM, T_IN, ST_IN> sourceSub = source.subarray(bwb.border().begin(),
259 vigra::MultiArrayView<DIM, T_OUT, ST_OUT> destCore = dest.subarray(bwb.core().begin(),
261 const Block localCore = bwb.localCore();
263 functor(sourceSub, destCore, localCore.begin(), localCore.end());
271 #define CONVOLUTION_FUNCTOR(FUNCTOR_NAME, FUNCTION_NAME) \
272 template<unsigned int DIM> \
273 class FUNCTOR_NAME{ \
275 typedef ConvolutionOptions<DIM> ConvOpt; \
276 FUNCTOR_NAME(const ConvOpt & convOpt) \
277 : sharedOpt_(convOpt){} \
278 template<class S, class D> \
279 void operator()(const S & s, D & d)const{ \
280 FUNCTION_NAME(s, d, sharedOpt_); \
282 template<class S, class D,class SHAPE> \
283 void operator()(const S & s, D & d, const SHAPE & roiBegin, const SHAPE & roiEnd){ \
284 ConvOpt localOpt(sharedOpt_); \
285 localOpt.subarray(roiBegin, roiEnd); \
286 FUNCTION_NAME(s, d, localOpt); \
289 ConvOpt sharedOpt_; \
302 #undef CONVOLUTION_FUNCTOR
304 template<
unsigned int DIM>
305 class HessianOfGaussianEigenvaluesFunctor{
307 typedef ConvolutionOptions<DIM> ConvOpt;
308 HessianOfGaussianEigenvaluesFunctor(
const ConvOpt & convOpt)
309 : sharedOpt_(convOpt){}
310 template<
class S,
class D>
311 void operator()(
const S & s, D & d)
const{
312 typedef typename vigra::NumericTraits<typename S::value_type>::RealPromote RealType;
313 vigra::MultiArray<DIM, TinyVector<RealType, int(DIM*(DIM+1)/2)> > hessianOfGaussianRes(d.shape());
317 template<
class S,
class D,
class SHAPE>
318 void operator()(
const S & s, D & d,
const SHAPE & roiBegin,
const SHAPE & roiEnd){
319 typedef typename vigra::NumericTraits<typename S::value_type>::RealPromote RealType;
320 vigra::MultiArray<DIM, TinyVector<RealType, int(DIM*(DIM+1)/2)> > hessianOfGaussianRes(roiEnd-roiBegin);
321 ConvOpt localOpt(sharedOpt_);
322 localOpt.subarray(roiBegin, roiEnd);
330 template<
unsigned int DIM,
unsigned int EV>
331 class HessianOfGaussianSelectedEigenvalueFunctor{
333 typedef ConvolutionOptions<DIM> ConvOpt;
334 HessianOfGaussianSelectedEigenvalueFunctor(
const ConvOpt & convOpt)
335 : sharedOpt_(convOpt){}
336 template<
class S,
class D>
337 void operator()(
const S & s, D & d)
const{
338 typedef typename vigra::NumericTraits<typename S::value_type>::RealPromote RealType;
341 vigra::MultiArray<DIM, TinyVector<RealType, int(DIM*(DIM+1)/2)> > hessianOfGaussianRes(s.shape());
344 vigra::MultiArray<DIM, TinyVector<RealType, DIM > > allEigenvalues(s.shape());
347 d = allEigenvalues.bindElementChannel(EV);
349 template<
class S,
class D,
class SHAPE>
350 void operator()(
const S & s, D & d,
const SHAPE & roiBegin,
const SHAPE & roiEnd){
352 typedef typename vigra::NumericTraits<typename S::value_type>::RealPromote RealType;
355 vigra::MultiArray<DIM, TinyVector<RealType, int(DIM*(DIM+1)/2)> > hessianOfGaussianRes(roiEnd-roiBegin);
356 ConvOpt localOpt(sharedOpt_);
357 localOpt.subarray(roiBegin, roiEnd);
360 vigra::MultiArray<DIM, TinyVector<RealType, DIM > > allEigenvalues(roiEnd-roiBegin);
363 d = allEigenvalues.bindElementChannel(EV);
370 template<
unsigned int DIM>
371 class HessianOfGaussianFirstEigenvalueFunctor
372 :
public HessianOfGaussianSelectedEigenvalueFunctor<DIM, 0>{
374 typedef ConvolutionOptions<DIM> ConvOpt;
375 HessianOfGaussianFirstEigenvalueFunctor(
const ConvOpt & convOpt)
376 : HessianOfGaussianSelectedEigenvalueFunctor<DIM, 0>(convOpt){}
379 template<
unsigned int DIM>
380 class HessianOfGaussianLastEigenvalueFunctor
381 :
public HessianOfGaussianSelectedEigenvalueFunctor<DIM, DIM-1>{
383 typedef ConvolutionOptions<DIM> ConvOpt;
384 HessianOfGaussianLastEigenvalueFunctor(
const ConvOpt & convOpt)
385 : HessianOfGaussianSelectedEigenvalueFunctor<DIM, DIM-1>(convOpt){}
395 template<
unsigned int N>
396 vigra::TinyVector< vigra::MultiArrayIndex, N > getBorder(
397 const BlockwiseConvolutionOptions<N> & opt,
399 const bool usesOuterScale =
false
401 vigra::TinyVector< vigra::MultiArrayIndex, N > res(vigra::SkipInitialization);
403 if(opt.getFilterWindowSize()<=0.00001){
404 for(
size_t d=0; d<N; ++d){
405 double stdDev = opt.getStdDev()[d];
407 stdDev += opt.getOuterScale()[d];
408 res[d] =
static_cast<MultiArrayIndex>(3.0 * stdDev + 0.5*
static_cast<double>(order)+0.5);
412 throw std::runtime_error(
"blockwise filters do not allow a user defined FilterWindowSize");
419#define VIGRA_BLOCKWISE(FUNCTOR, FUNCTION, ORDER, USES_OUTER_SCALE) \
420template <unsigned int N, class T1, class S1, class T2, class S2> \
422 MultiArrayView<N, T1, S1> const & source, \
423 MultiArrayView<N, T2, S2> dest, \
424 BlockwiseConvolutionOptions<N> const & options \
427 typedef MultiBlocking<N, vigra::MultiArrayIndex> Blocking; \
428 typedef typename Blocking::Shape Shape; \
429 const Shape border = blockwise::getBorder(options, ORDER, USES_OUTER_SCALE); \
430 BlockwiseConvolutionOptions<N> subOptions(options); \
431 subOptions.subarray(Shape(0), Shape(0)); \
432 const Blocking blocking(source.shape(), options.template getBlockShapeN<N>()); \
433 blockwise::FUNCTOR<N> f(subOptions); \
434 blockwise::blockwiseCaller(source, dest, f, blocking, border, options); \
442VIGRA_BLOCKWISE(HessianOfGaussianEigenvaluesFunctor, hessianOfGaussianEigenvaluesMultiArray, 2,
false );
443VIGRA_BLOCKWISE(HessianOfGaussianFirstEigenvalueFunctor, hessianOfGaussianFirstEigenvalueMultiArray, 2,
false );
444VIGRA_BLOCKWISE(HessianOfGaussianLastEigenvalueFunctor, hessianOfGaussianLastEigenvalueMultiArray, 2,
false );
446VIGRA_BLOCKWISE(GaussianGradientMagnitudeFunctor, gaussianGradientMagnitudeMultiArray, 1,
false );
449#undef VIGRA_BLOCKWISE
452template <
unsigned int N,
class T1,
class S1,
class T2,
class S2>
459 gaussianGradientMagnitudeMultiArray(source, dest, options);
Definition array_vector.hxx:514
Definition multi_blockwise.hxx:162
Definition multi_blockwise.hxx:56
BlockwiseOptions & blockShape(MultiArrayIndex blockShape)
Definition multi_blockwise.hxx:134
BlockwiseOptions & blockShape(const TinyVector< T, N > &blockShape)
Definition multi_blockwise.hxx:127
Shape const & getBlockShape() const
Definition multi_blockwise.hxx:71
TinyVector< MultiArrayIndex, N > getBlockShapeN() const
Definition multi_blockwise.hxx:89
BlockwiseOptions & blockShape(const Shape &blockShape)
Definition multi_blockwise.hxx:114
Base class for, and view to, MultiArray.
Definition multi_array.hxx:705
Definition multi_blocking.hxx:157
size_t numBlocks() const
total number of blocks
Definition multi_blocking.hxx:225
ParallelOptions & numThreads(const int n)
Set the number of threads or one of the constants Auto, Nice and NoThreads.
Definition threadpool.hxx:111
int getNumThreads() const
Get desired number of threads.
Definition threadpool.hxx:85
Class for fixed size vectors.
Definition tinyvector.hxx:1008
void gaussianGradientMagnitude(...)
Calculate the gradient magnitude by means of a 1st derivatives of Gaussian filter.
void structureTensorMultiArray(...)
Calculate the structure tensor of a multi-dimensional arrays.
void laplacianOfGaussianMultiArray(...)
Calculate Laplacian of a N-dimensional arrays using Gaussian derivative filters.
void gaussianDivergenceMultiArray(...)
Calculate the divergence of a vector field using Gaussian derivative filters.
void gaussianSmoothMultiArray(...)
Isotropic Gaussian smoothing of a multi-dimensional arrays.
void tensorEigenvaluesMultiArray(...)
Calculate the tensor eigenvalues for every element of a N-D tensor array.
std::ptrdiff_t MultiArrayIndex
Definition multi_fwd.hxx:60
void hessianOfGaussianMultiArray(...)
Calculate Hessian matrix of a N-dimensional arrays using Gaussian derivative filters.
void gaussianGradientMultiArray(...)
Calculate Gaussian gradient of a multi-dimensional arrays.
void symmetricGradientMultiArray(...)
Calculate gradient of a multi-dimensional arrays using symmetric difference filters.
void parallel_foreach(...)
Apply a functor to all items in a range in parallel.